From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1381 invoked by alias); 29 Dec 2007 14:33:15 -0000 Received: (qmail 1370 invoked by uid 22791); 29 Dec 2007 14:33:14 -0000 X-Spam-Check-By: sourceware.org Received: from mu-out-0910.google.com (HELO mu-out-0910.google.com) (209.85.134.188) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 29 Dec 2007 14:33:04 +0000 Received: by mu-out-0910.google.com with SMTP id g7so2754018muf.0 for ; Sat, 29 Dec 2007 06:33:01 -0800 (PST) Received: by 10.78.185.15 with SMTP id i15mr12785631huf.61.1198938106632; Sat, 29 Dec 2007 06:21:46 -0800 (PST) Received: from ?78.130.87.130? ( [78.130.87.130]) by mx.google.com with ESMTPS id 7sm2512086nfv.35.2007.12.29.06.21.43 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 29 Dec 2007 06:21:46 -0800 (PST) Message-ID: <477657B2.6020101@portugalmail.pt> Date: Sat, 29 Dec 2007 14:35:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.8.1.9) Gecko/20071031 Thunderbird/2.0.0.9 Mnenhy/0.7.5.0 MIME-Version: 1.0 To: Joel Brobecker CC: gdb-patches@sourceware.org Subject: Re: PR/2386 [2/2]: MinGW attach to process without an exec file References: <47744F9C.8040604@portugalmail.pt> <20071228013457.GB7602@ednor.casa.cgf.cx> <477579E0.5010809@portugalmail.pt> <20071229035030.GC30002@adacore.com> <47764306.4060903@portugalmail.pt> In-Reply-To: <47764306.4060903@portugalmail.pt> Content-Type: multipart/mixed; boundary="------------040205090201090608090904" X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-12/txt/msg00457.txt.bz2 This is a multi-part message in MIME format. --------------040205090201090608090904 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 115 Updated version reinstating 9x support using ToolHelp32 functions, following Eli's remarks. OK ? -- Pedro Alves --------------040205090201090608090904 Content-Type: text/x-diff; name="win32_pid_to_exec_file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="win32_pid_to_exec_file.diff" Content-length: 8882 2007-12-28 Pedro Alves PR gdb/2386 * win32-nat.c: Include "tlhelp32.h". Minor cleanups. (toolhelp_loaded, toolhelp_CreateToolhelp32Snapshot) (toolhelp_Process32First, toolhelp_Process32Next): New variables. (load_toolhelp, load_psapi): New functions. (psapi_get_dll_name): Use load_psapi. (win32_pid_to_exec_file): Use PSAPI to find native Windows processes on NT, and ToolHelp32 to find native Windows processes on 9x. --- gdb/win32-nat.c | 215 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 165 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 14:18:38.000000000 +0000 @@ -38,6 +38,8 @@ #include #include #include +#include +#include #ifdef __CYGWIN__ #include #endif @@ -84,7 +86,6 @@ enum CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT) }; #endif -#include #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \ | CONTEXT_EXTENDED_REGISTERS @@ -247,6 +248,36 @@ check (BOOL ok, const char *file, int li GetLastError ()); } +static int toolhelp_loaded = 0; +static HANDLE WINAPI (*toolhelp_CreateToolhelp32Snapshot) (DWORD, DWORD); +static BOOL WINAPI (*toolhelp_Process32First) (HANDLE, LPPROCESSENTRY32); +static BOOL WINAPI (*toolhelp_Process32Next) (HANDLE, LPPROCESSENTRY32); + +/* Try to get pointers into ToolHelp32 funcions and return true if + available. Loaded dunamically, because ToolHelp32 is not available + on some versions of NT. */ +static int +load_toolhelp (void) +{ + if (!toolhelp_loaded) + { + HMODULE h = GetModuleHandle ("kernel32.dll"); + if (h != NULL) + { + toolhelp_CreateToolhelp32Snapshot = (void *) + GetProcAddress (h, "CreateToolhelp32Snapshot"); + toolhelp_Process32First = GetProcAddress (h, "Process32First"); + toolhelp_Process32Next = GetProcAddress (h, "Process32Next"); + } + + toolhelp_loaded = 1; + } + + return (toolhelp_CreateToolhelp32Snapshot != NULL + && toolhelp_Process32First != NULL + && toolhelp_Process32Next != NULL); +} + /* Find a thread record given a thread id. If GET_CONTEXT is not 0, then also retrieve the context for this thread. If GET_CONTEXT is negative, then don't suspend the thread. */ @@ -458,9 +489,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 +536,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 +1774,106 @@ 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; + OSVERSIONINFO osvi = { 0 }; + + /* 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 + + osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); + GetVersionEx (&osvi); + if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + /* 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); + else + { + /* Iterate through all the processes in the system using + ToolHelp32 looking for PID. We only use this method on 9x + because on on NT the szExeFile field doesn't include the full + path to the executable. */ + + if (load_toolhelp ()) + { + HANDLE h; + h = toolhelp_CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, pid); + if (h != INVALID_HANDLE_VALUE) + { + PROCESSENTRY32 e = { sizeof (PROCESSENTRY32) }; + int n; + for (n = toolhelp_Process32First (h, &e); + n; + n = toolhelp_Process32Next (h, &e)) + if (e.th32ProcessID == pid) + { + strcpy (path, e.szExeFile); + ok = TRUE; + break; + } + + CloseHandle (h); + } + } + } + + 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. */ --------------040205090201090608090904--