* windows-nat.c (DebugActiveProcessStop): Implement macro wraparound for
authorChristopher Faylor <me+cygwin@cgf.cx>
Sun, 22 Mar 2009 21:27:30 +0000 (21:27 +0000)
committerChristopher Faylor <me+cygwin@cgf.cx>
Sun, 22 Mar 2009 21:27:30 +0000 (21:27 +0000)
dynamically loaded function.
(DebugBreakProcess): Ditto.
(DebugSetProcessKillOnExit): Ditto.
(EnumProcessModules): Ditto.
(GetModuleFileNameExA): Ditto.
(GetModuleInformation): Ditto.
(DebugActiveProcessStop): Rename and define placeholder for address of
dynamically loaded function.  for dynamically loaded function.
(DebugBreakProcess): Ditto.
(DebugSetProcessKillOnExit): Ditto.
(EnumProcessModules): Ditto.
(GetModuleFileNameExA): Ditto.
(GetModuleInformation): Ditto.
(psapi_loaded): Delete.
(get_module_name): Don't check psapi_loaded, just rely on the fact that
dynamically loaded functions will return failure if they weren't previously
found.
(has_detach_ability): Delete.
(windows_attach): Remove call to has_detach_ability ().  Just rely on functions
being callable.
(bad_DebugActiveProcessStop): Define.
(bad_DebugBreakProcess): Ditto.
(bad_DebugSetProcessKillOnExit): Ditto.
(bad_EnumProcessModules): Ditto.
(bad_GetModuleFileNameExA): Ditto.
(bad_GetModuleInformation): Ditto.
(_initialize_loadable): Rename from _initialize_psapi.  Initialize all dynamic
storage here, setting nonexistent functions to dummy static functions which
always return error.

gdb/ChangeLog
gdb/windows-nat.c

index a323589a4417f510807919ceabed6ee8daf5eea7..686a1497054ae589035c96ce251f32cefcd7f2b4 100644 (file)
@@ -1,3 +1,36 @@
+2009-03-22  Christopher Faylor  <me+cygwin@cgf.cx>
+
+       * windows-nat.c (DebugActiveProcessStop): Implement macro wraparound
+       for dynamically loaded function.
+       (DebugBreakProcess): Ditto.
+       (DebugSetProcessKillOnExit): Ditto.
+       (EnumProcessModules): Ditto.
+       (GetModuleFileNameExA): Ditto.
+       (GetModuleInformation): Ditto.
+       (DebugActiveProcessStop): Rename and define placeholder for address of
+       dynamically loaded function.  for dynamically loaded function.
+       (DebugBreakProcess): Ditto.
+       (DebugSetProcessKillOnExit): Ditto.
+       (EnumProcessModules): Ditto.
+       (GetModuleFileNameExA): Ditto.
+       (GetModuleInformation): Ditto.
+       (psapi_loaded): Delete.
+       (get_module_name): Don't check psapi_loaded, just rely on the fact that
+       dynamically loaded functions will return failure if they weren't
+       previously found.
+       (has_detach_ability): Delete.
+       (windows_attach): Remove call to has_detach_ability ().  Just rely on
+       functions being callable.
+       (bad_DebugActiveProcessStop): Define.
+       (bad_DebugBreakProcess): Ditto.
+       (bad_DebugSetProcessKillOnExit): Ditto.
+       (bad_EnumProcessModules): Ditto.
+       (bad_GetModuleFileNameExA): Ditto.
+       (bad_GetModuleInformation): Ditto.
+       (_initialize_loadable): Rename from _initialize_psapi.  Initialize all
+       dynamic storage here, setting nonexistent functions to dummy static
+       functions which always return error.
+
 2009-03-22  Pedro Alves  <pedro@codesourcery.com>
 
        * mi/mi-interp.c (mi_interpreter_init): Attach mi_about_to_proceed
index 2ab17097cd5e4b8b9b3cf867b0ccab5d22594b34..e80c4c56da002c51e351f75d401c2c08f36fc3e1 100644 (file)
@@ -38,6 +38,7 @@
 #include <stdlib.h>
 #include <windows.h>
 #include <imagehlp.h>
+#include <psapi.h>
 #ifdef __CYGWIN__
 #include <sys/cygwin.h>
 #endif
 #include "windows-tdep.h"
 #include "windows-nat.h"
 
+#define DebugActiveProcessStop         dyn_DebugActiveProcessStop
+#define DebugBreakProcess              dyn_DebugBreakProcess
+#define DebugSetProcessKillOnExit      dyn_DebugSetProcessKillOnExit
+#define EnumProcessModules             dyn_EnumProcessModules
+#define GetModuleFileNameExA           dyn_GetModuleFileNameExA
+#define GetModuleInformation           dyn_GetModuleInformation
+
+/* 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 (*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 struct target_ops windows_ops;
 
 #ifdef __CYGWIN__
@@ -84,7 +107,6 @@ 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,
@@ -366,7 +388,7 @@ do_windows_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)
            {
@@ -438,14 +460,6 @@ windows_store_inferior_registers (struct target_ops *ops,
     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).  */
@@ -465,15 +479,10 @@ get_module_name (LPVOID 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 */
@@ -482,22 +491,22 @@ get_module_name (LPVOID 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 || 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__
@@ -976,7 +985,7 @@ info_w32_command (char *args, int from_tty)
 
 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
   printf_unfiltered ("gdb: Target exception %s at %p\n", x, \
-          current_event.u.Exception.ExceptionRecord.ExceptionAddress)
+                    current_event.u.Exception.ExceptionRecord.ExceptionAddress)
 
 static int
 handle_exception (struct target_waitstatus *ourstatus)
@@ -1089,7 +1098,7 @@ handle_exception (struct target_waitstatus *ourstatus)
        return -1;
       printf_unfiltered ("gdb: unknown target exception 0x%08lx at %p\n",
                    current_event.u.Exception.ExceptionRecord.ExceptionCode,
-               current_event.u.Exception.ExceptionRecord.ExceptionAddress);
+                   current_event.u.Exception.ExceptionRecord.ExceptionAddress);
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
       break;
     }
@@ -1465,20 +1474,20 @@ windows_wait (struct target_ops *ops,
   while (1)
     {
       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.  */
+        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_windows_debug_event (ops, pid, ourstatus);
       SetConsoleCtrlHandler (NULL, FALSE);
@@ -1554,36 +1563,6 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
   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 (*kernel32_DebugSetProcessKillOnExit)(BOOL);
-static BOOL WINAPI (*kernel32_DebugActiveProcessStop)(DWORD);
-
-static int
-has_detach_ability (void)
-{
-  static HMODULE kernel32 = NULL;
-
-  if (!kernel32)
-    kernel32 = LoadLibrary ("kernel32.dll");
-  if (kernel32)
-    {
-      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;
-}
-
 /* Try to set or remove a user privilege to the current process.  Return -1
    if that fails, the previous setting of that privilege otherwise.
 
@@ -1614,13 +1593,13 @@ set_process_privilege (const char *privilege, BOOL enable)
        goto out;
       if (!OpenProcessToken)
        OpenProcessToken =
-          (void *) GetProcAddress (advapi32, "OpenProcessToken");
+         (void *) GetProcAddress (advapi32, "OpenProcessToken");
       if (!LookupPrivilegeValue)
        LookupPrivilegeValue =
-          (void *) GetProcAddress (advapi32, "LookupPrivilegeValueA");
+         (void *) GetProcAddress (advapi32, "LookupPrivilegeValueA");
       if (!AdjustTokenPrivileges)
        AdjustTokenPrivileges =
-          (void *) GetProcAddress (advapi32, "AdjustTokenPrivileges");
+         (void *) GetProcAddress (advapi32, "AdjustTokenPrivileges");
       if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges)
        {
          advapi32 = NULL;
@@ -1698,8 +1677,7 @@ windows_attach (struct target_ops *ops, char *args, int from_tty)
   if (!ok)
     error (_("Can't attach to process."));
 
-  if (has_detach_ability ())
-    kernel32_DebugSetProcessKillOnExit (FALSE);
+  DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
@@ -1724,19 +1702,17 @@ windows_detach (struct target_ops *ops, char *args, int from_tty)
 {
   int detached = 1;
 
-  if (has_detach_ability ())
-    {
-      ptid_t ptid = {-1};
-      windows_resume (ops, ptid, 0, TARGET_SIGNAL_0);
+  ptid_t ptid = {-1};
+  windows_resume (ops, ptid, 0, TARGET_SIGNAL_0);
 
-      if (!kernel32_DebugActiveProcessStop (current_event.dwProcessId))
-       {
-         error (_("Can't detach process %lu (error %lu)"),
-                current_event.dwProcessId, GetLastError ());
-         detached = 0;
-       }
-      kernel32_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);
@@ -1994,18 +1970,18 @@ windows_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
     {
       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;
@@ -2343,33 +2319,89 @@ _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;
+}
+
+/* Load any functions which may not be available in ancient versions
+   of Windows. */
 void
-_initialize_psapi (void)
+_initialize_loadable (void)
 {
-  /* Load optional functions used for retrieving filename information
-     associated with the currently debugged process or its dlls. */
-  if (!psapi_loaded)
+  HMODULE hm = NULL;
+
+  hm = LoadLibrary ("kernel32.dll");
+  if (hm)
     {
-      HMODULE psapi_module_handle;
+      dyn_DebugActiveProcessStop = (void *)
+       GetProcAddress (hm, "DebugActiveProcessStop");
+      dyn_DebugBreakProcess = (void *)
+       GetProcAddress (hm, "DebugBreakProcess");
+      dyn_DebugSetProcessKillOnExit = (void *)
+       GetProcAddress (hm, "DebugSetProcessKillOnExit");
+    }
 
-      psapi_loaded = -1;
+  /* 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;
+    }
 
-      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;
-       }
+  /* Load optional functions used for retrieving filename information
+     associated with the currently debugged process or its dlls. */
+  hm = LoadLibrary ("psapi.dll");
+  if (hm)
+    {
+      dyn_EnumProcessModules = (void *)
+       GetProcAddress (hm, "EnumProcessModules");
+      dyn_GetModuleInformation = (void *)
+       GetProcAddress (hm, "GetModuleInformation");
+      dyn_GetModuleFileNameExA = (void *)
+       GetProcAddress (hm, "GetModuleFileNameExA");
     }
 
-  /* 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."));
+  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.  Use \"file\" or \"dll\" command to load executable/libraries directly."));
+    }
 }