From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2126) id 46B643857368; Fri, 13 May 2022 14:37:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 46B643857368 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tom Tromey To: gdb-cvs@sourceware.org Subject: [binutils-gdb] Implement pid_to_exec_file for Windows in gdbserver X-Act-Checkin: binutils-gdb X-Git-Author: Tom Tromey X-Git-Refname: refs/heads/master X-Git-Oldrev: 4eab18b566a0a10d8436eb221c606df4a2803edc X-Git-Newrev: fcab58390fc7a972f499b8ae1b2ff06994b6c1fc Message-Id: <20220513143718.46B643857368@sourceware.org> Date: Fri, 13 May 2022 14:37:18 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 13 May 2022 14:37:18 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dfcab58390fc7= a972f499b8ae1b2ff06994b6c1fc commit fcab58390fc7a972f499b8ae1b2ff06994b6c1fc Author: Tom Tromey Date: Tue Apr 26 14:16:57 2022 -0600 Implement pid_to_exec_file for Windows in gdbserver =20 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: --- gdb/nat/windows-nat.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++= ++++ gdb/nat/windows-nat.h | 14 ++++++++ gdb/windows-nat.c | 88 +---------------------------------------------- gdbserver/win32-low.cc | 6 ++++ gdbserver/win32-low.h | 5 +++ 5 files changed, 119 insertions(+), 87 deletions(-) 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 (); } =20 +/* 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 =3D 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 =3D (cygwin_buf_t *) alloca (exe_name_max_len * = sizeof (cygwin_buf_t)); + + len =3D GetModuleFileNameEx (current_process_handle, + dh_buf, pathbuf, exe_name_max_len); + if (len =3D=3D 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."), errn= o); + } +#else + len =3D GetModuleFileNameEx (handle, + dh_buf, exe_name_ret, exe_name_max_len); + if (len =3D=3D 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 =3D readlink (procexe, path, sizeof(path)); + if (nchars > 0 && nchars < sizeof (path)) + { + path[nchars] =3D '\0'; /* Got it */ + return path; + } +#endif + + /* If we get here then either Cygwin is hosed, this isn't a Cygwin versi= on + of gdb, or we're trying to debug a non-Cygwin windows executable. */ + if (!get_exec_module_filename (path, sizeof (path))) + path[0] =3D '\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 =20 gdb::optional fetch_pending_stop (bool debug_events); =20 + const char *pid_to_exec_file (int); + private: =20 /* Handle MS_VC_EXCEPTION when processing a stop. MS_VC_EXCEPTION is @@ -266,6 +268,18 @@ private: presumed loaded. */ =20 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_le= n); }; =20 /* 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 (); } =20 -/* 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 =3D 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 =3D (cygwin_buf_t *) alloca (exe_name_max_len * = sizeof (cygwin_buf_t)); - - len =3D GetModuleFileNameEx (current_process_handle, - dh_buf, pathbuf, exe_name_max_len); - if (len =3D=3D 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."), errn= o); - } -#else - len =3D GetModuleFileNameEx (windows_process.handle, - dh_buf, exe_name_ret, exe_name_max_len); - if (len =3D=3D 0) - error (_("Error getting executable filename: %u."), - (unsigned) GetLastError ()); -#endif - - return 1; /* success */ -} - /* The pid_to_exec_file target_ops method for this platform. */ =20 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 =3D readlink (procexe, path, sizeof(path)); - if (nchars > 0 && nchars < sizeof (path)) - { - path[nchars] =3D '\0'; /* Got it */ - return path; - } -#endif - - /* If we get here then either Cygwin is hosed, this isn't a Cygwin versi= on - of gdb, or we're trying to debug a non-Cygwin windows executable. */ - if (!windows_get_exec_module_filename (path, sizeof (path))) - path[0] =3D '\0'; - - return path; + return windows_process.pid_to_exec_file (pid); } =20 /* 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 (); } =20 +const char * +win32_process_target::pid_to_exec_file (int pid) +{ + return windows_process.pid_to_exec_file (pid); +} + /* The win32 target ops object. */ =20 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; =20 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; }; =20 /* The sole Windows process. */