diff options
Diffstat (limited to 'gdb/solib.c')
-rw-r--r-- | gdb/solib.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/gdb/solib.c b/gdb/solib.c index b09b140..6cf44d2 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -688,8 +688,7 @@ elf_locate_base () /* Find the DT_DEBUG entry in the the .dynamic section. For mips elf we look for DT_MIPS_RLD_MAP, mips elf apparently has no DT_DEBUG entries. */ - /* FIXME: In lack of a 64 bit ELF ABI the following code assumes - a 32 bit ELF ABI target. */ +#ifndef TARGET_ELF64 for (bufend = buf + dyninfo_sect_size; buf < bufend; buf += sizeof (Elf32_External_Dyn)) @@ -720,6 +719,25 @@ elf_locate_base () } #endif } +#else /* ELF64 */ + for (bufend = buf + dyninfo_sect_size; + buf < bufend; + buf += sizeof (Elf64_External_Dyn)) + { + Elf64_External_Dyn *x_dynp = (Elf64_External_Dyn *)buf; + long dyn_tag; + CORE_ADDR dyn_ptr; + + dyn_tag = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_tag); + if (dyn_tag == DT_NULL) + break; + else if (dyn_tag == DT_DEBUG) + { + dyn_ptr = bfd_h_get_64 (exec_bfd, (bfd_byte *) x_dynp->d_un.d_ptr); + return dyn_ptr; + } + } +#endif /* DT_DEBUG entry not found. */ return 0; @@ -1190,30 +1208,41 @@ info_sharedlibrary_command (ignore, from_tty) { register struct so_list *so = NULL; /* link map state variable */ int header_done = 0; - + int addr_width; + char *addr_fmt; + if (exec_bfd == NULL) { printf_unfiltered ("No exec file.\n"); return; } + +#ifndef TARGET_ELF64 + addr_width = 8+4; + addr_fmt = "08l"; +#else + addr_width = 16+4; + addr_fmt = "016l"; +#endif + while ((so = find_solib (so)) != NULL) { if (so -> so_name[0]) { if (!header_done) { - printf_unfiltered("%-12s%-12s%-12s%s\n", "From", "To", "Syms Read", - "Shared Object Library"); + printf_unfiltered("%-*s%-*s%-12s%s\n", addr_width, "From", + addr_width, "To", "Syms Read", + "Shared Object Library"); header_done++; } - /* FIXME-32x64: need print_address_numeric with field width or - some such. */ - printf_unfiltered ("%-12s", + + printf_unfiltered ("%-*s", addr_width, local_hex_string_custom ((unsigned long) LM_ADDR (so), - "08l")); - printf_unfiltered ("%-12s", + addr_fmt)); + printf_unfiltered ("%-*s", addr_width, local_hex_string_custom ((unsigned long) so -> lmend, - "08l")); + addr_fmt)); printf_unfiltered ("%-12s", so -> symbols_loaded ? "Yes" : "No"); printf_unfiltered ("%s\n", so -> so_name); } @@ -1655,9 +1684,11 @@ FIXME Also, what if child has exit()ed? Must exit loop somehow. */ -void +void solib_create_inferior_hook() { + static int dyn_relocated; + /* If we are using the BKPT_AT_SYMBOL code, then we don't need the base yet. In fact, in the case of a SunOS4 executable being run on Solaris, we can't get it yet. find_solib will get it when it needs @@ -1676,6 +1707,32 @@ solib_create_inferior_hook() return; } + if (!dyn_relocated && exec_bfd->start_address != stop_pc) + { + /* We have to relocate the debug information. */ + CORE_ADDR displacement = stop_pc - exec_bfd->start_address; + struct section_offsets *new_offsets; + int i; + + new_offsets = alloca (symfile_objfile->num_sections + * sizeof (*new_offsets)); + + for (i = 0; i < symfile_objfile->num_sections; ++i) + ANOFFSET (new_offsets, i) = + ANOFFSET (symfile_objfile->section_offsets, i); + + ANOFFSET (new_offsets, SECT_OFF_TEXT) += displacement; + ANOFFSET (new_offsets, SECT_OFF_DATA) += displacement; + ANOFFSET (new_offsets, SECT_OFF_BSS) += displacement; + ANOFFSET (new_offsets, SECT_OFF_RODATA) += displacement; + + objfile_relocate (symfile_objfile, new_offsets); + breakpoint_re_set (); + + /* Make sure this relocation is done only once. */ + dyn_relocated = 1; + } + #ifndef SVR4_SHARED_LIBS /* Only SunOS needs the loop below, other systems should be using the special shared library breakpoints and the shared library breakpoint |