solib-darwin.c: handle PIE when attaching processes.
[deliverable/binutils-gdb.git] / gdb / solib-darwin.c
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
This page took 0.025171 seconds and 4 git commands to generate.