From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 29044 invoked by alias); 29 Dec 2007 12:53:35 -0000 Received: (qmail 29034 invoked by uid 22791); 29 Dec 2007 12:53:34 -0000 X-Spam-Check-By: sourceware.org Received: from mu-out-0910.google.com (HELO mu-out-0910.google.com) (209.85.134.190) by sourceware.org (qpsmtpd/0.31) with ESMTP; Sat, 29 Dec 2007 12:53:27 +0000 Received: by mu-out-0910.google.com with SMTP id g7so2717260muf.0 for ; Sat, 29 Dec 2007 04:53:22 -0800 (PST) Received: by 10.78.139.14 with SMTP id m14mr12748906hud.25.1198932801504; Sat, 29 Dec 2007 04:53:21 -0800 (PST) Received: from ?78.130.87.130? ( [78.130.87.130]) by mx.google.com with ESMTPS id 5sm14963708nfv.32.2007.12.29.04.53.18 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 29 Dec 2007 04:53:21 -0800 (PST) Message-ID: <47764306.4060903@portugalmail.pt> Date: Sat, 29 Dec 2007 12:59: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> In-Reply-To: <20071229035030.GC30002@adacore.com> Content-Type: multipart/mixed; boundary="------------070908040901030506000807" 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/msg00452.txt.bz2 This is a multi-part message in MIME format. --------------070908040901030506000807 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2107 Joel Brobecker wrote: > I have a couple of questions, out of curiosity... > Which prompted me to google a bit more :-) I guess I was trying too hard to not depend on psapi.dll. psapi.dll is available as part of the platform SDK, from MSFT, and since it is redistributable, as part of several applications, which means the chances it isn't there are slimm nowadays. If it isn't there, like for instance the user is still on an NT4, it can be downloaded from MSFT. "Platform SDK Redistributable: PSAPI for Windows NT" gets you there. >> - looks in the Cygwin processes using cygwin_internal (CW_GETPINFO, ...). >> This is what's done currently, so Cygwin processes will be detected >> like before. > > If we are going to have some code that does this natively as suggested > below, why have some code that would work on cygwin only? Is the above > going to cover more cases (windows versions?) than the approach below? > It will cover Cygwin processes on 9x, and the cases where psapi.dll isn't found. I'll leave to Christopher to decide if it should be removed. >> - If that fails, tries to get at the filename associated with the file >> handle that the debug api gives us in the CREATE_PROCESS_DEBUG_EVENT. >> Previously, it was just closed; we now store it in a global variable. >> This relies on the internal NT name of the HANDLE, and it may change >> in future releases, hence, > I've stripped this part from the patch. > Do you know when it wouldn't work? The name associated with the HANDLE is an internal, private NT detail which which happens to work in practice, in XP at least, but subject to change by MSFT. > >> - If that fails, GetModuleFileNameEx from psapi.dll is used. > > Same here, if we know the conditions when this would or woudln't work, > a comment would be very helpful for future contributors. > The function will always work for a process we're already debugging, provided dynamically loading psapi.dll works. The patch is now certainly much less invasive. Chris, do you think it is on the right track now ? -- Pedro Alves --------------070908040901030506000807 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: 6462 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. */ --------------070908040901030506000807--