* linux-nat.c (enum sigchld_state): Delete.
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index 061430b74d012f26ea555361a298eb712a0983bb..09c134c6491b560365f83d80e7715f7c1f275f9b 100644 (file)
@@ -1,7 +1,7 @@
-/* Target-vector operations for controlling win32 child processes, for GDB.
+/* Target-vector operations for controlling windows child processes, for GDB.
 
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
@@ -38,6 +38,7 @@
 #include <stdlib.h>
 #include <windows.h>
 #include <imagehlp.h>
+#include <psapi.h>
 #ifdef __CYGWIN__
 #include <sys/cygwin.h>
 #endif
@@ -48,7 +49,6 @@
 #include "objfiles.h"
 #include "gdb_obstack.h"
 #include "gdb_string.h"
-#include "gdb_stdint.h"
 #include "gdbthread.h"
 #include "gdbcmd.h"
 #include <sys/param.h>
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
-#include "i386-cygwin-tdep.h"
-
-static struct target_ops win32_ops;
+#include "windows-tdep.h"
+#include "windows-nat.h"
+
+#define AdjustTokenPrivileges          dyn_AdjustTokenPrivileges
+#define DebugActiveProcessStop         dyn_DebugActiveProcessStop
+#define DebugBreakProcess              dyn_DebugBreakProcess
+#define DebugSetProcessKillOnExit      dyn_DebugSetProcessKillOnExit
+#define EnumProcessModules             dyn_EnumProcessModules
+#define GetModuleFileNameExA           dyn_GetModuleFileNameExA
+#define GetModuleInformation           dyn_GetModuleInformation
+#define LookupPrivilegeValueA          dyn_LookupPrivilegeValueA
+#define OpenProcessToken               dyn_OpenProcessToken
+
+static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
+                                           DWORD, PTOKEN_PRIVILEGES, PDWORD);
+static BOOL WINAPI (*DebugActiveProcessStop) (DWORD);
+static BOOL WINAPI (*DebugBreakProcess) (HANDLE);
+static BOOL WINAPI (*DebugSetProcessKillOnExit) (BOOL);
+static BOOL WINAPI (*EnumProcessModules) (HANDLE, HMODULE *, DWORD,
+                                         LPDWORD);
+static DWORD WINAPI (*GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
+                                           DWORD);
+static BOOL WINAPI (*GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
+                                           DWORD);
+static BOOL WINAPI (*LookupPrivilegeValueA)(LPCSTR, LPCSTR, PLUID);
+static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
+
+static struct target_ops windows_ops;
 
 #ifdef __CYGWIN__
 /* The starting and ending address of the cygwin1.dll text segment. */
-static bfd_vma cygwin_load_start;
-static bfd_vma cygwin_load_end;
+static CORE_ADDR cygwin_load_start;
+static CORE_ADDR cygwin_load_end;
 #endif
 
 static int have_saved_context; /* True if we've saved context from a cygwin signal. */
@@ -84,12 +109,17 @@ enum
     CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
   };
 #endif
-#include <psapi.h>
+
+#ifndef CONTEXT_EXTENDED_REGISTERS
+/* This macro is only defined on ia32.  It only makes sense on this target,
+   so define it as zero if not already defined.  */
+#define CONTEXT_EXTENDED_REGISTERS 0
+#endif
 
 #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
        | CONTEXT_EXTENDED_REGISTERS
 
-static unsigned dr[8];
+static uintptr_t dr[8];
 static int debug_registers_changed;
 static int debug_registers_used;
 #define DR6_CLEAR_VALUE 0xffff0ff0
@@ -106,9 +136,9 @@ static int debug_registers_used;
 #define DEBUG_MEM(x)   if (debug_memory)       printf_unfiltered x
 #define DEBUG_EXCEPT(x)        if (debug_exceptions)   printf_unfiltered x
 
-static void win32_stop (void);
-static int win32_win32_thread_alive (ptid_t);
-static void win32_kill_inferior (void);
+static void windows_stop (ptid_t);
+static int windows_thread_alive (struct target_ops *, ptid_t);
+static void windows_kill_inferior (struct target_ops *);
 
 static enum target_signal last_sig = TARGET_SIGNAL_0;
 /* Set if a signal was received from the debugged process */
@@ -156,11 +186,16 @@ static int debug_memory = 0;              /* show target memory accesses */
 static int debug_exceptions = 0;       /* show target exceptions */
 static int useshell = 0;               /* use shell for subprocesses */
 
-/* This vector maps GDB's idea of a register's number into an address
-   in the win32 exception context vector.
+/* This vector maps GDB's idea of a register's number into an offset
+   in the windows exception context vector.
 
    It also contains the bit mask needed to load the register in question.
 
+   The contents of this table can only be computed by the units
+   that provide CPU-specific support for Windows native debugging.
+   These units should set the table by calling
+   windows_set_context_register_offsets.
+
    One day we could read a reg, we could inspect the context we
    already have loaded, if it doesn't have the bit set that we need,
    we read that set of registers in using GetThreadContext.  If the
@@ -169,55 +204,7 @@ static int useshell = 0;           /* use shell for subprocesses */
    the other regs of the group, and then we copy the info in and set
    out bit. */
 
-#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
-static const int mappings[] =
-{
-  context_offset (Eax),
-  context_offset (Ecx),
-  context_offset (Edx),
-  context_offset (Ebx),
-  context_offset (Esp),
-  context_offset (Ebp),
-  context_offset (Esi),
-  context_offset (Edi),
-  context_offset (Eip),
-  context_offset (EFlags),
-  context_offset (SegCs),
-  context_offset (SegSs),
-  context_offset (SegDs),
-  context_offset (SegEs),
-  context_offset (SegFs),
-  context_offset (SegGs),
-  context_offset (FloatSave.RegisterArea[0 * 10]),
-  context_offset (FloatSave.RegisterArea[1 * 10]),
-  context_offset (FloatSave.RegisterArea[2 * 10]),
-  context_offset (FloatSave.RegisterArea[3 * 10]),
-  context_offset (FloatSave.RegisterArea[4 * 10]),
-  context_offset (FloatSave.RegisterArea[5 * 10]),
-  context_offset (FloatSave.RegisterArea[6 * 10]),
-  context_offset (FloatSave.RegisterArea[7 * 10]),
-  context_offset (FloatSave.ControlWord),
-  context_offset (FloatSave.StatusWord),
-  context_offset (FloatSave.TagWord),
-  context_offset (FloatSave.ErrorSelector),
-  context_offset (FloatSave.ErrorOffset),
-  context_offset (FloatSave.DataSelector),
-  context_offset (FloatSave.DataOffset),
-  context_offset (FloatSave.ErrorSelector)
-  /* XMM0-7 */ ,
-  context_offset (ExtendedRegisters[10*16]),
-  context_offset (ExtendedRegisters[11*16]),
-  context_offset (ExtendedRegisters[12*16]),
-  context_offset (ExtendedRegisters[13*16]),
-  context_offset (ExtendedRegisters[14*16]),
-  context_offset (ExtendedRegisters[15*16]),
-  context_offset (ExtendedRegisters[16*16]),
-  context_offset (ExtendedRegisters[17*16]),
-  /* MXCSR */
-  context_offset (ExtendedRegisters[24])
-};
-
-#undef context_offset
+static const int *mappings;
 
 /* This vector maps the target's idea of an exception (extracted
    from the DEBUG_EVENT structure) to GDB's idea. */
@@ -239,6 +226,15 @@ static const struct xlate_exception
   {STATUS_FLOAT_DIVIDE_BY_ZERO, TARGET_SIGNAL_FPE},
   {-1, -1}};
 
