* 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.
This commit is contained in:
Christopher Faylor 2008-01-01 18:42:08 +00:00
parent 1aa1b15b3c
commit 33605d3962
3 changed files with 202 additions and 162 deletions

View File

@ -1,3 +1,17 @@
2008-01-01 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.
2008-01-01 Joel Brobecker <brobecker@adacore.com> 2008-01-01 Joel Brobecker <brobecker@adacore.com>
* ada-lang.c (ada_remove_trailing_digits): New function. * ada-lang.c (ada_remove_trailing_digits): New function.

View File

@ -1,7 +1,7 @@
/* Target-vector operations for controlling win32 child processes, for GDB. /* Target-vector operations for controlling win32 child processes, for GDB.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007 Free Software Foundation, Inc. 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company. Contributed by Cygnus Solutions, A Red Hat Company.
@ -457,88 +457,78 @@ win32_store_inferior_registers (struct regcache *regcache, int r)
} }
static int psapi_loaded = 0; static int psapi_loaded = 0;
static HMODULE psapi_module_handle = NULL; static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD,
static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; LPDWORD);
static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL; static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL; 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 static int
psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret) get_module_name (DWORD base_address, char *dll_name_ret)
{ {
DWORD len; DWORD len;
MODULEINFO mi; MODULEINFO mi;
int i; int i;
HMODULE dh_buf[1]; HMODULE dh_buf[1];
HMODULE *DllHandle = dh_buf; HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
DWORD cbNeeded; 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 || /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain
psapi_EnumProcessModules == NULL || the needed functions. */
psapi_GetModuleInformation == NULL || if (psapi_loaded <= 0)
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;
}
cbNeeded = 0;
ok = (*psapi_EnumProcessModules) (current_process_handle,
DllHandle,
sizeof (HMODULE),
&cbNeeded);
if (!ok || !cbNeeded)
goto failed; goto failed;
cbNeeded = 0;
/* 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); DllHandle = (HMODULE *) alloca (cbNeeded);
if (!DllHandle) if (!DllHandle)
goto failed; goto failed;
ok = (*psapi_EnumProcessModules) (current_process_handle, /* Get the list of modules */
DllHandle, if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
cbNeeded, &cbNeeded))
&cbNeeded);
if (!ok)
goto failed; goto failed;
for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++) for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
{ {
if (!(*psapi_GetModuleInformation) (current_process_handle, /* Get information on this module */
DllHandle[i], if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
&mi, &mi, sizeof (mi)))
sizeof (mi)))
error (_("Can't get module info")); error (_("Can't get module info"));
len = (*psapi_GetModuleFileNameExA) (current_process_handle, if (!base_address || (DWORD) (mi.lpBaseOfDll) == base_address)
DllHandle[i], {
dll_name_ret, /* Try to find the name of the given module */
MAX_PATH); len = psapi_GetModuleFileNameExA (current_process_handle,
if (len == 0) DllHandle[i], pathbuf, MAX_PATH);
error (_("Error getting dll name: %u."), (unsigned) GetLastError ()); if (len == 0)
error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
if ((DWORD) (mi.lpBaseOfDll) == BaseAddress) #ifdef __CYGWIN__
return 1; /* 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: failed:
dll_name_ret[0] = '\0'; dll_name_ret[0] = '\0';
return 0; return 0; /* failure */
} }
/* Encapsulate the information required in a call to /* Encapsulate the information required in a call to
@ -745,7 +735,7 @@ handle_load_dll (void *dummy)
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; 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_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
dll_name = dll_buf; dll_name = dll_buf;
@ -1730,35 +1720,27 @@ win32_detach (char *args, int from_tty)
static char * static char *
win32_pid_to_exec_file (int pid) 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]; static char path[MAX_PATH + 1];
char *path_ptr = NULL;
#ifdef __CYGWIN__ #ifdef __CYGWIN__
/* TODO: Also find native Windows processes using CW_GETPINFO_FULL. */ /* Try to find exe name as symlink target of /proc/<pid>/exe */
int cpid; int nchars;
struct external_pinfo *pinfo; char procexe[sizeof ("/proc/4294967295/exe")];
sprintf (procexe, "/proc/%lu/exe", current_event.dwProcessId);
cygwin_internal (CW_LOCK_PINFO, 1000); nchars = readlink (procexe, path, sizeof(path));
for (cpid = 0; if (nchars > 0 && nchars < sizeof (path))
(pinfo = (struct external_pinfo *)
cygwin_internal (CW_GETPINFO, cpid | CW_NEXTPID));
cpid = pinfo->pid)
{ {
if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */ path[nchars] = '\0'; /* Got it */
{ return path;
cygwin_conv_to_full_posix_path (pinfo->progname, path);
path_ptr = path;
break;
}
} }
cygwin_internal (CW_UNLOCK_PINFO);
#endif #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. */ /* Print status information about what we're accessing. */
@ -2282,3 +2264,34 @@ _initialize_check_for_gdb_ini (void)
} }
} }
} }
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(_("cannot automatically find executable file or library to read symbols. Use \"file\" or \"dll\" command to load executable/libraries directly."));
}

