This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA/commit] solib-darwin.c: handle PIE when attaching processes.


Hello,

I am submitting this patch on behalf of Tristan, who is a little
busy to do so himself. This improves the objfile relocation when
attaching to a running process.

It's an RFA because it adds a couple of new routines in objfiles.c.

gdb/ChangeLog:

        * solib-darwin.c (darwin_current_sos): Fix indentation.
        (darwin_read_exec_load_addr): New function.
        (darwin_solib_create_inferior_hook): Rebase executable.
        * objfiles.c (objfile_rebase1, objfile_rebase): New functions.
        * objfiles.h (objfile_rebase1, objfile_rebase): Add prototypes.

Tested on x86_64-darwin. No regression. OK to commit?

Thanks,
-- 
Joel

---
 gdb/objfiles.c     |   39 ++++++++++++++++++++++++
 gdb/objfiles.h     |    1 +
 gdb/solib-darwin.c |   82 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 120 insertions(+), 2 deletions(-)

diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index feb387b..f75c434 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -882,6 +882,45 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
   if (changed)
     breakpoint_re_set ();
 }
+
+/* Rebase (add to the offsets) OBJFILE by SLIDE.  SEPARATE_DEBUG_OBJFILE is
+   not touched here.
+   Return non-zero iff any change happened.  */
+
+static int
+objfile_rebase1 (struct objfile *objfile, CORE_ADDR slide)
+{
+  struct section_offsets *new_offsets =
+    ((struct section_offsets *)
+     alloca (SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)));
+  int i;
+
+  for (i = 0; i < objfile->num_sections; ++i)
+    new_offsets->offsets[i] = slide;
+
+  return objfile_relocate1 (objfile, new_offsets);
+}
+
+/* Rebase (add to the offsets) OBJFILE by SLIDE.  Process also OBJFILE's
+   SEPARATE_DEBUG_OBJFILEs.  */
+
+void
+objfile_rebase (struct objfile *objfile, CORE_ADDR slide)
+{
+  struct objfile *debug_objfile;
+  int changed = 0;
+
+  changed |= objfile_rebase1 (objfile, slide);
+
+  for (debug_objfile = objfile->separate_debug_objfile;
+       debug_objfile;
+       debug_objfile = objfile_separate_debug_iterate (objfile, debug_objfile))
+    changed |= objfile_rebase1 (debug_objfile, slide);
+
+  /* Relocate breakpoints as necessary, after things are relocated.  */
+  if (changed)
+    breakpoint_re_set ();
+}
 
 /* Return non-zero if OBJFILE has partial symbols.  */
 
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index c794598..27cfd45 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -471,6 +471,7 @@ extern struct cleanup *make_cleanup_free_objfile (struct objfile *);
 extern void free_all_objfiles (void);
 
 extern void objfile_relocate (struct objfile *, struct section_offsets *);
+extern void objfile_rebase (struct objfile *, CORE_ADDR);
 
 extern int objfile_has_partial_symbols (struct objfile *objfile);
 
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 735d1c3..3546262 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -331,6 +331,51 @@ darwin_current_sos (void)
   return head;
 }
 
+/* Get the load address of the executable.  We assume that the dyld info are
+   correct.  */
+
+static CORE_ADDR
+darwin_read_exec_load_addr (struct darwin_info *info)
+{
+  struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+  int ptr_len = TYPE_LENGTH (ptr_type);
+  unsigned int image_info_size = ptr_len * 3;
+  int i;
+
+  /* Read infos for each solib.  One of them should be the executable.  */
+  for (i = 0; i < info->all_image.count; i++)
+    {
+      CORE_ADDR iinfo = info->all_image.info + i * image_info_size;
+      char buf[image_info_size];
+      CORE_ADDR load_addr;
+      struct mach_o_header_external hdr;
+      unsigned long hdr_val;
+
+      /* Read image info from inferior.  */
+      if (target_read_memory (iinfo, buf, image_info_size))
+	break;
+
+      load_addr = extract_typed_address (buf, ptr_type);
+
+      /* Read Mach-O header from memory.  */
+      if (target_read_memory (load_addr, (char *) &hdr, sizeof (hdr) - 4))
+	break;
+      /* Discard wrong magic numbers.  Shouldn't happen.  */
+      hdr_val = extract_unsigned_integer
+        (hdr.magic, sizeof (hdr.magic), byte_order);
+      if (hdr_val != BFD_MACH_O_MH_MAGIC && hdr_val != BFD_MACH_O_MH_MAGIC_64)
+        continue;
+      /* Check executable.  */
+      hdr_val = extract_unsigned_integer
+        (hdr.filetype, sizeof (hdr.filetype), byte_order);
+      if (hdr_val == BFD_MACH_O_MH_EXECUTE)
+	return load_addr;
+    }
+
+  return 0;
+}
+
 /* Return 1 if PC lies in the dynamic symbol resolution code of the
    run time loader.  */
 
@@ -456,6 +501,7 @@ static void
 darwin_solib_create_inferior_hook (int from_tty)
 {
   struct darwin_info *info = get_darwin_info ();
+  CORE_ADDR load_addr;
 
   info->all_image_addr = 0;
 
@@ -469,8 +515,40 @@ darwin_solib_create_inferior_hook (int from_tty)
 
   darwin_load_image_infos (info);
 
-  if (darwin_dyld_version_ok (info))
-    create_solib_event_breakpoint (target_gdbarch (), info->all_image.notifier);
+  if (!darwin_dyld_version_ok (info))
+    return;
+
+  create_solib_event_breakpoint (target_gdbarch (), info->all_image.notifier);
+
+  /* Possible relocate the main executable (PIE).  */
+  load_addr = darwin_read_exec_load_addr (info);
+  if (load_addr != 0 && symfile_objfile != NULL)
+    {
+      CORE_ADDR vmaddr = 0;
+      struct mach_o_data_struct *md = bfd_mach_o_get_data (exec_bfd);
+      unsigned int i, num;
+
+      /* Find the base address of the executable.  */
+      for (i = 0; i < md->header.ncmds; i++)
+	{
+	  struct bfd_mach_o_load_command *cmd = &md->commands[i];
+
+	  if (cmd->type != BFD_MACH_O_LC_SEGMENT
+	      && cmd->type != BFD_MACH_O_LC_SEGMENT_64)
+	    continue;
+	  if (cmd->command.segment.fileoff == 0
+	      && cmd->command.segment.vmaddr != 0
+	      && cmd->command.segment.filesize != 0)
+	    {
+	      vmaddr = cmd->command.segment.vmaddr;
+	      break;
+	    }
+	}
+
+      /* Relocate.  */
+      if (vmaddr != load_addr)
+	objfile_rebase (symfile_objfile, load_addr - vmaddr);
+    }
 }
 
 static void
-- 
1.7.0.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]