+/* Set the MAPPINGS static global to OFFSETS.
+   See the description of MAPPINGS for more details.  */
+
+void
+windows_set_context_register_offsets (const int *offsets)
+{
+  mappings = offsets;
+}
+
 static void
 check (BOOL ok, const char *file, int line)
 {
@@ -281,11 +277,16 @@ thread_rec (DWORD id, int get_context)
   return NULL;
 }
 
-/* Add a thread to the thread list */
+/* Add a thread to the thread list */
 static thread_info *
-win32_add_thread (DWORD id, HANDLE h)
+windows_add_thread (ptid_t ptid, HANDLE h)
 {
   thread_info *th;
+  DWORD id;
+
+  gdb_assert (ptid_get_tid (ptid) != 0);
+
+  id = ptid_get_tid (ptid);
 
   if ((th = thread_rec (id, FALSE)))
     return th;
@@ -295,8 +296,8 @@ win32_add_thread (DWORD id, HANDLE h)
   th->h = h;
   th->next = thread_head.next;
   thread_head.next = th;
-  add_thread (pid_to_ptid (id));
-  /* Set the debug registers for the new thread in they are used.  */
+  add_thread (ptid);
+  /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
       /* Only change the value of the debug registers.  */
@@ -317,11 +318,11 @@ win32_add_thread (DWORD id, HANDLE h)
 /* Clear out any old thread list and reintialize it to a
    pristine state. */
 static void
-win32_init_thread_list (void)
+windows_init_thread_list (void)
 {
   thread_info *th = &thread_head;
 
-  DEBUG_EVENTS (("gdb: win32_init_thread_list\n"));
+  DEBUG_EVENTS (("gdb: windows_init_thread_list\n"));
   init_thread_list ();
   while (th->next != NULL)
     {
@@ -334,13 +335,18 @@ win32_init_thread_list (void)
 
 /* Delete a thread from the list of threads */
 static void
-win32_delete_thread (DWORD id)
+windows_delete_thread (ptid_t ptid)
 {
   thread_info *th;
+  DWORD id;
+
+  gdb_assert (ptid_get_tid (ptid) != 0);
+
+  id = ptid_get_tid (ptid);
 
   if (info_verbose)
-    printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
-  delete_thread (pid_to_ptid (id));
+    printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
+  delete_thread (ptid);
 
   for (th = &thread_head;
        th->next != NULL && th->next->id != id;
@@ -356,9 +362,11 @@ win32_delete_thread (DWORD id)
 }
 
 static void
-do_win32_fetch_inferior_registers (struct regcache *regcache, int r)
+do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
 {
   char *context_offset = ((char *) &current_thread->context) + mappings[r];
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   long l;
 
   if (!current_thread)
@@ -382,7 +390,7 @@ do_win32_fetch_inferior_registers (struct regcache *regcache, int r)
          thread_info *th = current_thread;
          th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
          GetThreadContext (th->h, &th->context);
-         /* Copy dr values from that thread. 
+         /* Copy dr values from that thread.
             But only if there were not modified since last stop. PR gdb/2388 */
          if (!debug_registers_changed)
            {
@@ -397,14 +405,12 @@ do_win32_fetch_inferior_registers (struct regcache *regcache, int r)
       current_thread->reload_context = 0;
     }
 
-#define I387_ST0_REGNUM I386_ST0_REGNUM
-
-  if (r == I387_FISEG_REGNUM)
+  if (r == I387_FISEG_REGNUM (tdep))
     {
       l = *((long *) context_offset) & 0xffff;
       regcache_raw_supply (regcache, r, (char *) &l);
     }
-  else if (r == I387_FOP_REGNUM)
+  else if (r == I387_FOP_REGNUM (tdep))
     {
       l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
       regcache_raw_supply (regcache, r, (char *) &l);
@@ -413,25 +419,24 @@ do_win32_fetch_inferior_registers (struct regcache *regcache, int r)
     regcache_raw_supply (regcache, r, context_offset);
   else
     {
-      for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
-       do_win32_fetch_inferior_registers (regcache, r);
+      for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
+       do_windows_fetch_inferior_registers (regcache, r);
     }
-
-#undef I387_ST0_REGNUM
 }
 
 static void
-win32_fetch_inferior_registers (struct regcache *regcache, int r)
+windows_fetch_inferior_registers (struct target_ops *ops,
+                                 struct regcache *regcache, int r)
 {
-  current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
+  current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
   /* Check if current_thread exists.  Windows sometimes uses a non-existent
      thread id in its events */
   if (current_thread)
-    do_win32_fetch_inferior_registers (regcache, r);
+    do_windows_fetch_inferior_registers (regcache, r);
 }
 
 static void
-do_win32_store_inferior_registers (const struct regcache *regcache, int r)
+do_windows_store_inferior_registers (const struct regcache *regcache, int r)
 {
   if (!current_thread)
     /* Windows sometimes uses a non-existent thread id in its events */;
@@ -441,34 +446,27 @@ do_win32_store_inferior_registers (const struct regcache *regcache, int r)
   else
     {
       for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
-       do_win32_store_inferior_registers (regcache, r);
+       do_windows_store_inferior_registers (regcache, r);
     }
 }
 
 /* Store a new register value into the current thread context */
 static void
-win32_store_inferior_registers (struct regcache *regcache, int r)
+windows_store_inferior_registers (struct target_ops *ops,
+                                 struct regcache *regcache, int r)
 {
-  current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
+  current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
   /* Check if current_thread exists.  Windows sometimes uses a non-existent
      thread id in its events */
   if (current_thread)
-    do_win32_store_inferior_registers (regcache, r);
+    do_windows_store_inferior_registers (regcache, r);
 }
 
-static int psapi_loaded = 0;
-static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD,
-                                               LPDWORD);
-static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
-                                                 DWORD);
-static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
-                                                  DWORD);
-
 /* Get the name of a given module at at given base address.  If base_address
    is zero return the first loaded module (which is always the name of the
    executable).  */
 static int
-get_module_name (DWORD base_address, char *dll_name_ret)
+get_module_name (LPVOID base_address, char *dll_name_ret)
 {
   DWORD len;
   MODULEINFO mi;
@@ -483,15 +481,10 @@ get_module_name (DWORD base_address, char *dll_name_ret)
   char *pathbuf = dll_name_ret;        /* Just copy directly to passed-in arg */
 #endif
 
-  /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain
-     the needed functions. */
-  if (psapi_loaded <= 0)
-    goto failed;
-
   cbNeeded = 0;
   /* Find size of buffer needed to handle list of modules loaded in inferior */
-  if (!psapi_EnumProcessModules (current_process_handle, DllHandle,
-                                sizeof (HMODULE), &cbNeeded) || !cbNeeded)
+  if (!EnumProcessModules (current_process_handle, DllHandle,
+                          sizeof (HMODULE), &cbNeeded) || !cbNeeded)
     goto failed;
 
   /* Allocate correct amount of space for module list */
@@ -500,22 +493,22 @@ get_module_name (DWORD base_address, char *dll_name_ret)
     goto failed;
 
   /* Get the list of modules */
-  if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
+  if (!EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
                                 &cbNeeded))
     goto failed;
 
   for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
     {
       /* Get information on this module */
-      if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
-                                      &mi, sizeof (mi)))
+      if (!GetModuleInformation (current_process_handle, DllHandle[i],
+                                &mi, sizeof (mi)))
        error (_("Can't get module info"));
 
-      if (!base_address || (DWORD) (mi.lpBaseOfDll) == base_address)
+      if (!base_address || mi.lpBaseOfDll == base_address)
        {
          /* Try to find the name of the given module */
-         len = psapi_GetModuleFileNameExA (current_process_handle,
-                                           DllHandle[i], pathbuf, MAX_PATH);
+         len = GetModuleFileNameExA (current_process_handle,
+                                     DllHandle[i], pathbuf, MAX_PATH);
          if (len == 0)
            error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
 #ifdef __CYGWIN__
@@ -547,7 +540,7 @@ struct safe_symbol_file_add_args
 /* Maintain a linked list of "so" information. */
 struct lm_info
 {
-  DWORD load_addr;
+  LPVOID load_addr;
 };
 
 static struct so_list solib_start, *solib_end;
@@ -558,8 +551,6 @@ static int
 safe_symbol_file_add_stub (void *argv)
 {
 #define p ((struct safe_symbol_file_add_args *) argv)
-  struct so_list *so = &solib_start;
-
   p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
   return !!p->ret;
 #undef p
@@ -608,7 +599,7 @@ safe_symbol_file_add (char *name, int from_tty,
 }
 
 static struct so_list *
-win32_make_so (const char *name, DWORD load_addr)
+windows_make_so (const char *name, LPVOID load_addr)
 {
   struct so_list *so;
   char buf[MAX_PATH + 1];
@@ -673,7 +664,7 @@ win32_make_so (const char *name, DWORD load_addr)
       /* The symbols in a dll are offset by 0x1000, which is the the
         offset from 0 of the first byte in an image - because of the
         file header and the section alignment. */
-      cygwin_load_start = load_addr + 0x1000;
+      cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *) load_addr + 0x1000);
       cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
 
       bfd_close (abfd);
@@ -691,7 +682,7 @@ get_image_name (HANDLE h, void *address, int unicode)
   char *address_ptr;
   int len = 0;
   char b[2];
-  DWORD done;
+  SIZE_T done;
 
   /* Attempt to read the name of the dll that was detected.
      This is documented to work only when actively debugging
@@ -735,7 +726,7 @@ handle_load_dll (void *dummy)
 
   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
-  if (!get_module_name ((DWORD) event->lpBaseOfDll, dll_buf))
+  if (!get_module_name (event->lpBaseOfDll, dll_buf))
     dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
   dll_name = dll_buf;
@@ -746,14 +737,17 @@ handle_load_dll (void *dummy)
   if (!dll_name)
     return 1;
 
-  solib_end->next = win32_make_so (dll_name, (DWORD) event->lpBaseOfDll);
+  solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
   solib_end = solib_end->next;
 
+  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
+                host_address_to_string (solib_end->lm_info->load_addr)));
+
   return 1;
 }
 
 static void
-win32_free_so (struct so_list *so)
+windows_free_so (struct so_list *so)
 {
   if (so->lm_info)
     xfree (so->lm_info);
@@ -763,7 +757,7 @@ win32_free_so (struct so_list *so)
 static int
 handle_unload_dll (void *dummy)
 {
-  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
+  LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
   struct so_list *so;
 
   for (so = &solib_start; so->next != NULL; so = so->next)
@@ -773,19 +767,22 @@ handle_unload_dll (void *dummy)
        so->next = sodel->next;
        if (!so->next)
          solib_end = so;
-       win32_free_so (sodel);
+       DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+
+       windows_free_so (sodel);
        solib_add (NULL, 0, NULL, auto_solib_add);
        return 1;
       }
 
-  error (_("Error: dll starting at 0x%lx not found."), (DWORD) lpBaseOfDll);
+  error (_("Error: dll starting at %s not found."),
+          host_address_to_string (lpBaseOfDll));
 
   return 0;
 }
 
 /* Clear list of loaded DLLs. */
 static void
-win32_clear_solib (void)
+windows_clear_solib (void)
 {
   solib_start.next = NULL;
   solib_end = &solib_start;
@@ -990,8 +987,9 @@ info_w32_command (char *args, int from_tty)
 
 
 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
-  printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \
-  (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress)
+  printf_unfiltered ("gdb: Target exception %s at %s\n", x, \
+    host_address_to_string (\
+      current_event.u.Exception.ExceptionRecord.ExceptionAddress))
 
 static int
 handle_exception (struct target_waitstatus *ourstatus)
@@ -1018,8 +1016,7 @@ handle_exception (struct target_waitstatus *ourstatus)
           and will be sent as a cygwin-specific-signal.  So, ignore SEGVs if they show up
           within the text segment of the DLL itself. */
        char *fn;
-       bfd_vma addr = (bfd_vma) (uintptr_t) current_event.u.Exception.
-                                            ExceptionRecord.ExceptionAddress;
+       CORE_ADDR addr = (CORE_ADDR) (uintptr_t) current_event.u.Exception.ExceptionRecord.ExceptionAddress;
        if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end))
            || (find_pc_partial_function (addr, &fn, NULL, NULL)
                && strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0))