View File

@ -1,7 +1,7 @@
/* Target-vector operations for controlling win32 child processes, for GDB. /* Target-vector operations for controlling win32 child processes, for GDB.
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007 Free Software Foundation, Inc. 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Contributed by Cygnus Solutions, A Red Hat Company. Contributed by Cygnus Solutions, A Red Hat Company.
@ -457,88 +457,78 @@ win32_store_inferior_registers (struct regcache *regcache, int r)
} }
static int psapi_loaded = 0; static int psapi_loaded = 0;
static HMODULE psapi_module_handle = NULL; static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD,
static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL; LPDWORD);
static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL; static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL; 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 static int
psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret) get_module_name (DWORD base_address, char *dll_name_ret)
{ {
DWORD len; DWORD len;
MODULEINFO mi; MODULEINFO mi;
int i; int i;
HMODULE dh_buf[1]; HMODULE dh_buf[1];
HMODULE *DllHandle = dh_buf; HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
DWORD cbNeeded; 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 || /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain
psapi_EnumProcessModules == NULL || the needed functions. */
psapi_GetModuleInformation == NULL || if (psapi_loaded <= 0)
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;
}
cbNeeded = 0;
ok = (*psapi_EnumProcessModules) (current_process_handle,
DllHandle,
sizeof (HMODULE),
&cbNeeded);
if (!ok || !cbNeeded)
goto failed; goto failed;
cbNeeded = 0;
/* 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); DllHandle = (HMODULE *) alloca (cbNeeded);
if (!DllHandle) if (!DllHandle)
goto failed; goto failed;
ok = (*psapi_EnumProcessModules) (current_process_handle, /* Get the list of modules */
DllHandle, if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
cbNeeded, &cbNeeded))
&cbNeeded);
if (!ok)
goto failed; goto failed;
for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++) for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
{ {
if (!(*psapi_GetModuleInformation) (current_process_handle, /* Get information on this module */
DllHandle[i], if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
&mi, &mi, sizeof (mi)))
sizeof (mi)))
error (_("Can't get module info")); error (_("Can't get module info"));
len = (*psapi_GetModuleFileNameExA) (current_process_handle, if (!base_address || (DWORD) (mi.lpBaseOfDll) == base_address)
DllHandle[i], {
dll_name_ret, /* Try to find the name of the given module */
MAX_PATH); len = psapi_GetModuleFileNameExA (current_process_handle,
if (len == 0) DllHandle[i], pathbuf, MAX_PATH);
error (_("Error getting dll name: %u."), (unsigned) GetLastError ()); if (len == 0)
error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
if ((DWORD) (mi.lpBaseOfDll) == BaseAddress) #ifdef __CYGWIN__
return 1; /* 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: failed:
dll_name_ret[0] = '\0'; dll_name_ret[0] = '\0';
return 0; return 0; /* failure */
} }
/* Encapsulate the information required in a call to /* Encapsulate the information required in a call to
@ -745,7 +735,7 @@ handle_load_dll (void *dummy)
dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0'; 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_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
dll_name = dll_buf; dll_name = dll_buf;
@ -1730,35 +1720,27 @@ win32_detach (char *args, int from_tty)
static char * static char *
win32_pid_to_exec_file (int pid) 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]; static char path[MAX_PATH + 1];
char *path_ptr = NULL;
#ifdef __CYGWIN__ #ifdef __CYGWIN__
/* TODO: Also find native Windows processes using CW_GETPINFO_FULL. */ /* Try to find exe name as symlink target of /proc/<pid>/exe */
int cpid; int nchars;
struct external_pinfo *pinfo; char procexe[sizeof ("/proc/4294967295/exe")];
sprintf (procexe, "/proc/%lu/exe", current_event.dwProcessId);
cygwin_internal (CW_LOCK_PINFO, 1000); nchars = readlink (procexe, path, sizeof(path));
for (cpid = 0; if (nchars > 0 && nchars < sizeof (path))
(pinfo = (struct external_pinfo *)
cygwin_internal (CW_GETPINFO, cpid | CW_NEXTPID));
cpid = pinfo->pid)
{ {
if (pinfo->dwProcessId == current_event.dwProcessId) /* Got it */ path[nchars] = '\0'; /* Got it */
{ return path;
cygwin_conv_to_full_posix_path (pinfo->progname, path);
path_ptr = path;
break;
}
} }
cygwin_internal (CW_UNLOCK_PINFO);
#endif #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. */ /* Print status information about what we're accessing. */
@ -2282,3 +2264,34 @@ _initialize_check_for_gdb_ini (void)
} }
} }
} }
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(_("cannot automatically find executable file or library to read symbols. Use \"file\" or \"dll\" command to load executable/libraries directly."));
}