solib-darwin.c: handle PIE when attaching processes.
authorJoel Brobecker <brobecker@gnat.com>
Tue, 18 Dec 2012 06:19:54 +0000 (06:19 +0000)
committerJoel Brobecker <brobecker@gnat.com>
Tue, 18 Dec 2012 06:19:54 +0000 (06:19 +0000)
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.

gdb/ChangeLog
gdb/objfiles.c
gdb/objfiles.h
gdb/solib-darwin.c

index 4cd2891d76532ecdda869927366d63a3086cdeee..7558559b5df1509773225b7001247c1be1573e4c 100644 (file)
@@ -1,3 +1,11 @@
+2012-12-18  Joel Brobecker  <brobecker@adacore.com>
+
+       * 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.
+
 2012-12-18  Joel Brobecker  <brobecker@adacore.com>
 
        * gnulib/update-gnulib.sh (IMPORTED_GNULIB_MODULES): Add errno.
index feb387b1bad71f6e6239d981c9c060cc8db8e6d5..f75c4349c990839fc2f1cd2cca5ad9055791f30d 100644 (file)
@@ -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 ();
+}
 \f
 /* Return non-zero if OBJFILE has partial symbols.  */
 
index c79459805f6a617e44bc28d30b13d8902c58d07f..27cfd452dfa4843ed6236b554c9f3526a8d4c16e 100644 (file)
@@ -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);
 
index 735d1c3addae9146d261a90f896ea3bbbf980ebb..3546262864385038af16573be191093702e76df0 100644 (file)
@@ -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