From 4141a416ddb921e600cf6d28b805f854ef3b60e9 Mon Sep 17 00:00:00 2001 From: Joel Brobecker Date: Tue, 18 Dec 2012 06:19:54 +0000 Subject: solib-darwin.c: handle PIE when attaching processes. 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 | 8 ++++++ gdb/objfiles.c | 39 ++++++++++++++++++++++++++ gdb/objfiles.h | 1 + gdb/solib-darwin.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 128 insertions(+), 2 deletions(-) (limited to 'gdb') diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 4cd2891..7558559 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,13 @@ 2012-12-18 Joel Brobecker + * 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 + * gnulib/update-gnulib.sh (IMPORTED_GNULIB_MODULES): Add errno. * gnulib/import/errno.in.h: Import. * gnulib/import/m4/errno_h.m4: Import. 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 -- cgit v1.1