aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorRichard Sandiford <rdsandiford@googlemail.com>2008-03-20 10:53:11 +0000
committerRichard Sandiford <rdsandiford@googlemail.com>2008-03-20 10:53:11 +0000
commitccb4c9519b8b4528411a85b654af60c7dd598894 (patch)
treeaa0b1ca991bdaa02f5f3cb701bf727f7cc697d70 /binutils
parent51e38d68782784e67211a66c5408d1c1943f1aa9 (diff)
downloadfsf-binutils-gdb-ccb4c9519b8b4528411a85b654af60c7dd598894.zip
fsf-binutils-gdb-ccb4c9519b8b4528411a85b654af60c7dd598894.tar.gz
fsf-binutils-gdb-ccb4c9519b8b4528411a85b654af60c7dd598894.tar.bz2
binutils/
* readelf.c (print_mips_got_entry): New function. (process_mips_specific): Print GOT information. ld/testsuite/ * ld-mips-elf/got-dump-1.d, ld-mips-elf/got-dump-1.s, ld-mips-elf/got-dump-1.ld, ld-mips-elf/got-dump-2.d, ld-mips-elf/got-dump-2.s, ld-mips-elf/got-dump-2.ld: New tests. * ld-mips-elf/mips-elf.exp: Run them.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog5
-rw-r--r--binutils/readelf.c123
2 files changed, 128 insertions, 0 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index d3dc8b6..f7dedeb 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,8 @@
+2008-03-20 Richard Sandiford <rsandifo@nildram.co.uk>
+
+ * readelf.c (print_mips_got_entry): New function.
+ (process_mips_specific): Print GOT information.
+
2008-03-17 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* aclocal.m4: Regenerate.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index e9c380f..2807f26 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -9125,6 +9125,33 @@ process_power_specific (FILE *file)
display_power_gnu_attribute);
}
+/* DATA points to the contents of a MIPS GOT that starts at VMA PLTGOT.
+ Print the Address, Access and Initial fields of an entry at VMA ADDR
+ and return the VMA of the next entry. */
+
+static bfd_vma
+print_mips_got_entry (unsigned char *data, bfd_vma pltgot, bfd_vma addr)
+{
+ printf (" ");
+ print_vma (addr, LONG_HEX);
+ printf (" ");
+ if (addr < pltgot + 0xfff0)
+ printf ("%6d(gp)", (int) (addr - pltgot - 0x7ff0));
+ else
+ printf ("%10s", "");
+ printf (" ");
+ if (data == NULL)
+ printf ("%*s", is_32bit_elf ? 8 : 16, "<unknown>");
+ else
+ {
+ bfd_vma entry;
+
+ entry = byte_get (data + addr - pltgot, is_32bit_elf ? 4 : 8);
+ print_vma (entry, LONG_HEX);
+ }
+ return addr + (is_32bit_elf ? 4 : 8);
+}
+
static int
process_mips_specific (FILE *file)
{
@@ -9134,6 +9161,10 @@ process_mips_specific (FILE *file)
size_t conflictsno = 0;
size_t options_offset = 0;
size_t conflicts_offset = 0;
+ bfd_vma pltgot = 0;
+ bfd_vma local_gotno = 0;
+ bfd_vma gotsym = 0;
+ bfd_vma symtabno = 0;
process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL,
display_mips_gnu_attribute);
@@ -9165,6 +9196,17 @@ process_mips_specific (FILE *file)
case DT_MIPS_CONFLICTNO:
conflictsno = entry->d_un.d_val;
break;
+ case DT_PLTGOT:
+ pltgot = entry->d_un.d_val;
+ case DT_MIPS_LOCAL_GOTNO:
+ local_gotno = entry->d_un.d_val;
+ break;
+ case DT_MIPS_GOTSYM:
+ gotsym = entry->d_un.d_val;
+ break;
+ case DT_MIPS_SYMTABNO:
+ symtabno = entry->d_un.d_val;
+ break;
default:
break;
}
@@ -9515,6 +9557,87 @@ process_mips_specific (FILE *file)
free (iconf);
}
+ if (pltgot != 0 && local_gotno != 0)
+ {
+ bfd_vma entry, local_end, global_end;
+ size_t addr_size, i, offset;
+ unsigned char *data;
+
+ entry = pltgot;
+ addr_size = (is_32bit_elf ? 4 : 8);
+ local_end = pltgot + local_gotno * addr_size;
+ global_end = local_end + (symtabno - gotsym) * addr_size;
+
+ offset = offset_from_vma (file, pltgot, global_end - pltgot);
+ data = get_data (NULL, file, offset, global_end - pltgot, 1, _("GOT"));
+ printf (_("\nPrimary GOT:\n"));
+ printf (_(" Canonical gp value: "));
+ print_vma (pltgot + 0x7ff0, LONG_HEX);
+ printf ("\n\n");
+
+ printf (_(" Reserved entries:\n"));
+ printf (_(" %*s %10s %*s Purpose\n"),
+ addr_size * 2, "Address", "Access",
+ addr_size * 2, "Initial");
+ entry = print_mips_got_entry (data, pltgot, entry);
+ printf (" Lazy resolver\n");
+ if (data
+ && (byte_get (data + entry - pltgot, addr_size)
+ >> (addr_size * 8 - 1)) != 0)
+ {
+ entry = print_mips_got_entry (data, pltgot, entry);
+ printf (" Module pointer (GNU extension)\n");
+ }
+ printf ("\n");
+
+ if (entry < local_end)
+ {
+ printf (_(" Local entries:\n"));
+ printf (_(" %*s %10s %*s\n"),
+ addr_size * 2, "Address", "Access",
+ addr_size * 2, "Initial");
+ while (entry < local_end)
+ {
+ entry = print_mips_got_entry (data, pltgot, entry);
+ printf ("\n");
+ }
+ printf ("\n");
+ }
+
+ if (gotsym < symtabno)
+ {
+ int sym_width;
+
+ printf (_(" Global entries:\n"));
+ printf (_(" %*s %10s %*s %*s %-7s %3s %s\n"),
+ addr_size * 2, "Address", "Access",
+ addr_size * 2, "Initial",
+ addr_size * 2, "Sym.Val.", "Type", "Ndx", "Name");
+ sym_width = (is_32bit_elf ? 80 : 160) - 28 - addr_size * 6 - 1;
+ for (i = gotsym; i < symtabno; i++)
+ {
+ Elf_Internal_Sym *psym;
+
+ psym = dynamic_symbols + i;
+ entry = print_mips_got_entry (data, pltgot, entry);
+ printf (" ");
+ print_vma (psym->st_value, LONG_HEX);
+ printf (" %-7s %3s ",
+ get_symbol_type (ELF_ST_TYPE (psym->st_info)),
+ get_symbol_index_type (psym->st_shndx));
+ if (VALID_DYNAMIC_NAME (psym->st_name))
+ print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name));
+ else
+ printf ("<corrupt: %14ld>", psym->st_name);
+ printf ("\n");
+ }
+ printf ("\n");
+ }
+
+ if (data)
+ free (data);
+ }
+
return 1;
}