Implement pid_to_exec_file for Windows in gdbserver
I noticed that gdbserver did not implement pid_to_exec_file for Windows, while gdb did implement it. This patch moves the code to nat/windows-nat.c, so that it can be shared. This makes the gdbserver implementation trivial.
This commit is contained in:
parent
4eab18b566
commit
fcab58390f
5 changed files with 119 additions and 87 deletions
|
@ -144,6 +144,99 @@ windows_thread_info::thread_name ()
|
||||||
return name.get ();
|
return name.get ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try to determine the executable filename.
|
||||||
|
|
||||||
|
EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
|
||||||
|
|
||||||
|
Upon success, the filename is stored inside EXE_NAME_RET, and
|
||||||
|
this function returns nonzero.
|
||||||
|
|
||||||
|
Otherwise, this function returns zero and the contents of
|
||||||
|
EXE_NAME_RET is undefined. */
|
||||||
|
|
||||||
|
int
|
||||||
|
windows_process_info::get_exec_module_filename (char *exe_name_ret,
|
||||||
|
size_t exe_name_max_len)
|
||||||
|
{
|
||||||
|
DWORD len;
|
||||||
|
HMODULE dh_buf;
|
||||||
|
DWORD cbNeeded;
|
||||||
|
|
||||||
|
cbNeeded = 0;
|
||||||
|
#ifdef __x86_64__
|
||||||
|
if (wow64_process)
|
||||||
|
{
|
||||||
|
if (!EnumProcessModulesEx (handle,
|
||||||
|
&dh_buf, sizeof (HMODULE), &cbNeeded,
|
||||||
|
LIST_MODULES_32BIT)
|
||||||
|
|| !cbNeeded)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (!EnumProcessModules (handle,
|
||||||
|
&dh_buf, sizeof (HMODULE), &cbNeeded)
|
||||||
|
|| !cbNeeded)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We know the executable is always first in the list of modules,
|
||||||
|
which we just fetched. So no need to fetch more. */
|
||||||
|
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
{
|
||||||
|
/* Cygwin prefers that the path be in /x/y/z format, so extract
|
||||||
|
the filename into a temporary buffer first, and then convert it
|
||||||
|
to POSIX format into the destination buffer. */
|
||||||
|
cygwin_buf_t *pathbuf = (cygwin_buf_t *) alloca (exe_name_max_len * sizeof (cygwin_buf_t));
|
||||||
|
|
||||||
|
len = GetModuleFileNameEx (current_process_handle,
|
||||||
|
dh_buf, pathbuf, exe_name_max_len);
|
||||||
|
if (len == 0)
|
||||||
|
error (_("Error getting executable filename: %u."),
|
||||||
|
(unsigned) GetLastError ());
|
||||||
|
if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, exe_name_ret,
|
||||||
|
exe_name_max_len) < 0)
|
||||||
|
error (_("Error converting executable filename to POSIX: %d."), errno);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
len = GetModuleFileNameEx (handle,
|
||||||
|
dh_buf, exe_name_ret, exe_name_max_len);
|
||||||
|
if (len == 0)
|
||||||
|
error (_("Error getting executable filename: %u."),
|
||||||
|
(unsigned) GetLastError ());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1; /* success */
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
windows_process_info::pid_to_exec_file (int pid)
|
||||||
|
{
|
||||||
|
static char path[MAX_PATH];
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
/* Try to find exe name as symlink target of /proc/<pid>/exe. */
|
||||||
|
int nchars;
|
||||||
|
char procexe[sizeof ("/proc/4294967295/exe")];
|
||||||
|
|
||||||
|
xsnprintf (procexe, sizeof (procexe), "/proc/%u/exe", pid);
|
||||||
|
nchars = readlink (procexe, path, sizeof(path));
|
||||||
|
if (nchars > 0 && nchars < sizeof (path))
|
||||||
|
{
|
||||||
|
path[nchars] = '\0'; /* Got it */
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 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_exec_module_filename (path, sizeof (path)))
|
||||||
|
path[0] = '\0';
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the name of the DLL referenced by H at ADDRESS. UNICODE
|
/* Return the name of the DLL referenced by H at ADDRESS. UNICODE
|
||||||
determines what sort of string is read from the inferior. Returns
|
determines what sort of string is read from the inferior. Returns
|
||||||
the name of the DLL, or NULL on error. If a name is returned, it
|
the name of the DLL, or NULL on error. If a name is returned, it
|
||||||
|
|
|
@ -248,6 +248,8 @@ struct windows_process_info
|
||||||
|
|
||||||
gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
|
gdb::optional<pending_stop> fetch_pending_stop (bool debug_events);
|
||||||
|
|
||||||
|
const char *pid_to_exec_file (int);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is
|
/* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is
|
||||||
|
@ -266,6 +268,18 @@ private:
|
||||||
presumed loaded. */
|
presumed loaded. */
|
||||||
|
|
||||||
void add_dll (LPVOID load_addr);
|
void add_dll (LPVOID load_addr);
|
||||||
|
|
||||||
|
/* Try to determine the executable filename.
|
||||||
|
|
||||||
|
EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
|
||||||
|
|
||||||
|
Upon success, the filename is stored inside EXE_NAME_RET, and
|
||||||
|
this function returns nonzero.
|
||||||
|
|
||||||
|
Otherwise, this function returns zero and the contents of
|
||||||
|
EXE_NAME_RET is undefined. */
|
||||||
|
|
||||||
|
int get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* A simple wrapper for ContinueDebugEvent that continues the last
|
/* A simple wrapper for ContinueDebugEvent that continues the last
|
||||||
|
|
|
@ -1937,98 +1937,12 @@ windows_nat_target::detach (inferior *inf, int from_tty)
|
||||||
maybe_unpush_target ();
|
maybe_unpush_target ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to determine the executable filename.
|
|
||||||
|
|
||||||
EXE_NAME_RET is a pointer to a buffer whose size is EXE_NAME_MAX_LEN.
|
|
||||||
|
|
||||||
Upon success, the filename is stored inside EXE_NAME_RET, and
|
|
||||||
this function returns nonzero.
|
|
||||||
|
|
||||||
Otherwise, this function returns zero and the contents of
|
|
||||||
EXE_NAME_RET is undefined. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len)
|
|
||||||
{
|
|
||||||
DWORD len;
|
|
||||||
HMODULE dh_buf;
|
|
||||||
DWORD cbNeeded;
|
|
||||||
|
|
||||||
cbNeeded = 0;
|
|
||||||
#ifdef __x86_64__
|
|
||||||
if (windows_process.wow64_process)
|
|
||||||
{
|
|
||||||
if (!EnumProcessModulesEx (windows_process.handle,
|
|
||||||
&dh_buf, sizeof (HMODULE), &cbNeeded,
|
|
||||||
LIST_MODULES_32BIT)
|
|
||||||
|| !cbNeeded)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (!EnumProcessModules (windows_process.handle,
|
|
||||||
&dh_buf, sizeof (HMODULE), &cbNeeded)
|
|
||||||
|| !cbNeeded)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We know the executable is always first in the list of modules,
|
|
||||||
which we just fetched. So no need to fetch more. */
|
|
||||||
|
|
||||||
#ifdef __CYGWIN__
|
|
||||||
{
|
|
||||||
/* Cygwin prefers that the path be in /x/y/z format, so extract
|
|
||||||
the filename into a temporary buffer first, and then convert it
|
|
||||||
to POSIX format into the destination buffer. */
|
|
||||||
cygwin_buf_t *pathbuf = (cygwin_buf_t *) alloca (exe_name_max_len * sizeof (cygwin_buf_t));
|
|
||||||
|
|
||||||
len = GetModuleFileNameEx (current_process_handle,
|
|
||||||
dh_buf, pathbuf, exe_name_max_len);
|
|
||||||
if (len == 0)
|
|
||||||
error (_("Error getting executable filename: %u."),
|
|
||||||
(unsigned) GetLastError ());
|
|
||||||
if (cygwin_conv_path (CCP_WIN_W_TO_POSIX, pathbuf, exe_name_ret,
|
|
||||||
exe_name_max_len) < 0)
|
|
||||||
error (_("Error converting executable filename to POSIX: %d."), errno);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
len = GetModuleFileNameEx (windows_process.handle,
|
|
||||||
dh_buf, exe_name_ret, exe_name_max_len);
|
|
||||||
if (len == 0)
|
|
||||||
error (_("Error getting executable filename: %u."),
|
|
||||||
(unsigned) GetLastError ());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 1; /* success */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The pid_to_exec_file target_ops method for this platform. */
|
/* The pid_to_exec_file target_ops method for this platform. */
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
windows_nat_target::pid_to_exec_file (int pid)
|
windows_nat_target::pid_to_exec_file (int pid)
|
||||||
{
|
{
|
||||||
static char path[__PMAX];
|
return windows_process.pid_to_exec_file (pid);
|
||||||
#ifdef __CYGWIN__
|
|
||||||
/* Try to find exe name as symlink target of /proc/<pid>/exe. */
|
|
||||||
int nchars;
|
|
||||||
char procexe[sizeof ("/proc/4294967295/exe")];
|
|
||||||
|
|
||||||
xsnprintf (procexe, sizeof (procexe), "/proc/%u/exe", pid);
|
|
||||||
nchars = readlink (procexe, path, sizeof(path));
|
|
||||||
if (nchars > 0 && nchars < sizeof (path))
|
|
||||||
{
|
|
||||||
path[nchars] = '\0'; /* Got it */
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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 (!windows_get_exec_module_filename (path, sizeof (path)))
|
|
||||||
path[0] = '\0';
|
|
||||||
|
|
||||||
return path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print status information about what we're accessing. */
|
/* Print status information about what we're accessing. */
|
||||||
|
|
|
@ -1515,6 +1515,12 @@ win32_process_target::thread_name (ptid_t thread)
|
||||||
return th->thread_name ();
|
return th->thread_name ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
win32_process_target::pid_to_exec_file (int pid)
|
||||||
|
{
|
||||||
|
return windows_process.pid_to_exec_file (pid);
|
||||||
|
}
|
||||||
|
|
||||||
/* The win32 target ops object. */
|
/* The win32 target ops object. */
|
||||||
|
|
||||||
static win32_process_target the_win32_target;
|
static win32_process_target the_win32_target;
|
||||||
|
|
|
@ -160,6 +160,11 @@ public:
|
||||||
bool supports_stopped_by_sw_breakpoint () override;
|
bool supports_stopped_by_sw_breakpoint () override;
|
||||||
|
|
||||||
const char *thread_name (ptid_t thread) override;
|
const char *thread_name (ptid_t thread) override;
|
||||||
|
|
||||||
|
bool supports_pid_to_exec_file () override
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
const char *pid_to_exec_file (int pid) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The sole Windows process. */
|
/* The sole Windows process. */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue