* PR/2386 [2/2]: MinGW attach to process without an exec file
@ 2007-12-28 1:35 Pedro Alves
2007-12-28 4:33 ` Christopher Faylor
2007-12-29 11:33 ` Eli Zaretskii
0 siblings, 2 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-28 1:35 UTC (permalink / raw)
To: gdb-patches; +Cc: Bogdan Slusarczyk
[-- Attachment #1: Type: text/plain, Size: 798 bytes --]
The target_pid_to_exec_file MinGW implementation
win32-nat.c:win32_pid_to_exec_file is currently an empty stub,
as I mentioned on http://sourceware.org/ml/gdb/2007-10/msg00104.html.
This patch fills the gap. The patch covers 9x/NT, and tries to
work even if psapi.dll isn't present, as it isn't part of
the OS. To do that, it has to resort to non documented
NT funcionality... If that doesn't work, it falls back
into using psapi.dll. I'd be very happy if someone could
point me at better ways to get at executable from a PID on
Windows, or at a filename from a file handle. Note that de
documented way to use a mapping relies on psapi.dll.
This is also useful when debugging a native win32 app
from a Cygwin gdb.
Tested on XP Pro SP2, i686-pc-cygwin, no changes.
OK ?
--
Pedro Alves
[-- Attachment #2: win32_pid_to_exec_file.diff --]
[-- Type: text/x-diff, Size: 13831 bytes --]
2007-12-28 Pedro Alves <pedro_alves@portugalmail.pt>
PR gdb/2386
* win32-nat.c: Include "tlhelp32.h", "ntdef.h" and "safe-ctype.h".
(current_process_file_handle): New variable.
(load_psapi): New function.
(psapi_get_dll_name): Use load_psapi.
(get_win32_debug_event): Don't close the process file handle.
Store it in current_process_file_handle.
(do_initial_win32_stuff): Clear current_process_file_handle.
(pid_to_exec_file_psapi): New function.
(toolhelp_loaded, toolhelp_module_handle)
(toolhelp_CreateToolhelp32Snapshot, toolhelp_Process32First)
(toolhelp_Process32Next): New variables.
(load_toolhelp, pid_to_exec_file_toolhelp_9x)
(device_filename_to_dos_filename): New functions.
(OBJECT_INFO_CLASS, OBJECT_NAME_INFO): New structs.
(NTQUERYOBJECT): New variable.
(get_nt_object_name, get_file_name_from_handle_objname)
(win32_pid_to_exec_file_1): New functions.
(win32_pid_to_exec_file): Use win32_pid_to_exec_file_1.
(win32_mourn_inferior): Close current_process_file_handle.
* Makefile.in (win32-nat.o): Add dependency on $(safe_ctype_h).
---
gdb/Makefile.in | 2
gdb/win32-nat.c | 333 +++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 284 insertions(+), 51 deletions(-)
Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c 2007-12-27 00:45:50.000000000 +0000
+++ src/gdb/win32-nat.c 2007-12-27 23:55:02.000000000 +0000
@@ -38,6 +38,9 @@
#include <stdlib.h>
#include <windows.h>
#include <imagehlp.h>
+#include <psapi.h>
+#include <tlhelp32.h>
+#include <ntdef.h>
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
@@ -57,6 +60,7 @@
#include "solist.h"
#include "solib.h"
#include "xml-support.h"
+#include "safe-ctype.h"
#include "i386-tdep.h"
#include "i387-tdep.h"
@@ -84,7 +88,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
@@ -135,6 +138,8 @@ static thread_info thread_head;
static DEBUG_EVENT current_event; /* The current debug event from
WaitForDebugEvent */
static HANDLE current_process_handle; /* Currently executing process */
+static HANDLE current_process_file_handle; /* Currently executing
+ process' file handle */
static thread_info *current_thread; /* Info on currently selected thread */
static DWORD main_thread_id; /* Thread ID of the main thread */
@@ -463,6 +468,28 @@ static BOOL WINAPI (*psapi_GetModuleInfo
static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
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)
{
DWORD len;
@@ -473,29 +500,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,
@@ -1277,7 +1288,7 @@ get_win32_debug_event (int pid, struct t
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"CREATE_PROCESS_DEBUG_EVENT"));
- CloseHandle (current_event.u.CreateProcessInfo.hFile);
+ current_process_file_handle = current_event.u.CreateProcessInfo.hFile;
if (++saw_create != 1)
break;
@@ -1439,8 +1450,9 @@ do_initial_win32_stuff (DWORD pid)
#ifdef __CYGWIN__
cygwin_load_start = cygwin_load_end = 0;
#endif
- current_event.dwProcessId = pid;
memset (¤t_event, 0, sizeof (current_event));
+ current_event.dwProcessId = pid;
+ current_process_file_handle = INVALID_HANDLE_VALUE;
push_target (&win32_ops);
disable_breakpoints_in_shlibs ();
win32_clear_solib ();
@@ -1659,38 +1671,253 @@ win32_detach (char *args, int from_tty)
unpush_target (&win32_ops);
}
+static BOOL
+pid_to_exec_file_psapi (DWORD pid, char *pathbuf)
+{
+ BOOL ok = FALSE;
+
+ load_psapi ();
+
+ if (psapi_GetModuleFileNameExA != NULL)
+ {
+ HANDLE h;
+ h = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, pid);
+ if (h != NULL)
+ {
+ if (psapi_GetModuleFileNameExA (h, 0, pathbuf, MAX_PATH) > 0)
+ ok = TRUE;
+ CloseHandle (h);
+ }
+ }
+
+ return ok;
+}
+
+static int toolhelp_loaded = 0;
+static HMODULE toolhelp_module_handle = NULL;
+static HANDLE WINAPI (*toolhelp_CreateToolhelp32Snapshot) (DWORD, DWORD);
+static BOOL WINAPI (*toolhelp_Process32First) (HANDLE, LPPROCESSENTRY32);
+static BOOL WINAPI (*toolhelp_Process32Next) (HANDLE, LPPROCESSENTRY32);
+
+static int
+load_toolhelp (void)
+{
+ if (!toolhelp_loaded)
+ {
+ toolhelp_loaded = 1;
+ toolhelp_module_handle = GetModuleHandle ("kernel32.dll");
+ if (toolhelp_module_handle != NULL)
+ {
+ toolhelp_CreateToolhelp32Snapshot = (void *)
+ GetProcAddress (toolhelp_module_handle, "CreateToolhelp32Snapshot");
+ toolhelp_Process32First
+ = GetProcAddress (toolhelp_module_handle, "Process32First");
+ toolhelp_Process32Next
+ = GetProcAddress (toolhelp_module_handle, "Process32Next");
+ }
+ }
+
+ return toolhelp_module_handle != NULL;
+}
+
+static BOOL
+pid_to_exec_file_toolhelp_9x (DWORD pid, char *pathbuf)
+{
+ BOOL ok = 0;
+ HANDLE h;
+
+ if (!load_toolhelp ()
+ || toolhelp_CreateToolhelp32Snapshot == NULL
+ || toolhelp_Process32First == NULL
+ || toolhelp_Process32Next == NULL)
+ return FALSE;
+
+ h = toolhelp_CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
+ 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 (pathbuf, e.szExeFile);
+ ok = TRUE;
+ break;
+ }
+
+ CloseHandle (h);
+ }
+
+ return ok;
+}
+
+/* Translate a Windows path with device name to drive letters. */
+static BOOL
+device_filename_to_dos_filename (char *out, const char *in, size_t nSize)
+{
+ char drive[] = "_:";
+ char all_drives[0x1000];
+ char devices[MAX_PATH + 1];
+ char *p;
+
+ /* A NULL terminated list of NULL terminated strings. */
+ if (!GetLogicalDriveStrings (sizeof all_drives - 1, all_drives))
+ return FALSE;
+
+ p = all_drives;
+ while (*p)
+ {
+ /* Copy the drive letter to the template string. */
+ *drive = *p;
+
+ /* Look up each device name. DEVICES is a NULL terminated list
+ of NULL terminated strings. */
+ if (QueryDosDevice (drive, devices, sizeof devices - 1))
+ {
+ size_t len = strlen (devices);
+ if (len < MAX_PATH
+ && (in[len] == '\\' || in[len] == '\0')
+ && strncasecmp (in, devices, len) == 0)
+ {
+ /* Reconstruct the filename by replacing the device path
+ with a DOS drive path. */
+ snprintf (out, MAX_PATH, "%s%s", drive, in + len);
+ return TRUE;
+ }
+ }
+
+ /* Next drive letter. */
+ while (*p++)
+ ;
+ }
+
+ return FALSE;
+}
+
+typedef enum tagOBJECT_INFO_CLASS
+{
+ ObjectNameInfo = 1,
+} OBJECT_INFO_CLASS;
+
+typedef struct tagOBJECT_NAME_INFO
+{
+ UNICODE_STRING ObjectName;
+ WCHAR ObjectNameBuffer[1];
+} OBJECT_NAME_INFO;
+
+typedef NTSTATUS (NTAPI * NTQUERYOBJECT)(HANDLE, OBJECT_INFO_CLASS,
+ PVOID, ULONG, PULONG);
+static BOOL
+get_nt_object_name (HANDLE h, char *namebuf)
+{
+ BOOL ok = FALSE;
+ HMODULE ntdll = GetModuleHandle ("ntdll.dll");
+ NTQUERYOBJECT NtQueryObject
+ = (NTQUERYOBJECT) GetProcAddress (ntdll, "NtQueryObject");
+
+ size_t size = sizeof (OBJECT_NAME_INFO) + (MAX_PATH + 1) * sizeof(WCHAR);
+ OBJECT_NAME_INFO *nameinfo = xmalloc (size);
+
+ NTSTATUS rc = NtQueryObject (h, ObjectNameInfo, nameinfo, size, NULL);
+ if (rc == STATUS_SUCCESS)
+ {
+ wchar_t *wname = nameinfo->ObjectName.Buffer;
+ wcstombs (namebuf, wname, size - wcslen (wname) + 1);
+ ok = TRUE;
+ }
+
+ xfree (nameinfo);
+ return ok;
+}
+
+static BOOL
+get_file_name_from_handle_objname (HANDLE file, char *pathbuf)
+{
+ char buf[MAX_PATH + 1];
+ return (file != INVALID_HANDLE_VALUE
+ && get_nt_object_name (file, buf)
+ && device_filename_to_dos_filename (pathbuf, buf, MAX_PATH)
+ && ISALPHA (pathbuf[0]) && pathbuf[1] == ':');
+}
+
+static int
+win32_pid_to_exec_file_1 (int pid, char *pathbuf)
+{
+ OSVERSIONINFO osvi = { 0 };
+
+#ifdef __CYGWIN__
+ {
+ /* Try to find the process path using the Cygwin internal
+ process list.
+
+ 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 == pid) /* Got it */
+ {
+ strcpy (pathbuf, pinfo->progname);
+ return 1;
+ }
+ }
+ cygwin_internal (CW_UNLOCK_PINFO);
+ }
+#endif
+
+ osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ GetVersionEx (&osvi);
+ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ if (pid == current_event.dwProcessId)
+ {
+ /* Try with native NT functionality. */
+ HANDLE f = current_process_file_handle;
+ if (get_file_name_from_handle_objname (f, pathbuf))
+ return 1;
+ }
+
+ /* Fall back to using psapi.dll, which may not be present. */
+ if (pid_to_exec_file_psapi (pid, pathbuf))
+ return 1;
+
+ return 0;
+ }
+ else
+ /* Toolhelp functionality on 9x is always available in
+ kernel32.dll. Unlike the NT version, it returns a full
+ path. */
+ return pid_to_exec_file_toolhelp_9x (pid, pathbuf);
+}
+
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 pathbuf[MAX_PATH + 1];
- static char path[MAX_PATH + 1];
- char *path_ptr = NULL;
+ /* PID isn't a valid pid, unfortunately. Use current_event.dwProcessId
+ instead. */
+ pid = current_event.dwProcessId;
+ if (win32_pid_to_exec_file_1 (pid, pathbuf))
+ {
#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;
- }
- }
- cygwin_internal (CW_UNLOCK_PINFO);
+ char buf[sizeof pathbuf];
+ strcpy (buf, pathbuf);
+ cygwin_conv_to_full_posix_path (buf, pathbuf);
#endif
+ return pathbuf;
+ }
- return path_ptr;
+ return NULL;
}
/* Print status information about what we're accessing. */
@@ -1848,8 +2075,14 @@ win32_mourn_inferior (void)
if (open_process_used)
{
CHECK (CloseHandle (current_process_handle));
+ current_process_handle = NULL;
open_process_used = 0;
}
+ if (current_process_file_handle != INVALID_HANDLE_VALUE)
+ {
+ CHECK (CloseHandle (current_process_file_handle));
+ current_process_file_handle = INVALID_HANDLE_VALUE;
+ }
unpush_target (&win32_ops);
generic_mourn_inferior ();
}
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in 2007-12-27 00:45:50.000000000 +0000
+++ src/gdb/Makefile.in 2007-12-27 23:50:04.000000000 +0000
@@ -2946,7 +2946,7 @@ win32-nat.o: win32-nat.c $(defs_h) $(fra
$(regcache_h) $(top_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \
$(gdb_string_h) $(gdbthread_h) $(gdbcmd_h) $(exec_h) $(solist_h) \
$(solib_h) $(i386_tdep_h) $(i387_tdep_h) $(gdb_obstack_h) \
- $(xml_support_h) $(i386_cygwin_tdep_h) $(gdb_stdint_h)
+ $(xml_support_h) $(safe_ctype_h) $(i386_cygwin_tdep_h) $(gdb_stdint_h)
win32-termcap.o: win32-termcap.c
wrapper.o: wrapper.c $(defs_h) $(value_h) $(exceptions_h) $(wrapper_h) \
$(ui_out_h)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-28 1:35 PR/2386 [2/2]: MinGW attach to process without an exec file Pedro Alves
@ 2007-12-28 4:33 ` Christopher Faylor
2007-12-29 3:37 ` Pedro Alves
2007-12-29 11:33 ` Eli Zaretskii
1 sibling, 1 reply; 26+ messages in thread
From: Christopher Faylor @ 2007-12-28 4:33 UTC (permalink / raw)
To: gdb-patches
On Fri, Dec 28, 2007 at 01:21:32AM +0000, Pedro Alves wrote:
> The target_pid_to_exec_file MinGW implementation
> win32-nat.c:win32_pid_to_exec_file is currently an empty stub,
> as I mentioned on http://sourceware.org/ml/gdb/2007-10/msg00104.html.
>
> This patch fills the gap. The patch covers 9x/NT, and tries to
> work even if psapi.dll isn't present, as it isn't part of
> the OS. To do that, it has to resort to non documented
> NT funcionality... If that doesn't work, it falls back
> into using psapi.dll. I'd be very happy if someone could
> point me at better ways to get at executable from a PID on
> Windows, or at a filename from a file handle. Note that de
> documented way to use a mapping relies on psapi.dll.
>
> This is also useful when debugging a native win32 app
> from a Cygwin gdb.
>
> Tested on XP Pro SP2, i686-pc-cygwin, no changes.
>
> OK ?
I'm not going to comment on the MinGW aspects of this other than to note
that I think it is rather intrusive and I don't worrying about ancient
Windows versions is a good idea.
If you want to get the process name from a cygwin pid you just use the
/proc interface.
cgf
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-28 4:33 ` Christopher Faylor
@ 2007-12-29 3:37 ` Pedro Alves
2007-12-29 3:50 ` Joel Brobecker
` (2 more replies)
0 siblings, 3 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-29 3:37 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1840 bytes --]
Christopher Faylor wrote:
> I'm not going to comment on the MinGW aspects of this other than to note
> that I think it is rather intrusive and I don't worrying about ancient
> Windows versions is a good idea.
>
Then we should document it somewhere, that we don't support
Windows 9x anymore. Maybe in the NEWS file ?
Can we reach a compromise here ? I've removed the 9x support from this
patch. With the changes inplace, win32_pid_to_exec_file
- 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 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,
- If that fails, GetModuleFileNameEx from psapi.dll is used.
The rest of the patch is just refactoring the psapi.dll loading
into its own function, not closing the file handle immediatelly, and
auxilary static functions to keep the code readable.
The enabling of the extra methods on Cygwin removes the need to
implement this TODO:
"TODO: Also find native Windows processes using CW_GETPINFO_FULL."
... which is useful for attaching to apps built with
'gcc -mno-cygwin' with a Cygwin gdb.
> If you want to get the process name from a cygwin pid you just use the
> /proc interface.
>
Not useful in this case, as the pid gdb holds is the native Windows pid.
Hence current usage of cygwin_internal (CW_GETPINFO, ...).
(I have a patch to clean up the ptid_t usage in win32-nat.c which
removes that "PID isn't a valid pid, unfortunately" limitation ... )
> cgf
>
--
Pedro Alves
[-- Attachment #2: win32_pid_to_exec_file.diff --]
[-- Type: text/x-diff, Size: 11731 bytes --]
2007-12-28 Pedro Alves <pedro_alves@portugalmail.pt>
PR gdb/2386
* win32-nat.c: Include "ntdef.h", "wchar.h" and "safe-ctype.h".
(current_process_file_handle): New variable.
(load_psapi): New function.
(psapi_get_dll_name): Use load_psapi.
(get_win32_debug_event): Don't close the process file handle.
Store it in current_process_file_handle.
(do_initial_win32_stuff): Clear current_process_file_handle.
(pid_to_exec_file_psapi, device_filename_to_dos_filename): New
functions.
(OBJECT_INFO_CLASS, OBJECT_NAME_INFO): New structs.
(NTQUERYOBJECT): New variable.
(get_nt_object_name, get_file_name_from_handle_objname)
(win32_pid_to_exec_file): Also find native Windows processes.
(win32_mourn_inferior): Close current_process_file_handle.
* Makefile.in (win32-nat.o): Add dependency on $(safe_ctype_h).
---
gdb/Makefile.in | 2
gdb/win32-nat.c | 262 +++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 214 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-28 22:30:48.000000000 +0000
@@ -38,6 +38,9 @@
#include <stdlib.h>
#include <windows.h>
#include <imagehlp.h>
+#include <psapi.h>
+#include <ntdef.h>
+#include <wchar.h>
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
@@ -57,6 +60,7 @@
#include "solist.h"
#include "solib.h"
#include "xml-support.h"
+#include "safe-ctype.h"
#include "i386-tdep.h"
#include "i387-tdep.h"
@@ -84,7 +88,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
@@ -135,6 +138,8 @@ static thread_info thread_head;
static DEBUG_EVENT current_event; /* The current debug event from
WaitForDebugEvent */
static HANDLE current_process_handle; /* Currently executing process */
+static HANDLE current_process_file_handle; /* Currently executing
+ process' file handle */
static thread_info *current_thread; /* Info on currently selected thread */
static DWORD main_thread_id; /* Thread ID of the main thread */
@@ -463,6 +468,28 @@ static BOOL WINAPI (*psapi_GetModuleInfo
static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
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)
{
DWORD len;
@@ -473,29 +500,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,
@@ -1345,7 +1356,7 @@ get_win32_debug_event (int pid, struct t
(unsigned) current_event.dwProcessId,
(unsigned) current_event.dwThreadId,
"CREATE_PROCESS_DEBUG_EVENT"));
- CloseHandle (current_event.u.CreateProcessInfo.hFile);
+ current_process_file_handle = current_event.u.CreateProcessInfo.hFile;
if (++saw_create != 1)
break;
@@ -1507,8 +1518,9 @@ do_initial_win32_stuff (DWORD pid)
#ifdef __CYGWIN__
cygwin_load_start = cygwin_load_end = 0;
#endif
- current_event.dwProcessId = pid;
memset (¤t_event, 0, sizeof (current_event));
+ current_event.dwProcessId = pid;
+ current_process_file_handle = INVALID_HANDLE_VALUE;
push_target (&win32_ops);
disable_breakpoints_in_shlibs ();
win32_clear_solib ();
@@ -1727,38 +1739,184 @@ win32_detach (char *args, int from_tty)
unpush_target (&win32_ops);
}
+static BOOL
+pid_to_exec_file_psapi (DWORD pid, char *pathbuf)
+{
+ BOOL ok = FALSE;
+
+ load_psapi ();
+
+ if (psapi_GetModuleFileNameExA != NULL)
+ {
+ HANDLE h;
+ h = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, pid);
+ if (h != NULL)
+ {
+ if (psapi_GetModuleFileNameExA (h, 0, pathbuf, MAX_PATH) > 0)
+ ok = TRUE;
+ CloseHandle (h);
+ }
+ }
+
+ return ok;
+}
+
+/* Translate a Windows path with device name to a dos style path with
+ drive letters.
+ E.g.:
+ "\\Device\\HarddiskVolume1\\cygwin\\bin\\cat.exe"
+ -> "c:\\cygwin\\bin\\cat.exe"
+*/
+static BOOL
+device_filename_to_dos_filename (char *out, const char *in, size_t outsize)
+{
+ char drive[] = "_:";
+ char all_drives[0x1000];
+ char devices[MAX_PATH + 1];
+ char *p;
+
+ /* A NULL terminated list of NULL terminated strings. */
+ if (!GetLogicalDriveStrings (sizeof all_drives - 1, all_drives))
+ return FALSE;
+
+ p = all_drives;
+ while (*p)
+ {
+ /* Copy the drive letter to the template string. */
+ *drive = *p;
+
+ /* Look up each device name. DEVICES is a NULL terminated list
+ of NULL terminated strings. */
+ if (QueryDosDevice (drive, devices, sizeof devices - 1))
+ {
+ size_t len = strlen (devices);
+ if (len < MAX_PATH
+ && (in[len] == '\\' || in[len] == '\0')
+ && strncasecmp (in, devices, len) == 0)
+ {
+ /* Reconstruct the filename by replacing the device path
+ with a DOS drive path. */
+ snprintf (out, outsize, "%s%s", drive, in + len);
+ return TRUE;
+ }
+ }
+
+ /* Next drive letter. */
+ while (*p++)
+ ;
+ }
+
+ return FALSE;
+}
+
+typedef enum tagOBJECT_INFO_CLASS
+{
+ ObjectNameInfo = 1,
+} OBJECT_INFO_CLASS;
+
+typedef struct tagOBJECT_NAME_INFO
+{
+ UNICODE_STRING ObjectName;
+ WCHAR ObjectNameBuffer[1];
+} OBJECT_NAME_INFO;
+
+typedef NTSTATUS (NTAPI *NTQUERYOBJECT)(HANDLE, OBJECT_INFO_CLASS,
+ PVOID, ULONG, PULONG);
+static BOOL
+get_nt_object_name (HANDLE h, char *namebuf)
+{
+ BOOL ok = FALSE;
+ HMODULE ntdll = GetModuleHandle ("ntdll.dll");
+ NTQUERYOBJECT NtQueryObject
+ = (NTQUERYOBJECT) GetProcAddress (ntdll, "NtQueryObject");
+
+ size_t size = sizeof (OBJECT_NAME_INFO) + (MAX_PATH + 1) * sizeof (WCHAR);
+ OBJECT_NAME_INFO *nameinfo = xmalloc (size);
+
+ NTSTATUS rc = NtQueryObject (h, ObjectNameInfo, nameinfo, size, NULL);
+ if (rc == STATUS_SUCCESS)
+ {
+ wchar_t *wname = nameinfo->ObjectName.Buffer;
+ wcstombs (namebuf, wname, wcslen (wname) + 1);
+ ok = TRUE;
+ }
+
+ xfree (nameinfo);
+ return ok;
+}
+
+static BOOL
+get_file_name_from_handle_objname (HANDLE file, char *pathbuf)
+{
+ char buf[MAX_PATH + 1];
+ return (file != INVALID_HANDLE_VALUE
+ && get_nt_object_name (file, buf)
+ && device_filename_to_dos_filename (pathbuf, buf, MAX_PATH)
+ && ISALPHA (pathbuf[0]) && pathbuf[1] == ':');
+}
+
+/* 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
+ static char path[MAX_PATH + 1];
+ BOOL ok = FALSE;
+
+ /* PID isn't a valid pid, unfortunately. Use current_event.dwProcessId
instead. */
+ pid = current_event.dwProcessId;
- static char path[MAX_PATH + 1];
- char *path_ptr = NULL;
+#ifdef __CYGWIN__
+ {
+ /* 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
+ /* Try with native NT functionality. This only works if
+ pid == current_event.dwProcessId. */
+ if (!ok
+ && pid == current_event.dwProcessId
+ && get_file_name_from_handle_objname (current_process_file_handle,
+ path))
+ ok = TRUE;
+
+ /* Fallback to trying with PSAPI. */
+ if (!ok && pid_to_exec_file_psapi (pid, path))
+ ok = TRUE;
+
+ if (ok)
+ {
#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;
- }
- }
- cygwin_internal (CW_UNLOCK_PINFO);
+ 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. */
@@ -1916,8 +2074,14 @@ win32_mourn_inferior (void)
if (open_process_used)
{
CHECK (CloseHandle (current_process_handle));
+ current_process_handle = NULL;
open_process_used = 0;
}
+ if (current_process_file_handle != INVALID_HANDLE_VALUE)
+ {
+ CHECK (CloseHandle (current_process_file_handle));
+ current_process_file_handle = INVALID_HANDLE_VALUE;
+ }
unpush_target (&win32_ops);
generic_mourn_inferior ();
}
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in 2007-12-28 22:29:46.000000000 +0000
+++ src/gdb/Makefile.in 2007-12-28 22:30:48.000000000 +0000
@@ -2946,7 +2946,7 @@ win32-nat.o: win32-nat.c $(defs_h) $(fra
$(regcache_h) $(top_h) $(buildsym_h) $(symfile_h) $(objfiles_h) \
$(gdb_string_h) $(gdbthread_h) $(gdbcmd_h) $(exec_h) $(solist_h) \
$(solib_h) $(i386_tdep_h) $(i387_tdep_h) $(gdb_obstack_h) \
- $(xml_support_h) $(i386_cygwin_tdep_h) $(gdb_stdint_h)
+ $(xml_support_h) $(safe_ctype_h) $(i386_cygwin_tdep_h) $(gdb_stdint_h)
win32-termcap.o: win32-termcap.c
wrapper.o: wrapper.c $(defs_h) $(value_h) $(exceptions_h) $(wrapper_h) \
$(ui_out_h)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 3:37 ` Pedro Alves
@ 2007-12-29 3:50 ` Joel Brobecker
2007-12-29 11:47 ` Eli Zaretskii
2007-12-29 5:42 ` Joel Brobecker
2007-12-29 11:41 ` Eli Zaretskii
2 siblings, 1 reply; 26+ messages in thread
From: Joel Brobecker @ 2007-12-29 3:50 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> Then we should document it somewhere, that we don't support
> Windows 9x anymore. Maybe in the NEWS file ?
I personally don't mind declaring the end of support for 9x and NT. But,
we don't necessarily have to be that extreme - We could still support
Windows 9x but with limitations. Being able to attach the debugger
to a PID without specifying the executable is not a critical feature,
and if the rest is known to work, it's still a very fine debugger.
BTW: Pedro, thanks very much for your work on the Windows port.
--
Joel
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 3:37 ` Pedro Alves
2007-12-29 3:50 ` Joel Brobecker
@ 2007-12-29 5:42 ` Joel Brobecker
2007-12-29 12:59 ` Pedro Alves
2007-12-29 11:41 ` Eli Zaretskii
2 siblings, 1 reply; 26+ messages in thread
From: Joel Brobecker @ 2007-12-29 5:42 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
I have a couple of questions, out of curiosity...
> Can we reach a compromise here ? I've removed the 9x support from this
> patch. With the changes inplace, win32_pid_to_exec_file
>
> - 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?
> - 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,
If you propose another fallback approach, it means that this would
not necessarily work all the time. Do you know when it wouldn't work?
If you do, then perhaps we could document this in the code.
> - 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.
--
Joel
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-28 1:35 PR/2386 [2/2]: MinGW attach to process without an exec file Pedro Alves
2007-12-28 4:33 ` Christopher Faylor
@ 2007-12-29 11:33 ` Eli Zaretskii
2007-12-29 14:33 ` Pedro Alves
1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-29 11:33 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, bodzio131
> Date: Fri, 28 Dec 2007 01:21:32 +0000
> From: Pedro Alves <pedro_alves@portugalmail.pt>
> CC: Bogdan Slusarczyk <bodzio131@op.pl>
>
> This patch fills the gap. The patch covers 9x/NT, and tries to
> work even if psapi.dll isn't present, as it isn't part of
> the OS. To do that, it has to resort to non documented
> NT funcionality...
Sorry, I don't understand: NT functionality is not relevant to Windows
9x, is it? So could you please say in more detail what undocumented
APIs you had in mind, and why are they necessary on modern Windows
systems?
> I'd be very happy if someone could
> point me at better ways to get at executable from a PID on
> Windows, or at a filename from a file handle.
Better ways than what? Perhaps I misunderstood the patch, but it
looks like you are using Process32First on Windows 9x, which is a
perfectly good way. What am I missing?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 3:37 ` Pedro Alves
2007-12-29 3:50 ` Joel Brobecker
2007-12-29 5:42 ` Joel Brobecker
@ 2007-12-29 11:41 ` Eli Zaretskii
2 siblings, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-29 11:41 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> Date: Fri, 28 Dec 2007 22:34:08 +0000
> From: Pedro Alves <pedro_alves@portugalmail.pt>
>
> Christopher Faylor wrote:
> > I'm not going to comment on the MinGW aspects of this other than to note
> > that I think it is rather intrusive and I don't worrying about ancient
> > Windows versions is a good idea.
> >
> [...]
> Can we reach a compromise here ? I've removed the 9x support from this
> patch. With the changes inplace, win32_pid_to_exec_file
>
> - 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 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,
> - If that fails, GetModuleFileNameEx from psapi.dll is used.
I'm not sure this version is significantly less intrusive than the
original one, but that's for Chris to judge (FWIW, I didn't see much
of intrusiveness in the original patch).
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 3:50 ` Joel Brobecker
@ 2007-12-29 11:47 ` Eli Zaretskii
2007-12-29 14:02 ` Lerele
0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-29 11:47 UTC (permalink / raw)
To: Joel Brobecker; +Cc: pedro_alves, gdb-patches
> Date: Fri, 28 Dec 2007 19:42:28 -0800
> From: Joel Brobecker <brobecker@adacore.com>
> Cc: gdb-patches@sourceware.org
>
> > Then we should document it somewhere, that we don't support
> > Windows 9x anymore. Maybe in the NEWS file ?
>
> I personally don't mind declaring the end of support for 9x and NT.
I do. Many 3rd-world countries still have lots of users of older
systems, and I don't think we should drop their support as yet.
Granted, if Cygwin maintainers don't care about older Windows, then the
Cygwin port of GDB doesn't have to, either. But the native MinGW port
does not have to automatically follow that suit, IMO.
As I wrote elsewhere, the Windows 9x support in the original patch was
not too hairy, IMO; most of the hair was due to NT support in some
situations which I don't understand yet (see my questions to Pedro).
So perhaps even limiting 9x support is not necessary.
> But,
> we don't necessarily have to be that extreme - We could still support
> Windows 9x but with limitations. Being able to attach the debugger
> to a PID without specifying the executable is not a critical feature,
> and if the rest is known to work, it's still a very fine debugger.
I can live with this limitation, provided that:
. We state it in the manual, and
. GDB issues a clear error message when asked to attach to a process
by PID alone, and is unable to figure out the executable file name.
> BTW: Pedro, thanks very much for your work on the Windows port.
Seconded.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 5:42 ` Joel Brobecker
@ 2007-12-29 12:59 ` Pedro Alves
2007-12-29 14:35 ` Pedro Alves
2007-12-29 18:48 ` Christopher Faylor
0 siblings, 2 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-29 12:59 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2107 bytes --]
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
[-- Attachment #2: win32_pid_to_exec_file.diff --]
[-- Type: text/x-diff, Size: 6462 bytes --]
2007-12-28 Pedro Alves <pedro_alves@portugalmail.pt>
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 <stdlib.h>
#include <windows.h>
#include <imagehlp.h>
+#include <psapi.h>
#ifdef __CYGWIN__
#include <sys/cygwin.h>
#endif
@@ -84,7 +85,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
@@ -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. */
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 11:47 ` Eli Zaretskii
@ 2007-12-29 14:02 ` Lerele
0 siblings, 0 replies; 26+ messages in thread
From: Lerele @ 2007-12-29 14:02 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Joel Brobecker, pedro_alves, gdb-patches
Eli Zaretskii escribió:
>> Date: Fri, 28 Dec 2007 19:42:28 -0800
>> From: Joel Brobecker <brobecker@adacore.com>
>> Cc: gdb-patches@sourceware.org
>>
>>
>>> Then we should document it somewhere, that we don't support
>>> Windows 9x anymore. Maybe in the NEWS file ?
>>>
>> I personally don't mind declaring the end of support for 9x and NT.
>>
>
> I do. Many 3rd-world countries still have lots of users of older
> systems, and I don't think we should drop their support as yet.
>
> Granted, if Cygwin maintainers don't care about older Windows, then the
> Cygwin port of GDB doesn't have to, either. But the native MinGW port
> does not have to automatically follow that suit, IMO.
>
>
My vote for this one, if it matters. Didn't dare to say it before. Heh.
Plenty of users do still use older Windowses.
If a developer wants to target a Win9x box he/she needs proper debugging
on these, or if a developer is completely hosted on Win9x.
Please do keep in mind these cases, at least for MinGW as Eli says.
> As I wrote elsewhere, the Windows 9x support in the original patch was
> not too hairy, IMO; most of the hair was due to NT support in some
> situations which I don't understand yet (see my questions to Pedro).
> So perhaps even limiting 9x support is not necessary.
>
>
>> But,
>> we don't necessarily have to be that extreme - We could still support
>> Windows 9x but with limitations. Being able to attach the debugger
>> to a PID without specifying the executable is not a critical feature,
>> and if the rest is known to work, it's still a very fine debugger.
>>
>
> I can live with this limitation, provided that:
>
> . We state it in the manual, and
>
> . GDB issues a clear error message when asked to attach to a process
> by PID alone, and is unable to figure out the executable file name.
>
>
>> BTW: Pedro, thanks very much for your work on the Windows port.
>>
>
> Seconded.
>
>
"Thirded".
Quite impressive.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 11:33 ` Eli Zaretskii
@ 2007-12-29 14:33 ` Pedro Alves
2007-12-29 16:08 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Pedro Alves @ 2007-12-29 14:33 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches, bodzio131
Eli Zaretskii wrote:
>
> Sorry, I don't understand: NT functionality is not relevant to Windows
> 9x, is it? So could you please say in more detail what undocumented
> APIs you had in mind, and why are they necessary on modern Windows
> systems?
>
>> I'd be very happy if someone could
>> point me at better ways to get at executable from a PID on
>> Windows, or at a filename from a file handle.
>
> Better ways than what? Perhaps I misunderstood the patch, but it
> looks like you are using Process32First on Windows 9x, which is a
> perfectly good way. What am I missing?
>
I wasn't talking about 9x, there we always have ToolHelp32 available.
I meant better ways to get at the full path to the image from a
pid *on NT* without using NtQueryObject (ObjectNameInfo), which I
don't think we can rely on to always work, or relying on
having psapi.dll available.
--
Pedro Alves
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 12:59 ` Pedro Alves
@ 2007-12-29 14:35 ` Pedro Alves
2007-12-29 18:48 ` Christopher Faylor
1 sibling, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-29 14:35 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- 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. */
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 14:33 ` Pedro Alves
@ 2007-12-29 16:08 ` Eli Zaretskii
2007-12-30 0:30 ` Pedro Alves
0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-29 16:08 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches, bodzio131
> Date: Sat, 29 Dec 2007 14:26:26 +0000
> From: Pedro Alves <pedro_alves@portugalmail.pt>
> CC: gdb-patches@sourceware.org, bodzio131@op.pl
>
> > Better ways than what? Perhaps I misunderstood the patch, but it
> > looks like you are using Process32First on Windows 9x, which is a
> > perfectly good way. What am I missing?
> >
>
> I wasn't talking about 9x, there we always have ToolHelp32 available.
> I meant better ways to get at the full path to the image from a
> pid *on NT* without using NtQueryObject (ObjectNameInfo), which I
> don't think we can rely on to always work, or relying on
> having psapi.dll available.
How about ToolHelp32: is that available on NT? If so, perhaps using
it instead of Nt* internal APIs is a better way?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 12:59 ` Pedro Alves
2007-12-29 14:35 ` Pedro Alves
@ 2007-12-29 18:48 ` Christopher Faylor
2007-12-29 20:15 ` Eli Zaretskii
2007-12-29 22:46 ` Pedro Alves
1 sibling, 2 replies; 26+ messages in thread
From: Christopher Faylor @ 2007-12-29 18:48 UTC (permalink / raw)
To: gdb-patches
On Sat, Dec 29, 2007 at 12:52:22PM +0000, Pedro Alves wrote:
> 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 ?
On Fri, 28 Dec 2007 22:34:08 +0000 , Pedro Alves wrote:
>Not useful in this case, as the pid gdb holds is the native Windows pid.
>Hence current usage of cygwin_internal (CW_GETPINFO, ...).
I do find this less intrusive but I don't understand the above comment.
Did you actually try using /proc and found it wanting? Finding a cygwin
exename should be as simple as just doing a readlink
("/proc/<pid>/exe"). I just tried this on a top-level process created
by cygwin and on the pid returned by typing "sleep 300&" in bash. The
sleep process does have two pids associated with it due to the oddities
of the way that cygwin emulates exec but "ls -l /proc/<pid>/exe" showed
"/bin/sleep.exe" in each case.
For the rest of the code, have you investigated
"NtQuerySystemInformation"? I don't know if it contains everything
needed but, despite what the Microsoft site says, it seems to have had a
stable interface for years and I don't see how Microsoft could change
the functionality without breaking lots of stuff. I think it would be
better to adopt to probably nonexistent future API changes than it is
to rely on a DLL which may not be there. I've always had a problem with
the psapi.h stuff for just the reasons that you mentioned.
We use NtQuerySystemInformation in cygwin to return the list of
processes. See pinfo.cc.
For the Windows 9x case, I'd prefer if there was just a straightforward
error which indicated that what was being attempted is not available on
non-NT versions of Windows.
cgf
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 18:48 ` Christopher Faylor
@ 2007-12-29 20:15 ` Eli Zaretskii
2007-12-29 22:46 ` Pedro Alves
1 sibling, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-29 20:15 UTC (permalink / raw)
To: gdb-patches
> Date: Sat, 29 Dec 2007 13:01:46 -0500
> From: Christopher Faylor <cgf-use-the-mailinglist-please@sourceware.org>
>
> For the rest of the code, have you investigated
> "NtQuerySystemInformation"? I don't know if it contains everything
> needed but, despite what the Microsoft site says, it seems to have had a
> stable interface for years and I don't see how Microsoft could change
> the functionality without breaking lots of stuff.
Since in this case Nt* APIs are used for Windows NT, I think the
chances of Microsoft changing that API in that OS are strictly zero.
So it should safe to use that on NT. On other version of Windows, I
think there are documented solutions that don't use DLLs which might
be absent. Pedro, is that correct, or did I miss something?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
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:20 ` Eli Zaretskii
1 sibling, 2 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-29 22:46 UTC (permalink / raw)
To: gdb-patches
Christopher Faylor wrote:
>
> On Fri, 28 Dec 2007 22:34:08 +0000 , Pedro Alves wrote:
>> Not useful in this case, as the pid gdb holds is the native Windows pid.
>> Hence current usage of cygwin_internal (CW_GETPINFO, ...).
>
> I do find this less intrusive but I don't understand the above comment.
> Did you actually try using /proc and found it wanting? Finding a cygwin
> exename should be as simple as just doing a readlink
> ("/proc/<pid>/exe"). I just tried this on a top-level process created
> by cygwin and on the pid returned by typing "sleep 300&" in bash. The
> sleep process does have two pids associated with it due to the oddities
> of the way that cygwin emulates exec but "ls -l /proc/<pid>/exe" showed
> "/bin/sleep.exe" in each case.
>
From infcmd.c:attach_command :
/*
* If no exec file is yet known, try to determine it from the
* process itself.
*/
exec_file = (char *) get_exec_file (0);
if (!exec_file)
{
exec_file = target_pid_to_exec_file (PIDGET (inferior_ptid));
if (exec_file)
{
So, the pid that is passed is what's stored in inferior_ptid.
It happens, that the win32-nat.c implementation stuff *thread* ids
in ptid_t structs, so PIDGET (inferior_ptid) extracts the current
inferior thread id -- not very useful for target_pid_to_exec_file,
hence the following comment in the current version of
win32_pid_to_exec_file:
/* Try to find the process path using the Cygwin internal process list
pid isn't a valid pid, unfortunately. Use current_event.dwProcessId
instead. */
(That's the I-have-a-patch-to-clean-that-up part. But even then,
PIDGET(inferior_ptid) will be the winpid. We have room for it in the
ptid_t, though, in the form of a lwp. Note, *that* patch will
be invasive :-) )
What's stored in current_event.dwProcessId is a Windows PID, not a Cygwin
pid. In that case, /proc/<pid>/exe isn't helpful, unless we can query Cygwin
for the cygpid associated with this pid, or we look though all the /proc/<pid>s
looking at a matching `cat /proc/<cygpid>/winpid`.
>sleep 300&
[3] 3848
[2] Exit 1 sleep
>cat /proc/3848/winpid
1788
Is there a reverse of CW_CYGWIN_PID_TO_WINPID ?
Even if the user specifies a cygwin pid to gdb --pid <cygpid>, win32_attach
does this:
/* Attach to process PID, then initialize for debugging it. */
static void
win32_attach (char *args, int from_tty)
{
BOOL ok;
DWORD pid;
pid = strtoul (args, 0, 0); /* Windows pid */
ok = DebugActiveProcess (pid);
if (!ok)
{
/* Try fall back to Cygwin pid */
pid = cygwin_internal (CW_CYGWIN_PID_TO_WINPID, pid);
if (pid > 0)
ok = DebugActiveProcess (pid);
}
We're calling win32 debug functions, so we internally
always care for the Windows pid.
Please do note that I'm not writting that part of the patch.
That Cygwin specific code is already there. That is not to say
that I won't change it if you tell me how to get the winpid from
a cygwin pid.
> For the rest of the code, have you investigated
> "NtQuerySystemInformation"? I don't know if it contains everything
> needed but, despite what the Microsoft site says, it seems to have had a
> stable interface for years and I don't see how Microsoft could change
> the functionality without breaking lots of stuff. I think it would be
> better to adopt to probably nonexistent future API changes than it is
> to rely on a DLL which may not be there. I've always had a problem with
> the psapi.h stuff for just the reasons that you mentioned.
>
I'm not sure if psapi.dll is that problematic. It should be
quite widespread by now. Googling around shows that IE7 comes
with it, for instance. In fact, google shows a lot of people with
some app that doesn't load, because they have several versions
of psapi.dll on the system, and the wrong version is being loaded.
Following the lead of a lot of apps, we could *require* it, and
instruct the user to get it, if it isn't found.
For kickers, I took a quick peek at Wine's implementation of
psapi.dll, and it was looking directly at PEB structures and
similar stuff -- those probably are even less stable.
There's a new API in Vista that gives us what we want, but
I forgot it's name, and can't re-find it... argh...
In this particular case, I'm now inclined to just go for
psapi.dll and be done with it. We could load it in
_initialize_win32_nat and warn if we're on NT, and it
wasn't found ...
> We use NtQuerySystemInformation in cygwin to return the list of
> processes. See pinfo.cc.
>
Not fully useable, I did try it. The ProcessName field in the
SYSTEM_PROCESSES structure doesn't have a path, only the filename ...
I also looked into NtQueryInformationFile with FileNameInformation,
but that returns a file path starting from the root of the drive, that is:
\cygwin\bin\cat.exe, instead of \Device\Partition\cygwin\bin\cat.exe.
I couldn't find a way to get the drive letter from that info.
So, what shall I do ? I've already posted several patches with
different combinations, so please, let's decide what to use, then I'll
post a patch.
1 - ToolHelp32
- available on 9x, returns full path
- available on NT >= 2000, return filename only [1], not a full path.
Leaves NT4 out.
2 - PSAPI
- Available on NT only, as a seperate dll. I believe that on
2000, it comes with one of the service packs. XP, I believe
comes with it. I can't find anywhere specifying for sure
which versions of Windows are bundled with it. For all NT
versions, it can be downloaded from MSFT.
3 - NtQueryObject(ObjectNameInfo) on the file handle.
- Available on NT only, returns full path on XPSP2 at least.
- [2] Will only work on the current inferior. That is, if the
target_pid_to_exec_file is used for something, else
in the future, it will not work. But that is not a problem
currently.
4 - NtQueryInformationFile with FileNameInformation on the file handle.
- Available on NT only, returns semi-full path
relative to the drive base, but
- Same as [2] above.
5 - NtQuerySystemInformation
- Available on NT only, only returns filename [1], not a full path.
6 - Other ?
[1] - Gdb tries to cope with it, by looking for a match in the
debug info. Not very perfect, but the best it can be done.
In any case, we can put a warning in infcmd.c:attach_command,
when the exec file isn't found, instructing the user to use the
"file" command.
Looking at the options, I'd either go for '3 + 2 + 1' as in the
original patch, or just to '2 + 1' as in the latest patch. I'm
more inclined into just '2 + 1' like in:
http://sourceware.org/ml/gdb-patches/2007-12/msg00456.html
Chris, could you please take a peek at that patch ? I think
you may have missed it.
> For the Windows 9x case, I'd prefer if there was just a straightforward
> error which indicated that what was being attempted is not available on
> non-NT versions of Windows.
>
But why? It's not like supporting it in this case is hard. It can be
shoved in 30 lines of code, just getting at toolhelp, and iterating over
all the processes ... Pretty self contained, doesn't impact anything
else.
--
Pedro Alves
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 16:08 ` Eli Zaretskii
@ 2007-12-30 0:30 ` Pedro Alves
0 siblings, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-30 0:30 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches, bodzio131
Eli Zaretskii wrote:
> How about ToolHelp32: is that available on NT? If so, perhaps using
> it instead of Nt* internal APIs is a better way?
>
Only on NT >= 2000, and only returns the filename, not the
full path, unlike on 9x.
--
Pedro Alves
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
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:41 ` Pedro Alves
2007-12-30 4:20 ` Eli Zaretskii
1 sibling, 2 replies; 26+ messages in thread
From: Christopher Faylor @ 2007-12-30 3:07 UTC (permalink / raw)
To: gdb-patches
On Sat, Dec 29, 2007 at 10:43:47PM +0000, Pedro Alves wrote:
> Christopher Faylor wrote:
>> On Fri, 28 Dec 2007 22:34:08 +0000 , Pedro Alves wrote:
>>> Not useful in this case, as the pid gdb holds is the native Windows pid.
>>> Hence current usage of cygwin_internal (CW_GETPINFO, ...).
>> I do find this less intrusive but I don't understand the above comment.
>> Did you actually try using /proc and found it wanting? Finding a cygwin
>> exename should be as simple as just doing a readlink
>> ("/proc/<pid>/exe"). I just tried this on a top-level process created
>> by cygwin and on the pid returned by typing "sleep 300&" in bash. The
>> sleep process does have two pids associated with it due to the oddities
>> of the way that cygwin emulates exec but "ls -l /proc/<pid>/exe" showed
>> "/bin/sleep.exe" in each case.
>
> /* Try to find the process path using the Cygwin internal process list
> pid isn't a valid pid, unfortunately. Use current_event.dwProcessId
> instead. */
>
> (That's the I-have-a-patch-to-clean-that-up part. But even then,
> PIDGET(inferior_ptid) will be the winpid. We have room for it in the
> ptid_t, though, in the form of a lwp. Note, *that* patch will
> be invasive :-) )
>
>What's stored in current_event.dwProcessId is a Windows PID, not a
>Cygwin pid. In that case, /proc/<pid>/exe isn't helpful, unless we can
>query Cygwin for the cygpid associated with this pid, or we look though
>all the /proc/<pid>s looking at a matching `cat /proc/<cygpid>/winpid`.
I'm familiar with the difference between windows pids and Cygwin pids.
In many cases they are the same and, when they aren't, there should
still be a /proc entry for the windows pid associated with the Cygwin
process, which is what I was saying above.
bash-3.2$ sleep 300&
[1] 1560
bash-3.2$ ps
PID PPID PGID WINPID TTY UID STIME COMMAND
2332 1 2332 2332 con 1003 12:53:53 /bin/bash
1560 2332 1560 2576 con 1003 18:42:59 /bin/sleep
2920 2332 2920 3108 con 1003 18:43:01 /bin/ps
bash-3.2$ ls -l /proc/1560/exe
lrwxrwxrwx 1 cgf None 0 Nov 30 2006 exe -> /bin/sleep.exe
bash-3.2$ ls -l /proc/2576/exe
lrwxrwxrwx 1 cgf None 0 Nov 30 2006 exe -> /bin/sleep.exe
For exec'ed stubs you won't see the windows pid entry if you 'ls /proc'
but it is there if you query it.
/proc wasn't available when win32-nat.c was first written but it is now
so it should be used rather than querying an internal cygwin function.
The comment that you are referring to and the code around it is
out-of-date.
> Please do note that I'm not writting that part of the patch.
> That Cygwin specific code is already there. That is not to say
> that I won't change it if you tell me how to get the winpid from
> a cygwin pid.
I didn't catch that before but I'd prefer if you are going to be
refactoring the code that it use /proc. This interface has been
available in cygwin for about five years so gdb is overdue for this.
>> We use NtQuerySystemInformation in cygwin to return the list of
>> processes. See pinfo.cc.
>
> Not fully useable, I did try it. The ProcessName field in the
> SYSTEM_PROCESSES structure doesn't have a path, only the filename ...
>it isn't found.
Ok. After some additional digging and memory jogging, I see that Cygwin
actually uses GetModuleFileNameEx to retrieve this information after
iterating over the processes using NtQuerySystemInformation and
GetModuleFileNameEx comes from psapi.dll. So it seems like psapi.dll is
still the best solution.
I don't think that finding people with an app that doesn't load because
there are wrong versions of the DLL being loaded is a great
advertisement for psapi.dll. However, I don't recall anyone complaining
about problems in Cygwin with "ps -W" not working and gdb has been using
psapi for a while now so it probably isn't a big deal.
Rather than go back and forth on this, I've taken a stab at implementing
what I'm trying to get across here. I don't think there is any reason to
now add Windows 9x support for features that have been missing for years
so I didn't do that. I did issue an error when psapi.dll was not found
however. I also added some of those slash-star/star-slash things.
I'll check this in unless there are serious objections.
cgf
2007-12-29 Christopher Faylor <me+gdb@cgf.cx>
* win32-nat.c (psapi_module_handle): Remove static.
(get_module_name): Rename from psapi_get_dll_name. Revamp slightly to
return first module found if base_address is zero. Don't initialize
psapi function pointers here. Convert to cygwin paths when
appropriate.
(win32_pid_to_exec_file): Use Cygwin's /proc interface to determine
executable name. Use get_module_name when that fails or when
!__CYGWIN__.
(_initialize_psapi): New function. Initialize psapi stuff before it is
needed or issue a warning if it is not found. Move psapi_module_handle
here.
Index: win32-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/win32-nat.c,v
retrieving revision 1.144
diff -d -u -r1.144 win32-nat.c
--- win32-nat.c 22 Dec 2007 22:09:56 -0000 1.144
+++ win32-nat.c 30 Dec 2007 02:57:11 -0000
@@ -457,88 +457,78 @@
}
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);
+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). */
static int
-psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+get_module_name (DWORD base_address, char *dll_name_ret)
{
DWORD len;
MODULEINFO mi;
int i;
HMODULE dh_buf[1];
- HMODULE *DllHandle = dh_buf;
+ HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
DWORD cbNeeded;
- BOOL ok;
+#ifdef __CYGWIN__
+ char pathbuf[PATH_MAX + 1]; /* Temporary storage prior to converting to
+ posix form */
+#else
+ char *pathbuf = dll_name_ret; /* Just copy directly to passed-in arg */
+#endif
- 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 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;
- ok = (*psapi_EnumProcessModules) (current_process_handle,
- DllHandle,
- sizeof (HMODULE),
- &cbNeeded);
-
- if (!ok || !cbNeeded)
+ /* Find size of buffer needed to handle list of modules loaded in inferior */
+ if (!psapi_EnumProcessModules (current_process_handle, DllHandle,
+ sizeof (HMODULE), &cbNeeded) || !cbNeeded)
goto failed;
+ /* Allocate correct amount of space for module list */
DllHandle = (HMODULE *) alloca (cbNeeded);
if (!DllHandle)
goto failed;
- ok = (*psapi_EnumProcessModules) (current_process_handle,
- DllHandle,
- cbNeeded,
- &cbNeeded);
- if (!ok)
+ /* Get the list of modules */
+ if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
+ &cbNeeded))
goto failed;
for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
{
- if (!(*psapi_GetModuleInformation) (current_process_handle,
- DllHandle[i],
- &mi,
- sizeof (mi)))
+ /* Get information on this module */
+ if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
+ &mi, sizeof (mi)))
error (_("Can't get module info"));
- len = (*psapi_GetModuleFileNameExA) (current_process_handle,
- DllHandle[i],
- dll_name_ret,
- MAX_PATH);
- if (len == 0)
- error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
-
- if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
- return 1;
+ if (!base_address || (DWORD) (mi.lpBaseOfDll) == base_address)
+ {
+ /* Try to find the name of the given module */
+ len = psapi_GetModuleFileNameExA (current_process_handle,
+ DllHandle[i], pathbuf, MAX_PATH);
+ if (len == 0)
+ error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
+#ifdef __CYGWIN__
+ /* Cygwin prefers that the path be in /x/y/z format */
+ cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret);
+#endif
+ return 1; /* success */
+ }
}
failed:
dll_name_ret[0] = '\0';
- return 0;
+ return 0; /* failure */
}
/* Encapsulate the information required in a call to
@@ -745,7 +735,7 @@
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
- if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
+ if (!get_module_name ((DWORD) event->lpBaseOfDll, dll_buf))
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
dll_name = dll_buf;
@@ -1730,35 +1720,27 @@
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;
#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)
+ /* Try to find exe name as symlink target of /proc/<pid>/exe */
+ int nchars;
+ char procexe[sizeof ("/proc/4294967295/exe")];
+ sprintf (procexe, "/proc/%lu/exe", current_event.dwProcessId);
+ nchars = readlink (procexe, path, sizeof(path));
+ if (nchars > 0 && nchars < sizeof (path))
{
- if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */
- {
- cygwin_conv_to_full_posix_path (pinfo->progname, path);
- path_ptr = path;
- break;
- }
+ path[nchars] = '\0'; /* Got it */
+ return path;
}
- cygwin_internal (CW_UNLOCK_PINFO);
#endif
- return path_ptr;
+ /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
+ of gdb, or we're trying to debug a non-Cygwin windows executable. */
+ if (!get_module_name (0, path))
+ path[0] = '\0';
+
+ return path;
}
/* Print status information about what we're accessing. */
@@ -2282,3 +2264,34 @@
}
}
}
+
+void
+_initialize_psapi (void)
+{
+ /* Load optional functions used for retrieving filename information
+ associated with the currently debugged process or its dlls. */
+ if (!psapi_loaded)
+ {
+ HMODULE psapi_module_handle;
+
+ psapi_loaded = -1;
+
+ 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;
+ }
+ }
+
+ /* This will probably fail on Windows 9x/Me. Let the user know that we're
+ missing some functionality. */
+ if (psapi_loaded < 0)
+ warning(_("working version of psapi.dll not found. DLL and executable filenames may not be available."));
+}
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-29 22:46 ` Pedro Alves
2007-12-30 3:07 ` Christopher Faylor
@ 2007-12-30 4:20 ` Eli Zaretskii
2007-12-31 4:13 ` Pedro Alves
1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-30 4:20 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
> Date: Sat, 29 Dec 2007 22:43:47 +0000
> From: Pedro Alves <pedro_alves@portugalmail.pt>
>
> 2 - PSAPI
> - Available on NT only, as a seperate dll.
Are you sure it isn't available on 9x? I have a copy of a disk from
my older 9x machine, and I do see psapi.dll there.
> I believe that on
> 2000, it comes with one of the service packs. XP, I believe
> comes with it.
Yes, on my XP machine I see it as well.
> In any case, we can put a warning in infcmd.c:attach_command,
> when the exec file isn't found, instructing the user to use the
> "file" command.
Yes, if looking up the exec file fails, please issue a clear message.
I also requested for an update of the manual to state the limitations.
> > For the Windows 9x case, I'd prefer if there was just a straightforward
> > error which indicated that what was being attempted is not available on
> > non-NT versions of Windows.
> >
>
> But why? It's not like supporting it in this case is hard. It can be
> shoved in 30 lines of code, just getting at toolhelp, and iterating over
> all the processes ... Pretty self contained, doesn't impact anything
> else.
I also think that using ToolHelp32 is an okay solution of this.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-30 3:07 ` Christopher Faylor
@ 2007-12-30 4:32 ` Eli Zaretskii
2007-12-30 20:37 ` Christopher Faylor
2007-12-30 20:41 ` Pedro Alves
1 sibling, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-30 4:32 UTC (permalink / raw)
To: gdb-patches
> Date: Sat, 29 Dec 2007 21:57:54 -0500
> From: Christopher Faylor <cgf-use-the-mailinglist-please@sourceware.org>
>
> I don't think there is any reason to now add Windows 9x support for
> features that have been missing for years so I didn't do that. I
> did issue an error when psapi.dll was not found however.
> [...]
> + if (psapi_loaded < 0)
> + warning(_("working version of psapi.dll not found. DLL and executable filenames may not be available."));
This is not a useful message, IMHO. I, as a user, would not know what
to do with it. We need to says specifically that attach without an
exec file name will not work, and that users should use `file'
etc. commands to work around.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-30 4:32 ` Eli Zaretskii
@ 2007-12-30 20:37 ` Christopher Faylor
2007-12-31 6:35 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Christopher Faylor @ 2007-12-30 20:37 UTC (permalink / raw)
To: gdb-patches
On Sun, Dec 30, 2007 at 06:20:00AM +0200, Eli Zaretskii wrote:
>> Date: Sat, 29 Dec 2007 21:57:54 -0500
>> From: Christopher Faylor <cgf-use-the-mailinglist-please@sourceware.org>
>>
>> I don't think there is any reason to now add Windows 9x support for
>> features that have been missing for years so I didn't do that. I
>> did issue an error when psapi.dll was not found however.
>> [...]
>> + if (psapi_loaded < 0)
>> + warning(_("working version of psapi.dll not found. DLL and executable filenames may not be available."));
>
>This is not a useful message, IMHO. I, as a user, would not know what
>to do with it. We need to says specifically that attach without an
>exec file name will not work, and that users should use `file'
>etc. commands to work around.
Could you give me some exact wording, please? Is this adequate?
"working version of psapi.dll not found. Use `file' and `dll' commands to specifically load symbols."
?
Note, that this is actually an enhancement for what has existed in gdb
for years. I don't recall anyone ever complaining that things didn't
work in Windows 9x. But, then, unlike the nearly infinite number people
who use gdb on Windows 9x on an hourly basis, I've always found gdb to
be just barely usable on those systems due to OS bugs which result in
BSOD.
cgf
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-30 3:07 ` Christopher Faylor
2007-12-30 4:32 ` Eli Zaretskii
@ 2007-12-30 20:41 ` Pedro Alves
1 sibling, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-30 20:41 UTC (permalink / raw)
To: gdb-patches
Christopher Faylor wrote:
> In many cases they are the same and, when they aren't, there should
> still be a /proc entry for the windows pid associated with the Cygwin
> process, which is what I was saying above.
>
> For exec'ed stubs you won't see the windows pid entry if you 'ls /proc'
> but it is there if you query it.
Ah, OK. That's surprising. Nice.
> Rather than go back and forth on this, I've taken a stab at implementing
> what I'm trying to get across here. I don't think there is any reason to
> now add Windows 9x support for features that have been missing for years
> so I didn't do that.
I don't know if they were missing from the non FSF MinGW port of gdb,
but I won't go look either.
Sure. What happened was that now if the exec file wasn't found,
gdb would not see the dlls, since now the target_so_ops are
associated with current_gdbarch. That's what the PR is about.
Well, the 1/2 part of the patch also fixes that case, so it's OK.
> I'll check this in unless there are serious objections.
>
No, not from me. Thanks,
--
Pedro Alves
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-30 4:20 ` Eli Zaretskii
@ 2007-12-31 4:13 ` Pedro Alves
0 siblings, 0 replies; 26+ messages in thread
From: Pedro Alves @ 2007-12-31 4:13 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
Eli Zaretskii wrote:
>> 2 - PSAPI
>> - Available on NT only, as a seperate dll.
>
> Are you sure it isn't available on 9x? I have a copy of a disk from
> my older 9x machine, and I do see psapi.dll there.
>
Intriguing. Maybe it got installed by some app. If it's linked to
ntdll.dll, it won't load.
--
Pedro Alves
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-30 20:37 ` Christopher Faylor
@ 2007-12-31 6:35 ` Eli Zaretskii
2007-12-31 8:12 ` Christopher Faylor
0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-31 6:35 UTC (permalink / raw)
To: gdb-patches
> Date: Sun, 30 Dec 2007 12:08:28 -0500
> From: Christopher Faylor <cgf-use-the-mailinglist-please@sourceware.org>
>
> >> + warning(_("working version of psapi.dll not found. DLL and executable filenames may not be available."));
> >
> >This is not a useful message, IMHO. I, as a user, would not know what
> >to do with it. We need to says specifically that attach without an
> >exec file name will not work, and that users should use `file'
> >etc. commands to work around.
>
> Could you give me some exact wording, please? Is this adequate?
>
> "working version of psapi.dll not found. Use `file' and `dll' commands to specifically load symbols."
>
> ?
IMO, the first sentence is a technicality that doesn't help. How
about the following instead?
Cannot find executable file by PID. Use "file" and "dll" commands
to load symbols.
> Note, that this is actually an enhancement for what has existed in gdb
> for years.
Sure, but we want to improve things, right?
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-31 6:35 ` Eli Zaretskii
@ 2007-12-31 8:12 ` Christopher Faylor
2007-12-31 21:38 ` Eli Zaretskii
0 siblings, 1 reply; 26+ messages in thread
From: Christopher Faylor @ 2007-12-31 8:12 UTC (permalink / raw)
To: gdb-patches
On Mon, Dec 31, 2007 at 06:13:01AM +0200, Eli Zaretskii wrote:
>> Date: Sun, 30 Dec 2007 12:08:28 -0500
>> From: Christopher Faylor <cgf-use-the-mailinglist-please@sourceware.org>
>>
>> >> + warning(_("working version of psapi.dll not found. DLL and executable filenames may not be available."));
>> >
>> >This is not a useful message, IMHO. I, as a user, would not know what
>> >to do with it. We need to says specifically that attach without an
>> >exec file name will not work, and that users should use `file'
>> >etc. commands to work around.
>>
>> Could you give me some exact wording, please? Is this adequate?
>>
>> "working version of psapi.dll not found. Use `file' and `dll' commands to specifically load symbols."
>>
>> ?
>
>IMO, the first sentence is a technicality that doesn't help. How
>about the following instead?
>
> Cannot find executable file by PID. Use "file" and "dll" commands
> to load symbols.
That's not entirely accurate either since it's not just the ability to
load executable files by pid that is affected, it's also the ability to
figure out any dll names loaded in the executable.
Cannot determine correspondence between load addresses and dll/executable filenames. Use "file" and "dll" commands to load symbols.
?
>> Note, that this is actually an enhancement for what has existed in gdb
>> for years.
>
>Sure, but we want to improve things, right?
Uh, yeah. That's why I added the message. I wasn't sure you quite
understood that, for the most part, this wasn't new functionality.
cgf
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: PR/2386 [2/2]: MinGW attach to process without an exec file
2007-12-31 8:12 ` Christopher Faylor
@ 2007-12-31 21:38 ` Eli Zaretskii
0 siblings, 0 replies; 26+ messages in thread
From: Eli Zaretskii @ 2007-12-31 21:38 UTC (permalink / raw)
To: gdb-patches
> Date: Mon, 31 Dec 2007 01:35:34 -0500
> From: Christopher Faylor <cgf-use-the-mailinglist-please@sourceware.org>
>
> > Cannot find executable file by PID. Use "file" and "dll" commands
> > to load symbols.
>
> That's not entirely accurate either since it's not just the ability to
> load executable files by pid that is affected, it's also the ability to
> figure out any dll names loaded in the executable.
>
> Cannot determine correspondence between load addresses and dll/executable filenames. Use "file" and "dll" commands to load symbols.
>
> ?
Cannot find executable file or library to read symbols. Use "file"
or "dll" command to load executable/libraries directly.
?
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2007-12-31 21:01 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-12-28 1:35 PR/2386 [2/2]: MinGW attach to process without an exec file 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
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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox