diff mbox

[RFC] Rebase executable to match relocated base address

Message ID 20191222170000.7548-1-ssbssa@yahoo.de
State New
Headers show

Commit Message

Doug Evans via gdb-patches Dec. 22, 2019, 5 p.m. UTC
Windows executables linked with -dynamicbase get a new base address
when loaded, which makes debugging impossible if the executable isn't
also rebased in gdb.

solib_create_inferior_hook looked like the right place for rebasing,
since there is similar code in solib_aix_solib_create_inferior_hook
and darwin_solib_create_inferior_hook.

But I'm not at all sure about my approach to forward the image base
via auxv data, but I needed a solution that worked for gdbserver as well.

Also I just reused AT_ENTRY, which is not nice at all.
I guess a new define should be created (where?), and a new auxv print function
registered with set_gdbarch_print_auxv_entry, but since I'm not sure
if the auxv approach is even correct, I didn't bother with this (for now).
---
 gdb/gdbserver/win32-low.c | 32 +++++++++++++++++++++++++++++++-
 gdb/windows-nat.c         | 35 +++++++++++++++++++++++++++++++++++
 gdb/windows-tdep.c        | 20 ++++++++++++++++++++
 3 files changed, 86 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 33171ba7d2..33dd771998 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -75,6 +75,7 @@  static HANDLE current_process_handle = NULL;
 static DWORD current_process_id = 0;
 static DWORD main_thread_id = 0;
 static EXCEPTION_RECORD siginfo_er;	/* Contents of $_siginfo */
+static CORE_ADDR current_exec_base;	/* Executable base address */
 static enum gdb_signal last_sig = GDB_SIGNAL_0;
 
 /* The current debug event from WaitForDebugEvent.  */
@@ -1490,6 +1491,8 @@  get_child_debug_event (struct target_waitstatus *ourstatus)
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
       main_thread_id = current_event.dwThreadId;
+      current_exec_base =
+	(CORE_ADDR) current_event.u.CreateProcessInfo.lpBaseOfImage;
 
       /* Add the main thread.  */
       child_add_thread (current_event.dwProcessId,
@@ -1700,6 +1703,33 @@  win32_request_interrupt (void)
   soft_interrupt_requested = 1;
 }
 
+static int
+win32_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len)
+{
+  size_t buf[4];
+
+  if (!myaddr)
+    return -1;
+
+  if (offset > sizeof (buf))
+    return -1;
+
+  if (offset == sizeof (buf))
+    return 0;
+
+  if (offset + len > sizeof (buf))
+    len = sizeof (buf) - offset;
+
+  buf[0] = 9; /* AT_ENTRY */
+  buf[1] = current_exec_base;
+  buf[2] = 0; /* AT_NULL */
+  buf[3] = 0;
+
+  memcpy (myaddr, (char *) buf + offset, len);
+
+  return len;
+}
+
 #ifdef _WIN32_WCE
 int
 win32_error_to_fileio_error (DWORD err)
@@ -1822,7 +1852,7 @@  static struct target_ops win32_target_ops = {
   win32_write_inferior_memory,
   NULL, /* lookup_symbols */
   win32_request_interrupt,
-  NULL, /* read_auxv */
+  win32_read_auxv,
   win32_supports_z_point_type,
   win32_insert_point,
   win32_remove_point,
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index bb7d02b770..7e0dedee68 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -236,6 +236,7 @@  static DEBUG_EVENT current_event;	/* The current debug event from
 static HANDLE current_process_handle;	/* Currently executing process */
 static windows_thread_info *current_thread;	/* Info on currently selected thread */
 static EXCEPTION_RECORD siginfo_er;	/* Contents of $_siginfo */
+static CORE_ADDR current_exec_base;	/* Executable base address */
 
 /* Counts of things.  */
 static int exception_count = 0;
@@ -1597,6 +1598,8 @@  get_windows_debug_event (struct target_ops *ops,
 	break;
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
+      current_exec_base =
+	(CORE_ADDR) current_event.u.CreateProcessInfo.lpBaseOfImage;
       /* Add the main thread.  */
       th = windows_add_thread
         (ptid_t (current_event.dwProcessId, 0,
@@ -2997,6 +3000,35 @@  windows_xfer_siginfo (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
   return TARGET_XFER_OK;
 }
 
+static enum target_xfer_status
+windows_xfer_auxv (gdb_byte *readbuf, ULONGEST offset, ULONGEST len,
+		   ULONGEST *xfered_len)
+{
+  CORE_ADDR buf[4];
+
+  if (!readbuf)
+    return TARGET_XFER_E_IO;
+
+  if (offset > sizeof (buf))
+    return TARGET_XFER_E_IO;
+
+  if (offset == sizeof (buf))
+    return TARGET_XFER_EOF;
+
+  if (offset + len > sizeof (buf))
+    len = sizeof (buf) - offset;
+
+  buf[0] = 9; /* AT_ENTRY */
+  buf[1] = current_exec_base;
+  buf[2] = 0; /* AT_NULL */
+  buf[3] = 0;
+
+  memcpy (readbuf, (char *) buf + offset, len);
+  *xfered_len = len;
+
+  return TARGET_XFER_OK;
+}
+
 enum target_xfer_status
 windows_nat_target::xfer_partial (enum target_object object,
 				  const char *annex, gdb_byte *readbuf,
@@ -3015,6 +3047,9 @@  windows_nat_target::xfer_partial (enum target_object object,
     case TARGET_OBJECT_SIGNAL_INFO:
       return windows_xfer_siginfo (readbuf, offset, len, xfered_len);
 
+    case TARGET_OBJECT_AUXV:
+      return windows_xfer_auxv (readbuf, offset, len, xfered_len);
+
     default:
       if (beneath () == NULL)
 	{
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 9353f191d9..e3bd34f8ac 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -34,6 +34,10 @@ 
 #include "solib.h"
 #include "solib-target.h"
 #include "gdbcore.h"
+#include "coff/internal.h"
+#include "libcoff.h"
+#include "solist.h"
+#include "auxv.h"
 
 struct cmd_list_element *info_w32_cmdlist;
 
@@ -489,6 +493,20 @@  init_w32_command_list (void)
     }
 }
 
+static void
+windows_solib_create_inferior_hook (int from_tty)
+{
+  CORE_ADDR exec_base;
+  /* 9 -> AT_ENTRY */
+  if (target_auxv_search (current_top_target (), 9, &exec_base) == 1
+      && exec_base && symfile_objfile)
+    {
+      CORE_ADDR vmaddr = pe_data (exec_bfd)->pe_opthdr.ImageBase;
+      if (vmaddr != exec_base)
+	objfile_rebase (symfile_objfile, exec_base - vmaddr);
+    }
+}
+
 struct enum_value_name
 {
   uint32_t value;
@@ -622,6 +640,8 @@  windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_iterate_over_objfiles_in_search_order
     (gdbarch, windows_iterate_over_objfiles_in_search_order);
 
+  solib_target_so_ops.solib_create_inferior_hook =
+    windows_solib_create_inferior_hook;
   set_solib_ops (gdbarch, &solib_target_so_ops);
 
   set_gdbarch_get_siginfo_type (gdbarch, windows_get_siginfo_type);