From: Pedro Alves <pedro_alves@portugalmail.pt>
To: Joel Brobecker <brobecker@adacore.com>
Cc: gdb-patches@sourceware.org
Subject: Re: PR/2386 [2/2]: MinGW attach to process without an exec file
Date: Sat, 29 Dec 2007 14:35:00 -0000 [thread overview]
Message-ID: <477657B2.6020101@portugalmail.pt> (raw)
In-Reply-To: <47764306.4060903@portugalmail.pt>
[-- Attachment #1: Type: text/plain, Size: 115 bytes --]
Updated version reinstating 9x support using ToolHelp32 functions,
following Eli's remarks.
OK ?
--
Pedro Alves
[-- Attachment #2: win32_pid_to_exec_file.diff --]
[-- Type: text/x-diff, Size: 8882 bytes --]
2007-12-28 Pedro Alves <pedro_alves@portugalmail.pt>
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 <stdlib.h>
#include <windows.h>
#include <imagehlp.h>
+#include <tlhelp32.h>
+#include <psapi.h>
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
@@ -84,7 +86,6 @@ enum
CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
};
#endif
-#include <psapi.h>
#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. */
next prev parent reply other threads:[~2007-12-29 14:33 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-12-28 1:35 Pedro Alves
2007-12-28 4:33 ` Christopher Faylor
2007-12-29 3:37 ` Pedro Alves
2007-12-29 3:50 ` Joel Brobecker
2007-12-29 11:47 ` Eli Zaretskii
2007-12-29 14:02 ` Lerele
2007-12-29 5:42 ` Joel Brobecker
2007-12-29 12:59 ` Pedro Alves
2007-12-29 14:35 ` Pedro Alves [this message]
2007-12-29 18:48 ` Christopher Faylor
2007-12-29 20:15 ` Eli Zaretskii
2007-12-29 22:46 ` Pedro Alves
2007-12-30 3:07 ` Christopher Faylor
2007-12-30 4:32 ` Eli Zaretskii
2007-12-30 20:37 ` Christopher Faylor
2007-12-31 6:35 ` Eli Zaretskii
2007-12-31 8:12 ` Christopher Faylor
2007-12-31 21:38 ` Eli Zaretskii
2007-12-30 20:41 ` Pedro Alves
2007-12-30 4:20 ` Eli Zaretskii
2007-12-31 4:13 ` Pedro Alves
2007-12-29 11:41 ` Eli Zaretskii
2007-12-29 11:33 ` Eli Zaretskii
2007-12-29 14:33 ` Pedro Alves
2007-12-29 16:08 ` Eli Zaretskii
2007-12-30 0:30 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=477657B2.6020101@portugalmail.pt \
--to=pedro_alves@portugalmail.pt \
--cc=brobecker@adacore.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox