aboutsummaryrefslogtreecommitdiff
path: root/gdb/solib.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/solib.c')
-rw-r--r--gdb/solib.c81
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