2007-12-28 Pedro Alves PR gdb/2386 * win32-nat.c (load_psapi): New function. (psapi_get_dll_name): Use load_psapi. (win32_pid_to_exec_file): Use PSAPI to find native Windows processes. --- gdb/win32-nat.c | 152 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 102 insertions(+), 50 deletions(-) Index: src/gdb/win32-nat.c =================================================================== --- src.orig/gdb/win32-nat.c 2007-12-28 22:29:52.000000000 +0000 +++ src/gdb/win32-nat.c 2007-12-29 12:49:14.000000000 +0000 @@ -38,6 +38,7 @@ #include #include #include +#include #ifdef __CYGWIN__ #include #endif @@ -84,7 +85,6 @@ enum CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT) }; #endif -#include #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \ | CONTEXT_EXTENDED_REGISTERS @@ -458,9 +458,41 @@ win32_store_inferior_registers (struct 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) = NULL; +static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, + LPMODULEINFO, DWORD) = NULL; +static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, + LPSTR, DWORD) = NULL; + +/* Dinamically load psapi.dll, and get pointers to the functions we + need from it. PSAPI (Process Status API) is an NT helper library + available as a redistributable from MSFT, but chances are the user + already has it on the system. + + Return true if the library is available. The clients are + responsible for checking if the function they want was found. */ +static int +load_psapi (void) +{ + if (!psapi_loaded) + { + psapi_loaded = 1; + psapi_module_handle = LoadLibrary ("psapi.dll"); + if (psapi_module_handle != NULL) + { + psapi_EnumProcessModules + = GetProcAddress (psapi_module_handle, "EnumProcessModules"); + psapi_GetModuleInformation + = GetProcAddress (psapi_module_handle, "GetModuleInformation"); + psapi_GetModuleFileNameExA = (void *) + GetProcAddress (psapi_module_handle, "GetModuleFileNameExA"); + } + } + + return psapi_module_handle != NULL; +} + static int psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret) @@ -473,29 +505,13 @@ psapi_get_dll_name (DWORD BaseAddress, c DWORD cbNeeded; BOOL ok; - 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 (!load_psapi ()) + goto failed; + + if (psapi_EnumProcessModules == NULL + || psapi_GetModuleInformation == NULL + || psapi_GetModuleFileNameExA == NULL) + goto failed; cbNeeded = 0; ok = (*psapi_EnumProcessModules) (current_process_handle, @@ -1727,38 +1743,74 @@ win32_detach (char *args, int from_tty) unpush_target (&win32_ops); } +/* Accepts an integer PID; Returns a string representing a file that + can be opened to get the symbols for the child process. */ + 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; + BOOL ok = FALSE; + + /* PID isn't a valid pid, unfortunately. Use current_event.dwProcessId + instead. */ + pid = current_event.dwProcessId; #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) - { - if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */ - { - cygwin_conv_to_full_posix_path (pinfo->progname, path); - path_ptr = path; - break; - } + { + /* Try to find the process path using the Cygwin internal process + list. */ + 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) + { + if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */ + { + cygwin_conv_to_full_posix_path (pinfo->progname, path); + ok = TRUE; + break; + } + } + cygwin_internal (CW_UNLOCK_PINFO); + if (ok) + return path; + } +#endif + + if (!ok) + { + /* Try to find native Windows processes using PSAPI. */ + if (load_psapi () + && psapi_GetModuleFileNameExA != NULL) + { + HANDLE h; + h = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + 0, pid); + if (h != NULL) + { + if (psapi_GetModuleFileNameExA (h, 0, path, MAX_PATH) > 0) + ok = TRUE; + CloseHandle (h); + } + } } - cygwin_internal (CW_UNLOCK_PINFO); + + if (ok) + { +#ifdef __CYGWIN__ + char buf[sizeof path]; + strcpy (buf, path); + cygwin_conv_to_full_posix_path (buf, path); #endif + return path; + } - return path_ptr; + return NULL; } /* Print status information about what we're accessing. */