From: Tom Tromey Date: Tue, 26 Apr 2022 20:16:57 +0000 (-0600) Subject: Implement pid_to_exec_file for Windows in gdbserver X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fcab5839;p=binutils-gdb.git 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. --- diff --git a/gdb/nat/windows-nat.c b/gdb/nat/windows-nat.c index c8db19439f3..71a18a0efa9 100644 --- a/gdb/nat/windows-nat.c +++ b/gdb/nat/windows-nat.c @@ -144,6 +144,99 @@ windows_thread_info::thread_name () 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//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 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 diff --git a/gdb/nat/windows-nat.h b/gdb/nat/windows-nat.h index 9f7f8b63192..450ba69c844 100644 --- a/gdb/nat/windows-nat.h +++ b/gdb/nat/windows-nat.h @@ -248,6 +248,8 @@ struct windows_process_info gdb::optional fetch_pending_stop (bool debug_events); + const char *pid_to_exec_file (int); + private: /* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is @@ -266,6 +268,18 @@ private: presumed loaded. */ 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 diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index cd43409a02f..11f54302b11 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1937,98 +1937,12 @@ windows_nat_target::detach (inferior *inf, int from_tty) 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. */ const char * windows_nat_target::pid_to_exec_file (int pid) { - static char path[__PMAX]; -#ifdef __CYGWIN__ - /* Try to find exe name as symlink target of /proc//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; + return windows_process.pid_to_exec_file (pid); } /* Print status information about what we're accessing. */ diff --git a/gdbserver/win32-low.cc b/gdbserver/win32-low.cc index 5b91ab768e5..f941e8d2903 100644 --- a/gdbserver/win32-low.cc +++ b/gdbserver/win32-low.cc @@ -1515,6 +1515,12 @@ win32_process_target::thread_name (ptid_t thread) 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. */ static win32_process_target the_win32_target; diff --git a/gdbserver/win32-low.h b/gdbserver/win32-low.h index c5f40dd8d0a..d16f1f9609c 100644 --- a/gdbserver/win32-low.h +++ b/gdbserver/win32-low.h @@ -160,6 +160,11 @@ public: bool supports_stopped_by_sw_breakpoint () 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. */