This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PR/2386 [2/2]: MinGW attach to process without an exec file


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

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.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]