bfd/
[deliverable/binutils-gdb.git] / gdb / win32-nat.c
index 67082fada4645126f254e743f14e63f7a77cce75..9a1a28cfd56ecaf309ccfe1a0df8dd65de4db6cf 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-vector operations for controlling win32 child processes, for GDB.
 
    Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-   2005, 2006, 2007 Free Software Foundation, Inc.
+   2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
@@ -60,7 +60,8 @@
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
-#include "i386-cygwin-tdep.h"
+#include "win32-tdep.h"
+#include "win32-nat.h"
 
 static struct target_ops win32_ops;
 
@@ -85,6 +86,12 @@ enum
 #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
 
@@ -105,7 +112,7 @@ 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 void win32_stop (ptid_t);
 static int win32_win32_thread_alive (ptid_t);
 static void win32_kill_inferior (void);
 
@@ -141,6 +148,7 @@ static DWORD main_thread_id;                /* Thread ID of the main thread */
 static int exception_count = 0;
 static int event_count = 0;
 static int saw_create;
+static int open_process_used = 0;
 
 /* User options. */
 static int new_console = 0;
@@ -154,11 +162,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
+/* This vector maps GDB's idea of a register's number into an offset
    in the win32 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
+   win32_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
@@ -167,55 +180,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. */
@@ -237,6 +202,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
+win32_set_context_register_offsets (const int *offsets)
+{
+  mappings = offsets;
+}
+
 static void
 check (BOOL ok, const char *file, int line)
 {
@@ -279,11 +253,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)
+win32_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;
@@ -293,8 +272,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.  */
@@ -325,7 +304,6 @@ win32_init_thread_list (void)
     {
       thread_info *here = th->next;
       th->next = here->next;
-      (void) CloseHandle (here->h);
       xfree (here);
     }
   thread_head.next = NULL;
@@ -333,13 +311,18 @@ win32_init_thread_list (void)
 
 /* Delete a thread from the list of threads */
 static void
-win32_delete_thread (DWORD id)
+win32_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;
@@ -350,7 +333,6 @@ win32_delete_thread (DWORD id)
     {
       thread_info *here = th->next;
       th->next = here->next;
-      CloseHandle (here->h);
       xfree (here);
     }
 }
@@ -359,6 +341,8 @@ static void
 do_win32_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,25 +366,27 @@ 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.  */
-         dr[0] = th->context.Dr0;
-         dr[1] = th->context.Dr1;
-         dr[2] = th->context.Dr2;
-         dr[3] = th->context.Dr3;
-         dr[6] = th->context.Dr6;
-         dr[7] = th->context.Dr7;
+         /* Copy dr values from that thread. 
+            But only if there were not modified since last stop. PR gdb/2388 */
+         if (!debug_registers_changed)
+           {
+             dr[0] = th->context.Dr0;
+             dr[1] = th->context.Dr1;
+             dr[2] = th->context.Dr2;
+             dr[3] = th->context.Dr3;
+             dr[6] = th->context.Dr6;
+             dr[7] = th->context.Dr7;
+           }
        }
       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);
@@ -409,17 +395,15 @@ 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++)
+      for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
        do_win32_fetch_inferior_registers (regcache, r);
     }
-
-#undef I387_ST0_REGNUM
 }
 
 static void
 win32_fetch_inferior_registers (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)
@@ -445,7 +429,7 @@ do_win32_store_inferior_registers (const struct regcache *regcache, int r)
 static void
 win32_store_inferior_registers (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)
@@ -453,88 +437,78 @@ win32_store_inferior_registers (struct regcache *regcache, int r)
 }
 
 static int psapi_loaded = 0;
-static HMODULE psapi_module_handle = NULL;
-static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
-static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
-static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
-
+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
-psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+get_module_name (LPVOID base_address, char *dll_name_ret)
 {
   DWORD len;
   MODULEINFO mi;
   int i;
   HMODULE dh_buf[1];
-  HMODULE *DllHandle = dh_buf;
+  HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
   DWORD cbNeeded;
-  BOOL ok;
+#ifdef __CYGWIN__
+  char pathbuf[PATH_MAX + 1];  /* Temporary storage prior to converting to
+                                  posix form */
+#else
+  char *pathbuf = dll_name_ret;        /* Just copy directly to passed-in arg */
+#endif
 
-  if (!psapi_loaded ||
-      psapi_EnumProcessModules == NULL ||
-      psapi_GetModuleInformation == NULL ||
-      psapi_GetModuleFileNameExA == NULL)
-    {
-      if (psapi_loaded)
-       goto failed;
-      psapi_loaded = 1;
-      psapi_module_handle = LoadLibrary ("psapi.dll");
-      if (!psapi_module_handle)
-       {
-         /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
-         goto failed;
-       }
-      psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
-      psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
-      psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
-                                                   "GetModuleFileNameExA");
-      if (psapi_EnumProcessModules == NULL ||
-         psapi_GetModuleInformation == NULL ||
-         psapi_GetModuleFileNameExA == NULL)
-       goto failed;
-    }
+  /* 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;
-  ok = (*psapi_EnumProcessModules) (current_process_handle,
-                                   DllHandle,
-                                   sizeof (HMODULE),
-                                   &cbNeeded);
-
-  if (!ok || !cbNeeded)
+  /* Find size of buffer needed to handle list of modules loaded in inferior */
+  if (!psapi_EnumProcessModules (current_process_handle, DllHandle,
+                                sizeof (HMODULE), &cbNeeded) || !cbNeeded)
     goto failed;
 
+  /* Allocate correct amount of space for module list */
   DllHandle = (HMODULE *) alloca (cbNeeded);
   if (!DllHandle)
     goto failed;
 
-  ok = (*psapi_EnumProcessModules) (current_process_handle,
-                                   DllHandle,
-                                   cbNeeded,
-                                   &cbNeeded);
-  if (!ok)
+  /* Get the list of modules */
+  if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
+                                &cbNeeded))
     goto failed;
 
   for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
     {
-      if (!(*psapi_GetModuleInformation) (current_process_handle,
-                                         DllHandle[i],
-                                         &mi,
-                                         sizeof (mi)))
+      /* Get information on this module */
+      if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
+                                      &mi, sizeof (mi)))
        error (_("Can't get module info"));
 
-      len = (*psapi_GetModuleFileNameExA) (current_process_handle,
-                                          DllHandle[i],
-                                          dll_name_ret,
-                                          MAX_PATH);
-      if (len == 0)
-       error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
-
-      if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
-       return 1;
+      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);
+         if (len == 0)
+           error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
+#ifdef __CYGWIN__
+         /* Cygwin prefers that the path be in /x/y/z format */
+         cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret);
+#endif
+         return 1;     /* success */
+       }
     }
 
 failed:
   dll_name_ret[0] = '\0';
-  return 0;
+  return 0;            /* failure */
 }
 
 /* Encapsulate the information required in a call to
@@ -553,7 +527,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;
@@ -564,8 +538,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
@@ -614,7 +586,7 @@ safe_symbol_file_add (char *name, int from_tty,
 }
 
 static struct so_list *
-win32_make_so (const char *name, DWORD load_addr)
+win32_make_so (const char *name, LPVOID load_addr)
 {
   struct so_list *so;
   char buf[MAX_PATH + 1];
@@ -662,7 +634,7 @@ win32_make_so (const char *name, DWORD load_addr)
       asection *text = NULL;
       CORE_ADDR text_vma;
 
-      abfd = bfd_openr (name, "pei-i386");
+      abfd = bfd_openr (so->so_name, "pei-i386");
 
       if (!abfd)
        return so;
@@ -697,7 +669,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
@@ -741,7 +713,7 @@ handle_load_dll (void *dummy)
 
   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
-  if (!psapi_get_dll_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;
@@ -752,9 +724,12 @@ handle_load_dll (void *dummy)
   if (!dll_name)
     return 1;
 
-  solib_end->next = win32_make_so (dll_name, (DWORD) event->lpBaseOfDll);
+  solib_end->next = win32_make_so (dll_name, event->lpBaseOfDll);
   solib_end = solib_end->next;
 
+  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at 0x%lx.\n", solib_end->so_name,
+                solib_end->lm_info->load_addr));
+
   return 1;
 }
 
@@ -769,7 +744,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)
@@ -779,6 +754,8 @@ handle_unload_dll (void *dummy)
        so->next = sodel->next;
        if (!so->next)
          solib_end = so;
+       DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+
        win32_free_so (sodel);
        solib_add (NULL, 0, NULL, auto_solib_add);
        return 1;
@@ -829,7 +806,8 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
   int retval = 0;
 
   if (!target_read_string
-    ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
+       ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
+       &s, 1024, 0)
       || !s || !*s)
     /* nothing to do */;
   else if (strncmp (s, _CYGWIN_SIGNAL_STRING, sizeof (_CYGWIN_SIGNAL_STRING) - 1) != 0)
@@ -996,7 +974,7 @@ 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)
+          current_event.u.Exception.ExceptionRecord.ExceptionAddress)
 
 static int
 handle_exception (struct target_waitstatus *ourstatus)
@@ -1023,7 +1001,8 @@ 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) current_event.u.Exception.ExceptionRecord.ExceptionAddress;
+       bfd_vma addr = (bfd_vma) (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))
@@ -1109,7 +1088,7 @@ handle_exception (struct target_waitstatus *ourstatus)
        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);
+               current_event.u.Exception.ExceptionRecord.ExceptionAddress);
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
       break;
     }
@@ -1171,8 +1150,17 @@ fake_create_process (void)
 {
   current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
                                        current_event.dwProcessId);
+  if (current_process_handle != NULL)
+    open_process_used = 1;
+  else
+    {
+      error (_("OpenProcess call failed, GetLastError = %lud\n"),
+       GetLastError ());
+      /*  We can not debug anything in that case.  */
+    }
   main_thread_id = current_event.dwThreadId;
-  current_thread = win32_add_thread (main_thread_id,
+  current_thread = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                                current_event.dwThreadId),
                                     current_event.u.CreateThread.hThread);
   return main_thread_id;
 }
@@ -1183,7 +1171,13 @@ win32_resume (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)
     {
@@ -1221,11 +1215,11 @@ 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: win32_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 (current_event.dwThreadId, FALSE);
+  th = thread_rec (ptid_get_tid (inferior_ptid), FALSE);
   if (th)
     {
       if (step)
@@ -1255,7 +1249,10 @@ 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)
+    win32_continue (continue_status, -1);
+  else
+    win32_continue (continue_status, ptid_get_tid (ptid));
 }
 
 /* Get the next event from the child.  Return 1 if the event requires
@@ -1269,7 +1266,6 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
   thread_info *th;
   static thread_info dummy_thread_info;
   int retval = 0;
-  ptid_t ptid = {-1};
 
   last_sig = TARGET_SIGNAL_0;
 
@@ -1293,24 +1289,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 ();
-             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);
-      if (info_verbose)
-       printf_unfiltered ("[New %s]\n",
-                          target_pid_to_str (
-                            pid_to_ptid (current_event.dwThreadId)));
       retval = current_event.dwThreadId;
+      th = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                        current_event.dwThreadId),
+                            current_event.u.CreateThread.hThread);
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
@@ -1320,7 +1316,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);
+         win32_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                          current_event.dwThreadId));
          th = &dummy_thread_info;
        }
       break;
@@ -1332,19 +1329,18 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
                     "CREATE_PROCESS_DEBUG_EVENT"));
       CloseHandle (current_event.u.CreateProcessInfo.hFile);
       if (++saw_create != 1)
-       {
-         CloseHandle (current_event.u.CreateProcessInfo.hProcess);
-         break;
-       }
+       break;
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       if (main_thread_id)
-       win32_delete_thread (main_thread_id);
+       win32_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,
+      th = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                        current_event.dwThreadId),
                             current_event.u.CreateProcessInfo.hThread);
-      retval = ourstatus->value.related_pid = current_event.dwThreadId;
+      retval = current_event.dwThreadId;
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
@@ -1356,7 +1352,6 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
        break;
       ourstatus->kind = TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
-      CloseHandle (current_process_handle);
       retval = main_thread_id;
       break;
 
@@ -1433,13 +1428,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);
+       win32_resume (minus_one_ptid, 0, 1);
       else
        CHECK (win32_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);
     }
 
@@ -1447,11 +1443,11 @@ 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)
 {
-  int pid = PIDGET (ptid);
+  int pid = -1;
 
   target_terminal_ours ();
 
@@ -1463,9 +1459,27 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 
   while (1)
     {
-      int retval = get_win32_debug_event (pid, ourstatus);
+      int retval;
+      
+      /* Ignore CTRL+C signals while waiting for a debug event.
+         FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
+         the inferior is running, both the inferior and GDB receive the
+         associated signal.  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 to stop
+         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, and it would be nice
+         to find a better solution to that problem.  But in the meantime,
+         the current approach already greatly mitigate this issue.  */
+      SetConsoleCtrlHandler (NULL, TRUE);
+      retval = get_win32_debug_event (pid, ourstatus);
+      SetConsoleCtrlHandler (NULL, FALSE);
+
       if (retval)
-       return pid_to_ptid (retval);
+       return ptid_build (current_event.dwProcessId, 0, retval);
       else
        {
          int detach = 0;
@@ -1480,14 +1494,17 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 }
 
 static void
-do_initial_win32_stuff (DWORD pid)
+do_initial_win32_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;
   exception_count = 0;
+  open_process_used = 0;
   debug_registers_changed = 0;
   debug_registers_used = 0;
   for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
@@ -1497,24 +1514,37 @@ 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 ();
   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 win32_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;
 }
@@ -1524,8 +1554,8 @@ do_initial_win32_stuff (DWORD pid)
    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 BOOL WINAPI (*kernel32_DebugSetProcessKillOnExit)(BOOL);
+static BOOL WINAPI (*kernel32_DebugActiveProcessStop)(DWORD);
 
 static int
 has_detach_ability (void)
@@ -1536,13 +1566,14 @@ has_detach_ability (void)
     kernel32 = LoadLibrary ("kernel32.dll");
   if (kernel32)
     {
-      if (!DebugSetProcessKillOnExit)
-       DebugSetProcessKillOnExit = GetProcAddress (kernel32,
-                                                "DebugSetProcessKillOnExit");
-      if (!DebugActiveProcessStop)
-       DebugActiveProcessStop = GetProcAddress (kernel32,
-                                                "DebugActiveProcessStop");
-      if (DebugSetProcessKillOnExit && DebugActiveProcessStop)
+      if (!kernel32_DebugSetProcessKillOnExit)
+       kernel32_DebugSetProcessKillOnExit =
+         (void *) GetProcAddress (kernel32, "DebugSetProcessKillOnExit");
+      if (!kernel32_DebugActiveProcessStop)
+       kernel32_DebugActiveProcessStop =
+         (void *) GetProcAddress (kernel32, "DebugActiveProcessStop");
+      if (kernel32_DebugSetProcessKillOnExit
+         && kernel32_DebugActiveProcessStop)
        return 1;
     }
   return 0;
@@ -1577,13 +1608,14 @@ set_process_privilege (const char *privilege, BOOL enable)
       if (!(advapi32 = LoadLibrary ("advapi32.dll")))
        goto out;
       if (!OpenProcessToken)
-       OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken");
+       OpenProcessToken =
+          (void *) GetProcAddress (advapi32, "OpenProcessToken");
       if (!LookupPrivilegeValue)
-       LookupPrivilegeValue = GetProcAddress (advapi32,
-                                              "LookupPrivilegeValueA");
+       LookupPrivilegeValue =
+          (void *) GetProcAddress (advapi32, "LookupPrivilegeValueA");
       if (!AdjustTokenPrivileges)
