Implement pid_to_exec_file for Windows in gdbserver
authorTom Tromey <tromey@adacore.com>
Tue, 26 Apr 2022 20:16:57 +0000 (14:16 -0600)
committerTom Tromey <tromey@adacore.com>
Fri, 13 May 2022 14:21:16 +0000 (08:21 -0600)
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.

gdb/nat/windows-nat.c
gdb/nat/windows-nat.h
gdb/windows-nat.c
gdbserver/win32-low.cc
gdbserver/win32-low.h

index c8db19439f3dbae4dec9da5f0d20ba661a48fa9c..71a18a0efa9186038d0cecf7cd1926e44f8cfc50 100644 (file)
@@ -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/<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
    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
index 9f7f8b631925e778c04e0b1f032b5239485144d2..450ba69c844c48ba3488ba1f329e07d69162aca9 100644 (file)
@@ -248,6 +248,8 @@ struct windows_process_info
 
   gdb::optional<pending_stop> 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
index cd43409a02fd77e8d316f3965e38dbd3d65bb20e..11f54302b11625da6aaef88ee72e3abdd353d755 100644 (file)
@@ -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/<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;
+  return windows_process.pid_to_exec_file (pid);
 }
 
 /* Print status information about what we're accessing.  */
index 5b91ab768e51f20089f5df135c6b79dd29cd57a9..f941e8d29030f139c2a603ca8714ddb04eca8818 100644 (file)
@@ -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;
index c5f40dd8d0a9993cc0a53c3842140f584dbb2439..d16f1f9609c32ace95eb28f2384c26553e401701 100644 (file)
@@ -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.  */