@@ -1103,9 +1100,10 @@ handle_exception (struct target_waitstatus *ourstatus)
       /* Treat unhandled first chance exceptions specially. */
       if (current_event.u.Exception.dwFirstChance)
        return -1;
-      printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
-                   current_event.u.Exception.ExceptionRecord.ExceptionCode,
-       (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
+      printf_unfiltered ("gdb: unknown target exception 0x%08lx at %s\n",
+       current_event.u.Exception.ExceptionRecord.ExceptionCode,
+       host_address_to_string (
+         current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
       break;
     }
@@ -1117,7 +1115,7 @@ handle_exception (struct target_waitstatus *ourstatus)
 /* Resume all artificially suspended threads if we are continuing
    execution */
 static BOOL
-win32_continue (DWORD continue_status, int id)
+windows_continue (DWORD continue_status, int id)
 {
   int i;
   thread_info *th;
@@ -1176,18 +1174,26 @@ fake_create_process (void)
       /*  We can not debug anything in that case.  */
     }
   main_thread_id = current_event.dwThreadId;
-  current_thread = win32_add_thread (main_thread_id,
-                                    current_event.u.CreateThread.hThread);
+  current_thread = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                                  current_event.dwThreadId),
+                                      current_event.u.CreateThread.hThread);
   return main_thread_id;
 }
 
 static void