-       AdjustTokenPrivileges = GetProcAddress (advapi32,
-                                               "AdjustTokenPrivileges");
+       AdjustTokenPrivileges =
+          (void *) GetProcAddress (advapi32, "AdjustTokenPrivileges");
       if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
        {
          advapi32 = NULL;
@@ -1627,7 +1659,7 @@ out:
 
 /* Attach to process PID, then initialize for debugging it.  */
 static void
-win32_attach (char *args, int from_tty)
+win32_attach (struct target_ops *ops, char *args, int from_tty)
 {
   BOOL ok;
   DWORD pid;
@@ -1662,9 +1694,7 @@ win32_attach (char *args, int from_tty)
     error (_("Can't attach to process."));
 
   if (has_detach_ability ())
-    DebugSetProcessKillOnExit (FALSE);
-
-  attach_flag = 1;
+    kernel32_DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
@@ -1680,12 +1710,12 @@ win32_attach (char *args, int from_tty)
       gdb_flush (gdb_stdout);
     }
 
-  do_initial_win32_stuff (pid);
+  do_initial_win32_stuff (ops, pid, 1);
   target_terminal_ours ();
 }
 
 static void
-win32_detach (char *args, int from_tty)
+win32_detach (struct target_ops *ops, char *args, int from_tty)
 {
   int detached = 1;
 
@@ -1694,13 +1724,13 @@ win32_detach (char *args, int from_tty)
       ptid_t ptid = {-1};
       win32_resume (ptid, 0, TARGET_SIGNAL_0);
 
-      if (!DebugActiveProcessStop (current_event.dwProcessId))
+      if (!kernel32_DebugActiveProcessStop (current_event.dwProcessId))
        {
          error (_("Can't detach process %lu (error %lu)"),
                 current_event.dwProcessId, GetLastError ());
          detached = 0;
        }
-      DebugSetProcessKillOnExit (FALSE);
+      kernel32_DebugSetProcessKillOnExit (FALSE);
     }
   if (detached && from_tty)
     {
@@ -1711,42 +1741,37 @@ 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)
 {
-  /* Try to find the process path using the Cygwin internal process list
-     pid isn't a valid pid, unfortunately.  Use current_event.dwProcessId
-     instead.  */
-
   static char path[MAX_PATH + 1];
-  char *path_ptr = NULL;
 
 #ifdef __CYGWIN__
-  /* TODO: Also find native Windows processes using CW_GETPINFO_FULL.  */
-  int cpid;
-  struct external_pinfo *pinfo;
-
-  cygwin_internal (CW_LOCK_PINFO, 1000);
-  for (cpid = 0;
-       (pinfo = (struct external_pinfo *)
-       cygwin_internal (CW_GETPINFO, cpid | CW_NEXTPID));
-       cpid = pinfo->pid)
+  /* Try to find exe name as symlink target of /proc/<pid>/exe */
+  int nchars;
+  char procexe[sizeof ("/proc/4294967295/exe")];
+  sprintf (procexe, "/proc/%u/exe", pid);
+  nchars = readlink (procexe, path, sizeof(path));
+  if (nchars > 0 && nchars < sizeof (path))
     {
-      if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */
-       {
-        cygwin_conv_to_full_posix_path (pinfo->progname, path);
-        path_ptr = path;
-        break;
-       }
+      path[nchars] = '\0';     /* Got it */
+      return path;
     }
-  cygwin_internal (CW_UNLOCK_PINFO);
 #endif
 
-  return path_ptr;
+  /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
+     of gdb, or we're trying to debug a non-Cygwin windows executable. */
+  if (!get_module_name (0, path))
+    path[0] = '\0';
+
+  return path;
 }
 
 /* Print status information about what we're accessing.  */
@@ -1754,8 +1779,11 @@ win32_pid_to_exec_file (int pid)
 static void
 win32_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
@@ -1770,8 +1798,8 @@ win32_open (char *arg, int from_tty)
    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)
+win32_create_inferior (struct target_ops *ops, char *exec_file,
+                      char *allargs, char **in_env, int from_tty)
 {
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
@@ -1824,8 +1852,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, " ");
@@ -1894,17 +1920,22 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
   else
     saw_create = 0;
 
-  do_initial_win32_stuff (pi.dwProcessId);
+  do_initial_win32_stuff (ops, pi.dwProcessId, 0);
 
   /* win32_continue (DBG_CONTINUE, -1); */
 }
 
 static void
-win32_mourn_inferior (void)
+win32_mourn_inferior (struct target_ops *ops)
 {
   (void) win32_continue (DBG_CONTINUE, -1);
   i386_cleanup_dregs();
-  unpush_target (&win32_ops);
+  if (open_process_used)
+    {
+      CHECK (CloseHandle (current_process_handle));
+      open_process_used = 0;
+    }
+  unpush_target (ops);
   generic_mourn_inferior ();
 }
 
@@ -1912,7 +1943,7 @@ win32_mourn_inferior (void)
    ^C on the controlling terminal. */
 
 static void
-win32_stop (void)
+win32_stop (ptid_t ptid)
 {
   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
   CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
@@ -1924,21 +1955,24 @@ win32_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) memaddr));
-      if (!WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
+                 len, (DWORD) (uintptr_t) memaddr));
+      if (!WriteProcessMemory (current_process_handle, 
+                              (LPVOID) (uintptr_t) memaddr, our,
                               len, &done))
        done = 0;
-      FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
+      FlushInstructionCache (current_process_handle, 
+                            (LPCVOID) (uintptr_t) memaddr, len);
     }
   else
     {
       DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
-                 len, (DWORD) memaddr));
-      if (!ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our,
+                 len, (DWORD) (uintptr_t) memaddr));
+      if (!ReadProcessMemory (current_process_handle, 
+                             (LPCVOID) (uintptr_t) memaddr, our,
                              len, &done))
        done = 0;
     }
@@ -1960,11 +1994,6 @@ win32_kill_inferior (void)
        break;
     }
 
-  CHECK (CloseHandle (current_process_handle));
-
-  /* this may fail in an attached process so don't check. */
-  if (current_thread && current_thread->h)
-    (void) CloseHandle (current_thread->h);
   target_mourn_inferior ();    /* or just win32_mourn_inferior? */
 }
 
@@ -1992,13 +2021,15 @@ static char *
 win32_pid_to_str (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
@@ -2018,7 +2049,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);
+    win32_xfer_shared_library (so->so_name, (CORE_ADDR) so->lm_info->load_addr,
+                               &obstack);
   obstack_grow_str0 (&obstack, "</library-list>\n");
 
   buf = obstack_finish (&obstack);
@@ -2044,7 +2076,7 @@ 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);
@@ -2071,6 +2103,7 @@ init_win32_ops (void)
   win32_ops.to_open = win32_open;
   win32_ops.to_close = win32_close;
   win32_ops.to_attach = win32_attach;
+  win32_ops.to_attach_no_wait = 1;
   win32_ops.to_detach = win32_detach;
   win32_ops.to_resume = win32_resume;
   win32_ops.to_wait = win32_wait;
@@ -2101,8 +2134,8 @@ init_win32_ops (void)
   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;
+  win32_ops.to_magic = OPS_MAGIC;
 }
 
 static void
@@ -2230,15 +2263,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)
 {
-  int pid = PIDGET (ptid);
+  int tid;
 
-  return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
+  gdb_assert (ptid_get_tid (ptid) != 0);
+  tid = ptid_get_tid (ptid);
+
+  return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
     FALSE : TRUE;
 }
 
@@ -2270,3 +2306,34 @@ _initialize_check_for_gdb_ini (void)
        }
     }
 }
+
+void
+_initialize_psapi (void)
+{
+  /* Load optional functions used for retrieving filename information
+     associated with the currently debugged process or its dlls. */
+  if (!psapi_loaded)
+    {
+      HMODULE psapi_module_handle;
+
+      psapi_loaded = -1;
+
+      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;
+       }
+    }
+
+  /* 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."));
+}
This page took 0.068383 seconds and 4 git commands to generate.