diff options
author | Christopher Faylor <me+cygwin@cgf.cx> | 2009-03-22 21:27:30 +0000 |
---|---|---|
committer | Christopher Faylor <me+cygwin@cgf.cx> | 2009-03-22 21:27:30 +0000 |
commit | 2b008701dc388692b80774c1913c55d54be5c320 (patch) | |
tree | 34af7c3b0a555946cbded759bce2bacba46c47f5 /gdb/windows-nat.c | |
parent | bcd5727bdddbf3063b7a8714708a95863d811a9d (diff) | |
download | gdb-2b008701dc388692b80774c1913c55d54be5c320.zip gdb-2b008701dc388692b80774c1913c55d54be5c320.tar.gz gdb-2b008701dc388692b80774c1913c55d54be5c320.tar.bz2 |
* 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.
Diffstat (limited to 'gdb/windows-nat.c')
-rw-r--r-- | gdb/windows-nat.c | 248 |
1 files changed, 140 insertions, 108 deletions
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index 2ab1709..e80c4c5 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -38,6 +38,7 @@ #include <stdlib.h> #include <windows.h> #include <imagehlp.h> +#include <psapi.h> #ifdef __CYGWIN__ #include <sys/cygwin.h> #endif @@ -63,6 +64,28 @@ #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.")); + } } |