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/solib-darwin.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 2 deletions(-) (limited to 'gdb/solib-darwin.c') 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