-win32_resume (ptid_t ptid, int step, enum target_signal sig)
+windows_resume (struct target_ops *ops,
+               ptid_t ptid, int step, enum target_signal sig)
 {
   thread_info *th;
   DWORD continue_status = DBG_CONTINUE;
 
-  int pid = PIDGET (ptid);
+  /* A specific PTID means `step only this thread id'.  */
+  int resume_all = ptid_equal (ptid, minus_one_ptid);
+
+  /* If we're continuing all threads, it's the current inferior that
+     should be handled specially.  */
+  if (resume_all)
+    ptid = inferior_ptid;
 
   if (sig != TARGET_SIGNAL_0)
     {
@@ -1225,18 +1231,19 @@ win32_resume (ptid_t ptid, int step, enum target_signal sig)
 
   last_sig = TARGET_SIGNAL_0;
 
-  DEBUG_EXEC (("gdb: win32_resume (pid=%d, step=%d, sig=%d);\n",
-              pid, step, sig));
+  DEBUG_EXEC (("gdb: windows_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n",
+              ptid_get_pid (ptid), ptid_get_tid (ptid), step, sig));
 
   /* Get context for currently selected thread */
-  th = thread_rec (PIDGET (inferior_ptid), FALSE);
+  th = thread_rec (ptid_get_tid (inferior_ptid), FALSE);
   if (th)
     {
       if (step)
        {
          /* Single step by setting t bit */
-         win32_fetch_inferior_registers (get_current_regcache (),
-                                         gdbarch_ps_regnum (current_gdbarch));
+         windows_fetch_inferior_registers (ops,
+                                           get_current_regcache (),
+                                           gdbarch_ps_regnum (current_gdbarch));
          th->context.EFlags |= FLAG_TRACE_BIT;
        }
 
@@ -1259,21 +1266,49 @@ win32_resume (ptid_t ptid, int step, enum target_signal sig)
   /* Allow continuing with the same signal that interrupted us.
      Otherwise complain. */
 
-  win32_continue (continue_status, pid);
+  if (resume_all)
+    windows_continue (continue_status, -1);
+  else
+    windows_continue (continue_status, ptid_get_tid (ptid));
+}
+
+/* Ctrl-C handler used when the inferior is not run in the same console.  The
+   handler is in charge of interrupting the inferior using DebugBreakProcess.
+   Note that this function is not available prior to Windows XP.  In this case
+   we emit a warning.  */
+BOOL WINAPI
+ctrl_c_handler (DWORD event_type)
+{
+  const int attach_flag = current_inferior ()->attach_flag;
+
+  /* Only handle Ctrl-C event.  Ignore others.  */
+  if (event_type != CTRL_C_EVENT)
+    return FALSE;
+
+  /* If the inferior and the debugger share the same console, do nothing as
+     the inferior has also received the Ctrl-C event.  */
+  if (!new_console && !attach_flag)
+    return TRUE;
+
+  if (!DebugBreakProcess (current_process_handle))
+    warning (_("\
+Could not interrupt program.  Press Ctrl-c in the program console."));
+
+  /* Return true to tell that Ctrl-C has been handled.  */
+  return TRUE;
 }
 
 /* Get the next event from the child.  Return 1 if the event requires
-   handling by WFI (or whatever).
- */
+   handling by WFI (or whatever).  */
 static int
-get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
+get_windows_debug_event (struct target_ops *ops,
+                        int pid, struct target_waitstatus *ourstatus)
 {
   BOOL debug_event;
   DWORD continue_status, event_code;
   thread_info *th;
   static thread_info dummy_thread_info;
   int retval = 0;
-  ptid_t ptid = {-1};
 
   last_sig = TARGET_SIGNAL_0;
 
@@ -1297,21 +1332,24 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
                     "CREATE_THREAD_DEBUG_EVENT"));
       if (saw_create != 1)
        {
-         if (!saw_create && attach_flag)
+         struct inferior *inf;
+         inf = find_inferior_pid (current_event.dwProcessId);
+         if (!saw_create && inf->attach_flag)
            {
              /* Kludge around a Windows bug where first event is a create
                 thread event.  Caused when attached process does not have
                 a main thread. */
-             retval = ourstatus->value.related_pid = fake_create_process ();
-            if (retval)
-              saw_create++;
+             retval = fake_create_process ();
+             if (retval)
+               saw_create++;
            }
          break;
        }
       /* Record the existence of this thread */
-      th = win32_add_thread (current_event.dwThreadId,
-                            current_event.u.CreateThread.hThread);
       retval = current_event.dwThreadId;
+      th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                        current_event.dwThreadId),
+                            current_event.u.CreateThread.hThread);
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
@@ -1321,7 +1359,8 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
                     "EXIT_THREAD_DEBUG_EVENT"));
       if (current_event.dwThreadId != main_thread_id)
        {
-         win32_delete_thread (current_event.dwThreadId);
+         windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                          current_event.dwThreadId));
          th = &dummy_thread_info;
        }
       break;
@@ -1337,12 +1376,14 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       if (main_thread_id)
-       win32_delete_thread (main_thread_id);
+       windows_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                          main_thread_id));
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread */
-      th = win32_add_thread (main_thread_id,
-                            current_event.u.CreateProcessInfo.hThread);
-      retval = ourstatus->value.related_pid = current_event.dwThreadId;
+      th = windows_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                          current_event.dwThreadId),
+                              current_event.u.CreateProcessInfo.hThread);
+      retval = current_event.dwThreadId;
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
@@ -1430,13 +1471,14 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
   if (!retval || saw_create != 1)
     {
       if (continue_status == -1)
-       win32_resume (ptid, 0, 1);
+       windows_resume (ops, minus_one_ptid, 0, 1);
       else
-       CHECK (win32_continue (continue_status, -1));
+       CHECK (windows_continue (continue_status, -1));
     }
   else
     {
-      inferior_ptid = pid_to_ptid (retval);
+      inferior_ptid = ptid_build (current_event.dwProcessId, 0,
+                                 retval);
       current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
     }
 
@@ -1444,11 +1486,12 @@ out:
   return retval;
 }
 
-/* Wait for interesting events to occur in the target process. */
+/* Wait for interesting events to occur in the target process.  */
 static ptid_t
-win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+windows_wait (struct target_ops *ops,
+             ptid_t ptid, struct target_waitstatus *ourstatus)
 {
-  int pid = PIDGET (ptid);
+  int pid = -1;
 
   target_terminal_ours ();
 
@@ -1460,9 +1503,40 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 
   while (1)
     {
-      int retval = get_win32_debug_event (pid, ourstatus);
+      int retval;
+
+      /* If the user presses Ctrl-c while the debugger is waiting
+        for an event, he expects the debugger to interrupt his program
+        and to get the prompt back.  There are two possible situations:
+
+          - The debugger and the program do not share the console, in
+            which case the Ctrl-c event only reached the debugger.
+            In that case, the ctrl_c handler will take care of interrupting
+            the inferior. Note that this case is working starting with
+            Windows XP. For Windows 2000, Ctrl-C should be pressed in the
+            inferior console.
+
+          - The debugger and the program share the same console, in which
+            case both debugger and inferior will receive the Ctrl-c event.
+            In that case the ctrl_c handler will ignore the event, as the
+            Ctrl-c event generated inside the inferior will trigger the
+            expected debug event.
+
+            FIXME: brobecker/2008-05-20: If the inferior receives the
+            signal first and the delay until GDB receives that signal
+            is sufficiently long, GDB can sometimes receive the SIGINT
+            after we have unblocked the CTRL+C handler.  This would
+            lead to the debugger stopping prematurely while handling
+            the new-thread event that comes with the handling of the SIGINT
+            inside the inferior, and then stop again immediately when
+            the user tries to resume the execution in the inferior.
+            This is a classic race that we should try to fix one day.  */
+      SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
+      retval = get_windows_debug_event (ops, pid, ourstatus);
+      SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
+
       if (retval)
-       return pid_to_ptid (retval);
+       return ptid_build (current_event.dwProcessId, 0, retval);
       else
        {
          int detach = 0;
@@ -1471,16 +1545,18 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
            detach = deprecated_ui_loop_hook (0);
 
          if (detach)
-           win32_kill_inferior ();
+           windows_kill_inferior (ops);
        }
     }
 }
 
 static void
-do_initial_win32_stuff (DWORD pid)
+do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
 {
   extern int stop_after_trap;
   int i;
+  struct inferior *inf;
+  struct thread_info *tp;
 
   last_sig = TARGET_SIGNAL_0;
   event_count = 0;
@@ -1495,57 +1571,41 @@ do_initial_win32_stuff (DWORD pid)
 #endif
   current_event.dwProcessId = pid;
   memset (&current_event, 0, sizeof (current_event));
-  push_target (&win32_ops);
+  push_target (ops);
   disable_breakpoints_in_shlibs ();
-  win32_clear_solib ();
+  windows_clear_solib ();
   clear_proceed_status ();
   init_wait_for_inferior ();
 
+  inf = add_inferior (pid);
+  inf->attach_flag = attaching;
+
+  /* Make the new process the current inferior, so terminal handling
+     can rely on it.  When attaching, we don't know about any thread
+     id here, but that's OK --- nothing should be referencing the
+     current thread until we report an event out of windows_wait.  */
+  inferior_ptid = pid_to_ptid (pid);
+
   terminal_init_inferior_with_pgrp (pid);
   target_terminal_inferior ();
 
+  inf->stop_soon = STOP_QUIETLY;
   while (1)
     {
       stop_after_trap = 1;
-      wait_for_inferior ();
-      if (stop_signal != TARGET_SIGNAL_TRAP)
-       resume (0, stop_signal);
+      wait_for_inferior (0);
+      tp = inferior_thread ();
+      if (tp->stop_signal != TARGET_SIGNAL_TRAP)
+       resume (0, tp->stop_signal);
       else
        break;
     }
+
+  inf->stop_soon = NO_STOP_QUIETLY;
   stop_after_trap = 0;
   return;
 }
 
-/* Since Windows XP, detaching from a process is supported by Windows.
-   The following code tries loading the appropriate functions dynamically.
-   If loading these functions succeeds use them to actually detach from
-   the inferior process, otherwise behave as usual, pretending that
-   detach has worked. */
-static BOOL WINAPI (*DebugSetProcessKillOnExit)(BOOL);
-static BOOL WINAPI (*DebugActiveProcessStop)(DWORD);
-
-static int
-has_detach_ability (void)
-{
-  static HMODULE kernel32 = NULL;
-
-  if (!kernel32)
-    kernel32 = LoadLibrary ("kernel32.dll");
-  if (kernel32)
-    {
-      if (!DebugSetProcessKillOnExit)
-       DebugSetProcessKillOnExit = GetProcAddress (kernel32,
-                                                "DebugSetProcessKillOnExit");
-      if (!DebugActiveProcessStop)
-       DebugActiveProcessStop = GetProcAddress (kernel32,
-                                                "DebugActiveProcessStop");
-      if (DebugSetProcessKillOnExit && DebugActiveProcessStop)
-       return 1;
-    }
-  return 0;
-}
-
 /* Try to set or remove a user privilege to the current process.  Return -1
    if that fails, the previous setting of that privilege otherwise.
 
@@ -1555,46 +1615,18 @@ has_detach_ability (void)
 static int
 set_process_privilege (const char *privilege, BOOL enable)
 {
-  static HMODULE advapi32 = NULL;
-  static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE);
-  static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID);
-  static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES,
-                                             DWORD, PTOKEN_PRIVILEGES, PDWORD);
-
   HANDLE token_hdl = NULL;
   LUID restore_priv;
   TOKEN_PRIVILEGES new_priv, orig_priv;
   int ret = -1;
   DWORD size;
 
-  if (GetVersion () >= 0x80000000)  /* No security availbale on 9x/Me */
-    return 0;
-
-  if (!advapi32)
-    {
-      if (!(advapi32 = LoadLibrary ("advapi32.dll")))
-       goto out;
-      if (!OpenProcessToken)
-       OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken");
-      if (!LookupPrivilegeValue)
-       LookupPrivilegeValue = GetProcAddress (advapi32,
-                                              "LookupPrivilegeValueA");
-      if (!AdjustTokenPrivileges)
-       AdjustTokenPrivileges = GetProcAddress (advapi32,
-                                               "AdjustTokenPrivileges");
-      if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
-       {
-         advapi32 = NULL;
-         goto out;
-       }
-    }
-
   if (!OpenProcessToken (GetCurrentProcess (),
                         TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
                         &token_hdl))
     goto out;
 
-  if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
+  if (!LookupPrivilegeValueA (NULL, privilege, &restore_priv))
     goto out;
 
   new_priv.PrivilegeCount = 1;
@@ -1607,7 +1639,7 @@ set_process_privilege (const char *privilege, BOOL enable)
 #if 0
   /* Disabled, otherwise every `attach' in an unprivileged user session
      would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
-     win32_attach(). */
+     windows_attach(). */
   /* AdjustTokenPrivileges returns TRUE even if the privilege could not
      be enabled. GetLastError () returns an correct error code, though. */
   if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
@@ -1625,7 +1657,7 @@ out:
 
 /* Attach to process PID, then initialize for debugging it.  */
 static void
-win32_attach (char *args, int from_tty)
+windows_attach (struct target_ops *ops, char *args, int from_tty)
 {
   BOOL ok;
   DWORD pid;
@@ -1641,7 +1673,7 @@ win32_attach (char *args, int from_tty)
 
   pid = strtoul (args, 0, 0);          /* Windows pid */
 
-  win32_init_thread_list ();
+  windows_init_thread_list ();
   ok = DebugActiveProcess (pid);
   saw_create = 0;
 
@@ -1659,10 +1691,7 @@ win32_attach (char *args, int from_tty)
   if (!ok)
     error (_("Can't attach to process."));
 
-  if (has_detach_ability ())
-    DebugSetProcessKillOnExit (FALSE);
-
-  attach_flag = 1;
+  DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
@@ -1678,28 +1707,26 @@ win32_attach (char *args, int from_tty)
       gdb_flush (gdb_stdout);
     }
 
-  do_initial_win32_stuff (pid);
+  do_initial_windows_stuff (ops, pid, 1);
   target_terminal_ours ();
 }
 
 static void
-win32_detach (char *args, int from_tty)
+windows_detach (struct target_ops *ops, char *args, int from_tty)
 {
   int detached = 1;
 
-  if (has_detach_ability ())
-    {
-      ptid_t ptid = {-1};
-      win32_resume (ptid, 0, TARGET_SIGNAL_0);
+  ptid_t ptid = {-1};
+  windows_resume (ops, ptid, 0, TARGET_SIGNAL_0);
 
-      if (!DebugActiveProcessStop (current_event.dwProcessId))
-       {
-         error (_("Can't detach process %lu (error %lu)"),
-                current_event.dwProcessId, GetLastError ());
-         detached = 0;
-       }
-      DebugSetProcessKillOnExit (FALSE);
+  if (!DebugActiveProcessStop (current_event.dwProcessId))
+    {
+      error (_("Can't detach process %lu (error %lu)"),
+            current_event.dwProcessId, GetLastError ());
+      detached = 0;
     }
+  DebugSetProcessKillOnExit (FALSE);
+
   if (detached && from_tty)
     {
       char *exec_file = get_exec_file (0);
@@ -1709,12 +1736,15 @@ win32_detach (char *args, int from_tty)
                         current_event.dwProcessId);
       gdb_flush (gdb_stdout);
     }
+
   inferior_ptid = null_ptid;
-  unpush_target (&win32_ops);
+  detach_inferior (current_event.dwProcessId);
+
+  unpush_target (ops);
 }
 
 static char *
-win32_pid_to_exec_file (int pid)
+windows_pid_to_exec_file (int pid)
 {
   static char path[MAX_PATH + 1];
 
@@ -1722,7 +1752,7 @@ win32_pid_to_exec_file (int pid)
   /* Try to find exe name as symlink target of /proc/<pid>/exe */
   int nchars;
   char procexe[sizeof ("/proc/4294967295/exe")];
-  sprintf (procexe, "/proc/%lu/exe", current_event.dwProcessId);
+  sprintf (procexe, "/proc/%u/exe", pid);
   nchars = readlink (procexe, path, sizeof(path));
   if (nchars > 0 && nchars < sizeof (path))
     {
@@ -1742,26 +1772,29 @@ win32_pid_to_exec_file (int pid)
 /* Print status information about what we're accessing.  */
 
 static void
-win32_files_info (struct target_ops *ignore)
+windows_files_info (struct target_ops *ignore)
 {
+  struct inferior *inf = current_inferior ();
+
   printf_unfiltered ("\tUsing the running image of %s %s.\n",
-      attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
+                    inf->attach_flag ? "attached" : "child",
+                    target_pid_to_str (inferior_ptid));
 }
 
 static void
-win32_open (char *arg, int from_tty)
+windows_open (char *arg, int from_tty)
 {
   error (_("Use the \"run\" command to start a Unix child process."));
 }
 
-/* Start an inferior win32 child process and sets inferior_ptid to its pid.
+/* Start an inferior windows child process and sets inferior_ptid to its pid.
    EXEC_FILE is the file to run.
    ALLARGS is a string containing the arguments to the program.
    ENV is the environment vector to pass.  Errors reported with error().  */
 
 static void
-win32_create_inferior (char *exec_file, char *allargs, char **in_env,
-                      int from_tty)
+windows_create_inferior (struct target_ops *ops, char *exec_file,
+                      char *allargs, char **in_env, int from_tty)
 {
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
@@ -1772,8 +1805,12 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
   char *toexec;
   char shell[MAX_PATH + 1]; /* Path to shell */
   const char *sh;
+#ifdef __CYGWIN__
   int tty;
   int ostdin, ostdout, ostderr;
+#else
+  HANDLE tty;
+#endif
   const char *inferior_io_terminal = get_inferior_io_terminal ();
 
   if (!exec_file)
@@ -1814,8 +1851,6 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
   if (new_console)
     flags |= CREATE_NEW_CONSOLE;
 
-  attach_flag = 0;
-
   args = alloca (strlen (toexec) + strlen (allargs) + 2);
   strcpy (args, toexec);
   strcat (args, " ");
@@ -1845,9 +1880,31 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
          dup2 (tty, 2);
        }
     }
+#else
+  if (!inferior_io_terminal)
+    tty = INVALID_HANDLE_VALUE;
+  else
+    {
+      SECURITY_ATTRIBUTES sa;
+      sa.nLength = sizeof(sa);
+      sa.lpSecurityDescriptor = 0;
+      sa.bInheritHandle = TRUE;
+      tty = CreateFileA (inferior_io_terminal, GENERIC_READ | GENERIC_WRITE,
+                        0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+      if (tty == INVALID_HANDLE_VALUE)
+       warning (_("Warning: Failed to open TTY %s, error %#x."),
+                inferior_io_terminal, (unsigned) GetLastError ());
+      else
+       {
+         si.hStdInput = tty;
+         si.hStdOutput = tty;
+         si.hStdError = tty;
+         si.dwFlags |= STARTF_USESTDHANDLES;
+       }
+    }
 #endif
 
-  win32_init_thread_list ();
+  windows_init_thread_list ();
   ret = CreateProcess (0,
                       args,    /* command line */
                       NULL,    /* Security */
@@ -1870,6 +1927,9 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
       close (ostdout);
       close (ostderr);
     }
+#else
+  if (tty != INVALID_HANDLE_VALUE)
+    CloseHandle (tty);
 #endif
 
   if (!ret)
@@ -1884,22 +1944,22 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
   else
     saw_create = 0;
 
-  do_initial_win32_stuff (pi.dwProcessId);
+  do_initial_windows_stuff (ops, pi.dwProcessId, 0);
 
-  /* win32_continue (DBG_CONTINUE, -1); */
+  /* windows_continue (DBG_CONTINUE, -1); */
 }
 
 static void
-win32_mourn_inferior (void)
+windows_mourn_inferior (struct target_ops *ops)
 {
-  (void) win32_continue (DBG_CONTINUE, -1);
+  (void) windows_continue (DBG_CONTINUE, -1);
   i386_cleanup_dregs();
   if (open_process_used)
     {
       CHECK (CloseHandle (current_process_handle));
       open_process_used = 0;
     }
-  unpush_target (&win32_ops);
+  unpush_target (ops);
   generic_mourn_inferior ();
 }
 
@@ -1907,7 +1967,7 @@ win32_mourn_inferior (void)
    ^C on the controlling terminal. */
 
 static void
-win32_stop (void)
+windows_stop (ptid_t ptid)
 {
   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
   CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
@@ -1915,27 +1975,27 @@ win32_stop (void)
 }
 
 static int
-win32_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
+windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
                   int write, struct mem_attrib *mem,
                   struct target_ops *target)
 {
-  DWORD done = 0;
+  SIZE_T done = 0;
   if (write)
     {
       DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
                  len, (DWORD) (uintptr_t) memaddr));
-      if (!WriteProcessMemory (current_process_handle, 
+      if (!WriteProcessMemory (current_process_handle,
                               (LPVOID) (uintptr_t) memaddr, our,
                               len, &done))
        done = 0;
-      FlushInstructionCache (current_process_handle, 
+      FlushInstructionCache (current_process_handle,
                             (LPCVOID) (uintptr_t) memaddr, len);
     }
   else
     {
       DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
                  len, (DWORD) (uintptr_t) memaddr));
-      if (!ReadProcessMemory (current_process_handle, 
+      if (!ReadProcessMemory (current_process_handle,
                              (LPCVOID) (uintptr_t) memaddr, our,
                              len, &done))
        done = 0;
@@ -1944,13 +2004,13 @@ win32_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
 }
 
 static void
-win32_kill_inferior (void)
+windows_kill_inferior (struct target_ops *ops)
 {
   CHECK (TerminateProcess (current_process_handle, 0));
 
   for (;;)
     {
-      if (!win32_continue (DBG_CONTINUE, -1))
+      if (!windows_continue (DBG_CONTINUE, -1))
        break;
       if (!WaitForDebugEvent (&current_event, INFINITE))
        break;
@@ -1958,44 +2018,46 @@ win32_kill_inferior (void)
        break;
     }
 
-  target_mourn_inferior ();    /* or just win32_mourn_inferior? */
+  target_mourn_inferior ();    /* or just windows_mourn_inferior? */
 }
 
 static void
-win32_prepare_to_store (struct regcache *regcache)
+windows_prepare_to_store (struct regcache *regcache)
 {
   /* Do nothing, since we can store individual regs */
 }
 
 static int
-win32_can_run (void)
+windows_can_run (void)
 {
   return 1;
 }
 
 static void
-win32_close (int x)
+windows_close (int x)
 {
-  DEBUG_EVENTS (("gdb: win32_close, inferior_ptid=%d\n",
+  DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
                PIDGET (inferior_ptid)));
 }
 
 /* Convert pid to printable format. */
 static char *
-win32_pid_to_str (ptid_t ptid)
+windows_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   static char buf[80];
-  int pid = PIDGET (ptid);
 
-  if ((DWORD) pid == current_event.dwProcessId)
-    sprintf (buf, "process %d", pid);
-  else
-    sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
-  return buf;
+  if (ptid_get_tid (ptid) != 0)
+    {
+      snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
+               ptid_get_pid (ptid), ptid_get_tid (ptid));
+      return buf;
+    }
+
+  return normal_pid_to_str (ptid);
 }
 
 static LONGEST
-win32_xfer_shared_libraries (struct target_ops *ops,
+windows_xfer_shared_libraries (struct target_ops *ops,
                             enum target_object object, const char *annex,
                             gdb_byte *readbuf, const gdb_byte *writebuf,
                             ULONGEST offset, LONGEST len)
@@ -2011,7 +2073,8 @@ win32_xfer_shared_libraries (struct target_ops *ops,
   obstack_init (&obstack);
   obstack_grow_str (&obstack, "<library-list>\n");
   for (so = solib_start.next; so; so = so->next)
-    win32_xfer_shared_library (so->so_name, so->lm_info->load_addr, &obstack);
+    windows_xfer_shared_library (so->so_name, (CORE_ADDR) (uintptr_t) so->lm_info->load_addr,
+                                &obstack);
   obstack_grow_str0 (&obstack, "</library-list>\n");
 
   buf = obstack_finish (&obstack);
@@ -2028,7 +2091,7 @@ win32_xfer_shared_libraries (struct target_ops *ops,
 }
 
 static LONGEST
-win32_xfer_partial (struct target_ops *ops, enum target_object object,
+windows_xfer_partial (struct target_ops *ops, enum target_object object,
                    const char *annex, gdb_byte *readbuf,
                    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
@@ -2037,14 +2100,14 @@ win32_xfer_partial (struct target_ops *ops, enum target_object object,
     case TARGET_OBJECT_MEMORY:
       if (readbuf)
        return (*ops->deprecated_xfer_memory) (offset, readbuf,
-                                              len, 0/*write*/, NULL, ops);
+                                              len, 0/*read*/, NULL, ops);
       if (writebuf)
        return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
                                               len, 1/*write*/, NULL, ops);
       return -1;
 
     case TARGET_OBJECT_LIBRARIES:
-      return win32_xfer_shared_libraries (ops, object, annex, readbuf,
+      return windows_xfer_shared_libraries (ops, object, annex, readbuf,
                                          writebuf, offset, len);
 
     default:
@@ -2055,61 +2118,71 @@ win32_xfer_partial (struct target_ops *ops, enum target_object object,
     }
 }
 
+static ptid_t
+windows_get_ada_task_ptid (long lwp, long thread)
+{
+  return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
+}
+
 static void
-init_win32_ops (void)
-{
-  win32_ops.to_shortname = "child";
-  win32_ops.to_longname = "Win32 child process";
-  win32_ops.to_doc = "Win32 child process (started by the \"run\" command).";
-  win32_ops.to_open = win32_open;
-  win32_ops.to_close = win32_close;
-  win32_ops.to_attach = win32_attach;
-  win32_ops.to_detach = win32_detach;
-  win32_ops.to_resume = win32_resume;
-  win32_ops.to_wait = win32_wait;
-  win32_ops.to_fetch_registers = win32_fetch_inferior_registers;
-  win32_ops.to_store_registers = win32_store_inferior_registers;
-  win32_ops.to_prepare_to_store = win32_prepare_to_store;
-  win32_ops.deprecated_xfer_memory = win32_xfer_memory;
-  win32_ops.to_xfer_partial = win32_xfer_partial;
-  win32_ops.to_files_info = win32_files_info;
-  win32_ops.to_insert_breakpoint = memory_insert_breakpoint;
-  win32_ops.to_remove_breakpoint = memory_remove_breakpoint;
-  win32_ops.to_terminal_init = terminal_init_inferior;
-  win32_ops.to_terminal_inferior = terminal_inferior;
-  win32_ops.to_terminal_ours_for_output = terminal_ours_for_output;
-  win32_ops.to_terminal_ours = terminal_ours;
-  win32_ops.to_terminal_save_ours = terminal_save_ours;
-  win32_ops.to_terminal_info = child_terminal_info;
-  win32_ops.to_kill = win32_kill_inferior;
-  win32_ops.to_create_inferior = win32_create_inferior;
-  win32_ops.to_mourn_inferior = win32_mourn_inferior;
-  win32_ops.to_can_run = win32_can_run;
-  win32_ops.to_thread_alive = win32_win32_thread_alive;
-  win32_ops.to_pid_to_str = win32_pid_to_str;
-  win32_ops.to_stop = win32_stop;
-  win32_ops.to_stratum = process_stratum;
-  win32_ops.to_has_all_memory = 1;
-  win32_ops.to_has_memory = 1;
-  win32_ops.to_has_stack = 1;
-  win32_ops.to_has_registers = 1;
-  win32_ops.to_has_execution = 1;
-  win32_ops.to_magic = OPS_MAGIC;
-  win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file;
+init_windows_ops (void)
+{
+  windows_ops.to_shortname = "child";
+  windows_ops.to_longname = "Win32 child process";
+  windows_ops.to_doc = "Win32 child process (started by the \"run\" command).";
+  windows_ops.to_open = windows_open;
+  windows_ops.to_close = windows_close;
+  windows_ops.to_attach = windows_attach;
+  windows_ops.to_attach_no_wait = 1;
+  windows_ops.to_detach = windows_detach;
+  windows_ops.to_resume = windows_resume;
+  windows_ops.to_wait = windows_wait;
+  windows_ops.to_fetch_registers = windows_fetch_inferior_registers;
+  windows_ops.to_store_registers = windows_store_inferior_registers;
+  windows_ops.to_prepare_to_store = windows_prepare_to_store;
+  windows_ops.deprecated_xfer_memory = windows_xfer_memory;
+  windows_ops.to_xfer_partial = windows_xfer_partial;
+  windows_ops.to_files_info = windows_files_info;
+  windows_ops.to_insert_breakpoint = memory_insert_breakpoint;
+  windows_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  windows_ops.to_terminal_init = terminal_init_inferior;
+  windows_ops.to_terminal_inferior = terminal_inferior;
+  windows_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+  windows_ops.to_terminal_ours = terminal_ours;
+  windows_ops.to_terminal_save_ours = terminal_save_ours;
+  windows_ops.to_terminal_info = child_terminal_info;
+  windows_ops.to_kill = windows_kill_inferior;
+  windows_ops.to_create_inferior = windows_create_inferior;
+  windows_ops.to_mourn_inferior = windows_mourn_inferior;
+  windows_ops.to_can_run = windows_can_run;
+  windows_ops.to_thread_alive = windows_thread_alive;
+  windows_ops.to_pid_to_str = windows_pid_to_str;
+  windows_ops.to_stop = windows_stop;
+  windows_ops.to_stratum = process_stratum;
+  windows_ops.to_has_all_memory = 1;
+  windows_ops.to_has_memory = 1;
+  windows_ops.to_has_stack = 1;
+  windows_ops.to_has_registers = 1;
+  windows_ops.to_has_execution = 1;
+  windows_ops.to_pid_to_exec_file = windows_pid_to_exec_file;
+  windows_ops.to_get_ada_task_ptid = windows_get_ada_task_ptid;
+  i386_use_watchpoints (&windows_ops);
+
+  windows_ops.to_magic = OPS_MAGIC;
 }
 
 static void
-set_win32_aliases (char *argv0)
+set_windows_aliases (char *argv0)
 {
   add_info_alias ("dll", "sharedlibrary", 1);
 }
 
 void
-_initialize_win32_nat (void)
+_initialize_windows_nat (void)
 {
   struct cmd_list_element *c;
 
-  init_win32_ops ();
+  init_windows_ops ();
 
   c = add_com ("dll-symbols", class_files, dll_symbol_command,
               _("Load dll library symbols from FILE."));
@@ -2183,29 +2256,29 @@ Show whether to display kernel exceptions in child process."), NULL,
   add_cmd ("selector", class_info, display_selectors,
           _("Display selectors infos."),
           &info_w32_cmdlist);
-  add_target (&win32_ops);
-  deprecated_init_ui_hook = set_win32_aliases;
+  add_target (&windows_ops);
+  deprecated_init_ui_hook = set_windows_aliases;
 }
 
 /* Hardware watchpoint support, adapted from go32-nat.c code.  */
 
 /* Pass the address ADDR to the inferior in the I'th debug register.
    Here we just store the address in dr array, the registers will be
-   actually set up when win32_continue is called.  */
+   actually set up when windows_continue is called.  */
 void
 cygwin_set_dr (int i, CORE_ADDR addr)
 {
   if (i < 0 || i > 3)
     internal_error (__FILE__, __LINE__,
                    _("Invalid register %d in cygwin_set_dr.\n"), i);
-  dr[i] = (unsigned) addr;
+  dr[i] = addr;
   debug_registers_changed = 1;
   debug_registers_used = 1;
 }
 
 /* Pass the value VAL to the inferior in the DR7 debug control
    register.  Here we just store the address in D_REGS, the watchpoint
-   will be actually set up in win32_wait.  */
+   will be actually set up in windows_wait.  */
 void
 cygwin_set_dr7 (unsigned val)
 {
@@ -2223,15 +2296,18 @@ cygwin_get_dr6 (void)
   return dr[6];
 }
 
-/* Determine if the thread referenced by "pid" is alive
+/* Determine if the thread referenced by "ptid" is alive
    by "polling" it.  If WaitForSingleObject returns WAIT_OBJECT_0
-   it means that the pid has died.  Otherwise it is assumed to be alive. */
+   it means that the thread has died.  Otherwise it is assumed to be alive. */
 static int
-win32_win32_thread_alive (ptid_t ptid)
+windows_thread_alive (struct target_ops *ops, ptid_t ptid)
 {
-  int pid = PIDGET (ptid);
+  int tid;
+
+  gdb_assert (ptid_get_tid (ptid) != 0);
+  tid = ptid_get_tid (ptid);
 
-  return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
+  return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
     FALSE : TRUE;
 }
 
@@ -2264,33 +2340,110 @@ _initialize_check_for_gdb_ini (void)
     }
 }
 
+/* Define dummy functions which always return error for the rare cases where
+   these functions could not be found. */
+static BOOL WINAPI
+bad_DebugActiveProcessStop (DWORD w)
+{
+  return FALSE;
+}
+static BOOL WINAPI
+bad_DebugBreakProcess (HANDLE w)
+{
+  return FALSE;
+}
+static BOOL WINAPI
+bad_DebugSetProcessKillOnExit (BOOL w)
+{
+  return FALSE;
+}
+static BOOL WINAPI
+bad_EnumProcessModules (HANDLE w, HMODULE *x, DWORD y, LPDWORD z)
+{
+  return FALSE;
+}
+static DWORD WINAPI
+bad_GetModuleFileNameExA (HANDLE w, HMODULE x, LPSTR y, DWORD z)
+{
+  return 0;
+}
+static BOOL WINAPI
+bad_GetModuleInformation (HANDLE w, HMODULE x, LPMODULEINFO y, DWORD z)
+{
+  return FALSE;
+}
+
+static BOOL WINAPI
+bad_OpenProcessToken (HANDLE w, DWORD x, PHANDLE y)
+{
+  return FALSE;
+}
+
+/* Load any functions which may not be available in ancient versions
+   of Windows. */
 void
-_initialize_psapi (void)
+_initialize_loadable (void)
 {
+  HMODULE hm = NULL;
+
+  hm = LoadLibrary ("kernel32.dll");
+  if (hm)
+    {
+      dyn_DebugActiveProcessStop = (void *)
+       GetProcAddress (hm, "DebugActiveProcessStop");
+      dyn_DebugBreakProcess = (void *)
+       GetProcAddress (hm, "DebugBreakProcess");
+      dyn_DebugSetProcessKillOnExit = (void *)
+       GetProcAddress (hm, "DebugSetProcessKillOnExit");
+    }
+
+  /* Set variables to dummy versions of these processes if the function
+     wasn't found in kernel32.dll. */
+  if (!dyn_DebugBreakProcess)
+    dyn_DebugBreakProcess = bad_DebugBreakProcess;
+  if (!dyn_DebugActiveProcessStop || !dyn_DebugSetProcessKillOnExit)
+    {
+      dyn_DebugActiveProcessStop = bad_DebugActiveProcessStop;
+      dyn_DebugSetProcessKillOnExit = bad_DebugSetProcessKillOnExit;
+    }
+
   /* Load optional functions used for retrieving filename information
      associated with the currently debugged process or its dlls. */
-  if (!psapi_loaded)
+  hm = LoadLibrary ("psapi.dll");
+  if (hm)
     {
-      HMODULE psapi_module_handle;
-
-      psapi_loaded = -1;
+      dyn_EnumProcessModules = (void *)
+       GetProcAddress (hm, "EnumProcessModules");
+      dyn_GetModuleInformation = (void *)
+       GetProcAddress (hm, "GetModuleInformation");
+      dyn_GetModuleFileNameExA = (void *)
+       GetProcAddress (hm, "GetModuleFileNameExA");
+    }
 
-      psapi_module_handle = LoadLibrary ("psapi.dll");
-      if (psapi_module_handle)
-       {
-         psapi_EnumProcessModules = (void *) GetProcAddress (psapi_module_handle, "EnumProcessModules");
-         psapi_GetModuleInformation = (void *) GetProcAddress (psapi_module_handle, "GetModuleInformation");
-         psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle, "GetModuleFileNameExA");
-
-         if (psapi_EnumProcessModules != NULL
-             && psapi_GetModuleInformation != NULL
-             && psapi_GetModuleFileNameExA != NULL)
-           psapi_loaded = 1;
-       }
+  if (!dyn_EnumProcessModules || !dyn_GetModuleInformation || !dyn_GetModuleFileNameExA)
+    {
+      /* Set variables to dummy versions of these processes if the function
+        wasn't found in psapi.dll. */
+      dyn_EnumProcessModules = bad_EnumProcessModules;
+      dyn_GetModuleInformation = bad_GetModuleInformation;
+      dyn_GetModuleFileNameExA = bad_GetModuleFileNameExA;
+      /* This will probably fail on Windows 9x/Me.  Let the user know that we're
+        missing some functionality. */
+      warning(_("cannot automatically find executable file or library to read symbols.\nUse \"file\" or \"dll\" command to load executable/libraries directly."));
     }
 
-  /* This will probably fail on Windows 9x/Me.  Let the user know that we're
-     missing some functionality. */
-  if (psapi_loaded < 0)
-    warning(_("cannot automatically find executable file or library to read symbols.  Use \"file\" or \"dll\" command to load executable/libraries directly."));
+  hm = LoadLibrary ("advapi32.dll");
+  if (hm)
+    {
+      dyn_OpenProcessToken = (void *)
+       GetProcAddress (hm, "OpenProcessToken");
+      dyn_LookupPrivilegeValueA = (void *)
+       GetProcAddress (hm, "LookupPrivilegeValueA");
+      dyn_AdjustTokenPrivileges = (void *)
+       GetProcAddress (hm, "AdjustTokenPrivileges");
+      /* Only need to set one of these since if OpenProcessToken fails nothing
+        else is needed. */
+      if (!dyn_OpenProcessToken || !dyn_LookupPrivilegeValueA || !dyn_AdjustTokenPrivileges)
+       dyn_OpenProcessToken = bad_OpenProcessToken;
+    }
 }
This page took 0.068339 seconds and 4 git commands to generate.