daily update
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index 07ebef96be2dc2763cd62be1d66d21f232221779..52ff20a20aec985368122c4ba81b7838ccf29a52 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 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
@@ -359,6 +359,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 +384,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,11 +413,9 @@ 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
@@ -453,88 +455,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 (DWORD 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 || (DWORD) (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
@@ -662,7 +654,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;
@@ -741,7 +733,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 ((DWORD) event->lpBaseOfDll, dll_buf))
     dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
   dll_name = dll_buf;
@@ -1317,10 +1309,6 @@ get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
       /* 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;
       break;
 
@@ -1470,7 +1458,25 @@ 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);
       else
@@ -1517,7 +1523,7 @@ do_initial_win32_stuff (DWORD pid)
   while (1)
     {
       stop_after_trap = 1;
-      wait_for_inferior ();
+      wait_for_inferior (0);
       if (stop_signal != TARGET_SIGNAL_TRAP)
        resume (0, stop_signal);
       else
@@ -1726,35 +1732,27 @@ win32_detach (char *args, int from_tty)
 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/%lu/exe", current_event.dwProcessId);
+  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.  */
@@ -1894,6 +1892,9 @@ win32_create_inferior (char *exec_file, char *allargs, char **in_env,
     error (_("Error creating process %s, (error %d)."),
           exec_file, (unsigned) GetLastError ());
 
+  CloseHandle (pi.hThread);
+  CloseHandle (pi.hProcess);
+
   if (useshell && shell[0] != '\0')
     saw_create = -1;
   else
@@ -2052,7 +2053,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);
@@ -2278,3 +2279,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.037162 seconds and 4 git commands to generate.