diff options
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/solib-darwin.c | 71 |
2 files changed, 67 insertions, 11 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c3922e2..dfdde50 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2018-09-19 Xavier Roirand <roirand@adacore.com> + + PR gdb/20981: + * solib-darwin.c (darwin_get_dyld_bfd): New function. + (darwin_solib_get_all_image_info_addr_at_init): Update call. + (darwin_solib_create_inferior_hook): Handle unrelocated dyld. + 2018-09-19 John Baldwin <jhb@FreeBSD.org> * fbsd-tdep.c (fbsd_print_sockaddr_in): Style fix. diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c index ed8e0c1..d115f72 100644 --- a/gdb/solib-darwin.c +++ b/gdb/solib-darwin.c @@ -429,23 +429,21 @@ gdb_bfd_mach_o_fat_extract (bfd *abfd, bfd_format format, return gdb_bfd_ref_ptr (result); } -/* Extract dyld_all_image_addr when the process was just created, assuming the - current PC is at the entry of the dynamic linker. */ +/* Return the BFD for the program interpreter. */ -static void -darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) +static gdb_bfd_ref_ptr +darwin_get_dyld_bfd () { char *interp_name; - CORE_ADDR load_addr = 0; /* This method doesn't work with an attached process. */ if (current_inferior ()->attach_flag) - return; + return NULL; /* Find the program interpreter. */ interp_name = find_program_interpreter (); if (!interp_name) - return; + return NULL; /* Create a bfd for the interpreter. */ gdb_bfd_ref_ptr dyld_bfd (gdb_bfd_open (interp_name, gnutarget, -1)); @@ -459,6 +457,18 @@ darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) else dyld_bfd.release (); } + return dyld_bfd; +} + +/* Extract dyld_all_image_addr when the process was just created, assuming the + current PC is at the entry of the dynamic linker. */ + +static void +darwin_solib_get_all_image_info_addr_at_init (struct darwin_info *info) +{ + CORE_ADDR load_addr = 0; + gdb_bfd_ref_ptr dyld_bfd = darwin_get_dyld_bfd (); + if (dyld_bfd == NULL) return; @@ -528,10 +538,6 @@ darwin_solib_create_inferior_hook (int from_tty) return; } - /* Add the breakpoint which is hit by dyld when the list of solib is - modified. */ - create_solib_event_breakpoint (target_gdbarch (), info->all_image.notifier); - if (info->all_image.count != 0) { /* Possible relocate the main executable (PIE). */ @@ -558,6 +564,49 @@ darwin_solib_create_inferior_hook (int from_tty) if (vmaddr != load_addr) objfile_rebase (symfile_objfile, load_addr - vmaddr); } + + /* Set solib notifier (to reload list of shared libraries). */ + CORE_ADDR notifier = info->all_image.notifier; + + if (info->all_image.count == 0) + { + /* Dyld hasn't yet relocated itself, so the notifier address may + be incorrect (as it has to be relocated). */ + CORE_ADDR start = bfd_get_start_address (exec_bfd); + if (start == 0) + notifier = 0; + else + { + gdb_bfd_ref_ptr dyld_bfd = darwin_get_dyld_bfd (); + if (dyld_bfd != NULL) + { + CORE_ADDR dyld_bfd_start_address; + CORE_ADDR dyld_relocated_base_address; + CORE_ADDR pc; + + dyld_bfd_start_address = bfd_get_start_address (dyld_bfd.get()); + + /* We find the dynamic linker's base address by examining + the current pc (which should point at the entry point + for the dynamic linker) and subtracting the offset of + the entry point. */ + + pc = regcache_read_pc (get_current_regcache ()); + dyld_relocated_base_address = pc - dyld_bfd_start_address; + + /* We get the proper notifier relocated address by + adding the dyld relocated base address to the current + notifier offset value. */ + + notifier += dyld_relocated_base_address; + } + } + } + + /* Add the breakpoint which is hit by dyld when the list of solib is + modified. */ + if (notifier != 0) + create_solib_event_breakpoint (target_gdbarch (), notifier); } static void |