[binutils-gdb] readelf: Add --got-contents option
H.J. Lu
hjl@sourceware.org
Fri Aug 29 13:22:48 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=81e90cf63a10ad11772c2437c8f2a88f1a00c739
commit 81e90cf63a10ad11772c2437c8f2a88f1a00c739
Author: H.J. Lu <hjl.tools@gmail.com>
Date: Thu Aug 28 14:15:18 2025 -0700
readelf: Add --got-contents option
Add --got-contents option to readelf, inspired by the -G option on Solaris,
to display contents of GOT sections:
$ readelf --got-contents libfoo.so
Global Offset Table '.got' contains 1 entry:
Index: Address Reloc Sym. Name + Addend/Value
0: 000000200340 R_X86_64_GLOB_DAT foo + 0
Global Offset Table '.got.plt' contains 4 entries:
Index: Address Reloc Sym. Name + Addend/Value
0: 000000200348 200220
1: 000000200350 0
2: 000000200358 0
3: 000000200360 R_X86_64_JUMP_SLO bar + 0
When --got-content options are used:
1. Allocate an array, all_relocations, to hold all relocations.
2. Update dump_relr_relocations and dump_relocations to scan relocations
and cache them in all_relocations. Don't display relocations if not
requested.
3. Add process_got_section_contents to display contents of GOT sections
by matching the GOT entry offset against the cached relocations.
4. Update process_mips_specific to only display the GOT related contents
for --got-contents.
binutils/
* NEWS: Mention "readelf --got-contents".
* readelf.c (do_got_section_contents): New.
(elf_relocation): Likewise.
(all_relocations_root): Likewise.
(all_relocations): Likewise.
(all_relocations_count): Likewise.
(update_all_relocations): Likewise.
(dump_relr_relocations): Add a bool argument to indicate if
relocations should be displayed. Populate all_relocations if
do_got_section_contents is true.
(dump_relocations): Likewise.
(long_option_values): Add OPTION_GOT_CONTENTS.
(options): Add --got-contents.
(usage): Show --got-contents.
(parse_args): Support --got-contents.
(display_relocations): Add a bool argument, dump_reloc, to
indicate if relocations should be displayed. Call
update_all_relocations. Pass dump_reloc to dump_relr_relocations
and dump_relocations.
(process_relocs): Check do_got_section_contents. Handle
do_got_section_contents for dynamic relocations.
(process_section_contents): Pass true to display_relocations.
(process_mips_specific): Add a bool argument, dump_got, to
indicate if only the GOT related contents should be displayed.
Display all MIPS specific information if dump_got is false.
(elf_relocation_cmp): New.
(display_elf_relocation_at): Likewise.
(process_got_section_contents): Likewise.
(process_object): Call process_got_section_contents.
* doc/binutils.texi: Document --got-contents.
ld/
* testsuite/ld-i386/binutils.exp: New file.
* testsuite/ld-i386/got-1.s: Likewise.
* testsuite/ld-i386/libgot-1a.rd: Likewise.
* testsuite/ld-i386/libgot-1b.rd: Likewise.
* testsuite/ld-i386/libgot-1c.rd: Likewise.
* testsuite/ld-i386/libgot-1d.rd: Likewise.
* testsuite/ld-x86-64/binutils.exp: Likewise.
* testsuite/ld-x86-64/got-1.s: Likewise.
* testsuite/ld-x86-64/libgot-1a-x32.rd: Likewise.
* testsuite/ld-x86-64/libgot-1a.rd: Likewise.
* testsuite/ld-x86-64/libgot-1b-x32.rd: Likewise.
* testsuite/ld-x86-64/libgot-1b.rd: Likewise.
* testsuite/ld-x86-64/libgot-1c-x32.rd: Likewise.
* testsuite/ld-x86-64/libgot-1c.rd: Likewise.
* testsuite/ld-x86-64/libgot-1d-x32.rd: Likewise.
* testsuite/ld-x86-64/libgot-1d.rd: Likewise.
Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
Diff:
---
binutils/NEWS | 3 +
binutils/doc/binutils.texi | 12 +-
binutils/readelf.c | 1004 ++++++++++++++++++++++++-------
ld/testsuite/ld-i386/binutils.exp | 45 ++
ld/testsuite/ld-i386/got-1.s | 7 +
ld/testsuite/ld-i386/libgot-1a.rd | 9 +
ld/testsuite/ld-i386/libgot-1b.rd | 119 ++++
ld/testsuite/ld-i386/libgot-1c.rd | 12 +
ld/testsuite/ld-i386/libgot-1d.rd | 12 +
ld/testsuite/ld-x86-64/binutils.exp | 59 ++
ld/testsuite/ld-x86-64/got-1.s | 7 +
ld/testsuite/ld-x86-64/libgot-1a-x32.rd | 9 +
ld/testsuite/ld-x86-64/libgot-1a.rd | 9 +
ld/testsuite/ld-x86-64/libgot-1b-x32.rd | 119 ++++
ld/testsuite/ld-x86-64/libgot-1b.rd | 119 ++++
ld/testsuite/ld-x86-64/libgot-1c-x32.rd | 12 +
ld/testsuite/ld-x86-64/libgot-1c.rd | 12 +
ld/testsuite/ld-x86-64/libgot-1d-x32.rd | 12 +
ld/testsuite/ld-x86-64/libgot-1d.rd | 12 +
19 files changed, 1378 insertions(+), 215 deletions(-)
diff --git a/binutils/NEWS b/binutils/NEWS
index ccda8559897..0a4ed3bcc43 100644
--- a/binutils/NEWS
+++ b/binutils/NEWS
@@ -1,5 +1,8 @@
-*- text -*-
+* Add --got-contents option to readelf to display the contents of
+ Global Offset Table (GOT) sections.
+
* Internal changes to plugin support, and stricter target checking may result
in some errors being exposed in user options passed to the various binutils.
For example objcopy --target=TARGET now will only work if the input file is
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 4543341e00c..89425b8a15b 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -5076,6 +5076,7 @@ readelf [@option{-a}|@option{--all}]
[@option{--ctf-strings=}@var{section}]
[@option{--sframe=}@var{section}]
[@option{-I}|@option{--histogram}]
+ [@option{--got-contents}]
[@option{-v}|@option{--version}]
[@option{-W}|@option{--wide}]
[@option{-T}|@option{--silent-truncation}]
@@ -5111,7 +5112,8 @@ given.
Equivalent to specifying @option{--file-header},
@option{--program-headers}, @option{--sections}, @option{--symbols},
@option{--relocs}, @option{--dynamic}, @option{--notes},
-@option{--version-info}, @option{--arch-specific}, @option{--unwind},
+@option{--got-contents}, @option{--version-info},
+@option{--arch-specific}, @option{--unwind},
@option{--section-groups} and @option{--histogram}.
Note - this option does not enable @option{--use-dynamic} itself, so
@@ -5387,6 +5389,14 @@ string table are used.
If either of @option{--ctf-symbols} or @option{--ctf-strings} is specified, the
other must be specified as well.
+@item --got-contents
+@cindex ELF section information
+@cindex ELF reloc information
+Displays the contents of the file's Global Offset Table (GOT) sections,
+if it has any. For MIPS, this option is similar to
+@option{--arch-specific}, but it only displays the GOT related contents
+and it is ignored when @option{--arch-specific} is used.
+
@item -I
@itemx --histogram
Display a histogram of bucket list lengths when displaying the contents
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 68e193415f2..2affc713adb 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -229,6 +229,7 @@ static bool do_dyn_syms = false;
static bool do_lto_syms = false;
static bool do_reloc = false;
static bool do_sections = false;
+static bool do_got_section_contents = false;
static bool do_section_groups = false;
static bool do_section_details = false;
static bool do_segments = false;
@@ -372,6 +373,21 @@ enum versioned_symbol_info
symbol_public
};
+/* Relocation entries */
+
+typedef struct elf_relocation
+{
+ bfd_vma r_offset; /* Location at which to apply the action */
+ bfd_vma r_addend; /* Constant addend used to compute value */
+ const char *r_name; /* Relocation name. */
+ char *r_symbol; /* Relocation symbol. */
+ relocation_type r_type; /* Relocation type. */
+} elf_relocation;
+
+static elf_relocation *all_relocations_root;
+static elf_relocation *all_relocations;
+static size_t all_relocations_count;
+
static int
fseek64 (FILE *stream, int64_t offset, int whence)
{
@@ -1767,6 +1783,32 @@ symcmp (const void *p, const void *q)
return sp->st_value > sq->st_value ? 1 : (sp->st_value < sq->st_value ? -1 : 0);
}
+static void
+update_all_relocations (size_t nentries)
+{
+ size_t sz;
+
+ if (!do_got_section_contents)
+ return;
+
+ if (!all_relocations_root)
+ {
+ sz = nentries * sizeof (elf_relocation);
+ all_relocations_root = (elf_relocation *) xmalloc (sz);
+ all_relocations = all_relocations_root;
+ all_relocations_count = nentries;
+ }
+ else
+ {
+ size_t orig_count = all_relocations_count;
+ sz = (orig_count + nentries) * sizeof (elf_relocation);
+ all_relocations_root = (elf_relocation *)
+ xrealloc (all_relocations_root, sz);
+ all_relocations = all_relocations_root + orig_count;
+ all_relocations_count += nentries;
+ }
+}
+
static uint64_t
count_relr_relocations (Filedata * filedata,
Elf_Internal_Shdr * section)
@@ -1830,6 +1872,9 @@ count_relr_relocations (Filedata * filedata,
return count;
}
+/* If DUMP_RELOC is false, don't display RELR relocations, just collect
+ RELR relocations for displaying GOT section contents later. */
+
static bool
dump_relr_relocations (Filedata * filedata,
uint64_t relr_size,
@@ -1838,7 +1883,8 @@ dump_relr_relocations (Filedata * filedata,
Elf_Internal_Sym * symtab,
uint64_t nsyms,
char * strtab,
- uint64_t strtablen)
+ uint64_t strtablen,
+ bool dump_reloc)
{
uint64_t * relrs;
uint64_t nentries, i;
@@ -1860,7 +1906,8 @@ dump_relr_relocations (Filedata * filedata,
num_bits_in_entry = 63;
else
{
- warn (_("Unexpected entsize for RELR section\n"));
+ if (dump_reloc)
+ warn (_("Unexpected entsize for RELR section\n"));
return false;
}
@@ -1874,6 +1921,161 @@ dump_relr_relocations (Filedata * filedata,
if (symtab == NULL)
nsyms = 0;
+ const char *rtype = NULL;
+ if (do_got_section_contents)
+ switch (filedata->file_header.e_machine)
+ {
+ default:
+ abort ();
+
+ case EM_386:
+ case EM_IAMCU:
+ rtype = "R_386_RELATIVE";
+ break;
+
+ case EM_68K:
+ rtype = "R_68K_RELATIVE";
+ break;
+
+ case EM_860:
+ rtype = "R_860_RELATIVE";
+ break;
+
+ case EM_AARCH64:
+ rtype = "R_AARCH64_RELATIVE";
+ break;
+
+ case EM_AMDGPU:
+ rtype = "R_AMDGPU_RELATIVE64";
+ break;
+
+ case EM_ALPHA:
+ rtype = "R_ALPHA_RELATIVE";
+ break;
+
+ case EM_ALTERA_NIOS2:
+ rtype = "R_NIOS2_RELATIVE";
+ break;
+
+ case EM_ARM:
+ rtype = "R_ARM_RELATIVE";
+ break;
+
+ case EM_ARC:
+ case EM_ARC_COMPACT:
+ case EM_ARC_COMPACT2:
+ case EM_ARC_COMPACT3:
+ case EM_ARC_COMPACT3_64:
+ rtype = "R_ARC_RELATIVE";
+ break;
+
+ case EM_CRIS:
+ rtype = "R_CRIS_RELATIVE";
+ break;
+
+ case EM_CSKY:
+ rtype = "R_CKCORE_RELATIVE";
+ break;
+
+ case EM_KVX:
+ rtype = "R_KVX_RELATIVE";
+ break;
+
+ case EM_LATTICEMICO32:
+ rtype = "R_LM32_RELATIVE";
+ break;
+
+ case EM_LOONGARCH:
+ rtype = "R_LARCH_RELATIVE";
+ break;
+
+ case EM_M32R:
+ case EM_CYGNUS_M32R:
+ rtype = "R_M32R_RELATIVE";
+ break;
+
+ case EM_MCORE:
+ rtype = "R_MCORE_RELATIVE";
+ break;
+
+ case EM_METAG:
+ rtype = "R_METAG_RELATIVE";
+ break;
+
+ case EM_MN10300:
+ case EM_CYGNUS_MN10300:
+ rtype = "R_MN10300_RELATIVE";
+ break;
+
+ case EM_NDS32:
+ rtype = "R_NDS32_RELATIVE";
+ break;
+
+ case EM_OR1K:
+ rtype = "R_OR1K_RELATIVE";
+ break;
+
+ case EM_PPC:
+ rtype = "R_PPC_RELATIVE";
+ break;
+
+ case EM_PPC64:
+ rtype = "R_PPC64_RELATIVE";
+ break;
+
+ case EM_RISCV:
+ rtype = "R_RISCV_RELATIVE";
+ break;
+
+ case EM_S370:
+ rtype = "R_I370_RELATIVE";
+ break;
+
+ case EM_S390_OLD:
+ case EM_S390:
+ rtype = "R_390_RELATIVE";
+ break;
+
+ case EM_SH:
+ rtype = "R_SH_RELATIVE";
+ break;
+
+ case EM_OLD_SPARCV9:
+ case EM_SPARC32PLUS:
+ case EM_SPARCV9:
+ case EM_SPARC:
+ rtype = "R_SPARC_RELATIVE";
+ break;
+
+ case EM_TILEGX:
+ rtype = "R_TILEGX_RELATIVE";
+ break;
+
+ case EM_TILEPRO:
+ rtype = "R_TILEPRO_RELATIVE";
+ break;
+
+ case EM_V850:
+ case EM_CYGNUS_V850:
+ rtype = "R_V850_RELATIVE";
+ break;
+
+ case EM_VAX:
+ rtype = "R_VAX_RELATIVE";
+ break;
+
+ case EM_X86_64:
+ case EM_L1OM:
+ case EM_K1OM:
+ rtype = "R_X86_64_RELATIVE";
+ break;
+
+ case EM_XTENSA_OLD:
+ case EM_XTENSA:
+ rtype = "R_XTENSA_RELATIVE";
+ break;
+ }
+
if (symtab != NULL)
{
/* Symbol tables are not sorted on address, but we want a quick lookup
@@ -1884,11 +2086,15 @@ dump_relr_relocations (Filedata * filedata,
nsyms = filter_display_syms (filedata, symtab, nsyms, strtab, strtablen);
}
- if (relr_entsize == sizeof (Elf32_External_Relr))
- printf (_ ("Index: Entry Address Symbolic Address\n"));
- else
- printf (_ ("Index: Entry Address Symbolic Address\n"));
+ if (dump_reloc)
+ {
+ if (relr_entsize == sizeof (Elf32_External_Relr))
+ printf (_ ("Index: Entry Address Symbolic Address\n"));
+ else
+ printf (_ ("Index: Entry Address Symbolic Address\n"));
+ }
+ uint64_t r = 0;
for (i = 0; i < nentries; i++)
{
uint64_t entry;
@@ -1898,16 +2104,34 @@ dump_relr_relocations (Filedata * filedata,
else
entry = BYTE_GET (((Elf64_External_Relr *)relrs)[i].r_data);
- /* We assume that there will never be more than 9999 entries. */
- printf (_("%04u: "), (unsigned int) i);
- print_vma (entry, ZERO_HEX);
- printf (" ");
+ if (dump_reloc)
+ {
+ /* We assume that there will never be more than 9999
+ entries. */
+ printf (_("%04u: "), (unsigned int) i);
+ print_vma (entry, ZERO_HEX);
+ printf (" ");
+ }
if ((entry & 1) == 0)
{
where = entry;
- print_relr_addr_and_sym (filedata, symtab, nsyms, strtab, where);
- printf ("\n");
+ if (dump_reloc)
+ {
+ print_relr_addr_and_sym (filedata, symtab, nsyms, strtab,
+ where);
+ printf ("\n");
+ }
+
+ if (do_got_section_contents)
+ {
+ all_relocations[r].r_offset = where;
+ all_relocations[r].r_name = rtype;
+ all_relocations[r].r_symbol = NULL;
+ all_relocations[r].r_type = reltype_relr;
+ r++;
+ }
+
where += relr_entsize;
}
else
@@ -1920,7 +2144,7 @@ dump_relr_relocations (Filedata * filedata,
/* This can actually happen when the linker is allowed to shrink
RELR sections. For more details see: https://reviews.llvm.org/D67164. */
continue;
- else if (i == 0)
+ else if (dump_reloc && i == 0)
warn (_("Unusual RELR bitmap - no previous entry to set the base address\n"));
for (j = 0; entry >>= 1; j++)
@@ -1928,19 +2152,35 @@ dump_relr_relocations (Filedata * filedata,
{
uint64_t addr = where + (j * relr_entsize);
- if (first)
+ if (dump_reloc)
{
- print_relr_addr_and_sym (filedata, symtab, nsyms, strtab, addr);
- first = false;
+ if (first)
+ {
+ print_relr_addr_and_sym (filedata, symtab, nsyms,
+ strtab, addr);
+ first = false;
+ }
+ else
+ {
+ printf (_("\n%*s "),
+ relr_entsize == 4 ? 15 : 23, " ");
+ print_relr_addr_and_sym (filedata, symtab, nsyms,
+ strtab, addr);
+ }
}
- else
+
+ if (do_got_section_contents)
{
- printf (_("\n%*s "), relr_entsize == 4 ? 15 : 23, " ");
- print_relr_addr_and_sym (filedata, symtab, nsyms, strtab, addr);
+ all_relocations[r].r_offset = addr;
+ all_relocations[r].r_name = rtype;
+ all_relocations[r].r_symbol = NULL;
+ all_relocations[r].r_type = reltype_relr;
+ r++;
}
}
- printf ("\n");
+ if (dump_reloc)
+ printf ("\n");
where += num_bits_in_entry * relr_entsize;
}
}
@@ -1950,7 +2190,8 @@ dump_relr_relocations (Filedata * filedata,
}
/* Display the contents of the relocation data found at the specified
- offset. */
+ offset. If DUMP_RELOC is false, don't display relocations, just
+ collect relocations for displaying GOT section contents later. */
static bool
dump_relocations (Filedata * filedata,
@@ -1961,7 +2202,8 @@ dump_relocations (Filedata * filedata,
char * strtab,
uint64_t strtablen,
relocation_type rel_type,
- bool is_dynsym)
+ bool is_dynsym,
+ bool dump_reloc)
{
size_t i;
Elf_Internal_Rela * rels;
@@ -1986,26 +2228,26 @@ dump_relocations (Filedata * filedata,
return false;
}
- if (is_32bit_elf)
+ if (dump_reloc)
{
- if (rel_type == reltype_rela)
- {
- if (do_wide)
- printf (_(" Offset Info Type Sym. Value Symbol's Name + Addend\n"));
- else
- printf (_(" Offset Info Type Sym.Value Sym. Name + Addend\n"));
- }
- else
+ if (is_32bit_elf)
{
- if (do_wide)
- printf (_(" Offset Info Type Sym. Value Symbol's Name\n"));
+ if (rel_type == reltype_rela)
+ {
+ if (do_wide)
+ printf (_(" Offset Info Type Sym. Value Symbol's Name + Addend\n"));
+ else
+ printf (_(" Offset Info Type Sym.Value Sym. Name + Addend\n"));
+ }
else
- printf (_(" Offset Info Type Sym.Value Sym. Name\n"));
+ {
+ if (do_wide)
+ printf (_(" Offset Info Type Sym. Value Symbol's Name\n"));
+ else
+ printf (_(" Offset Info Type Sym.Value Sym. Name\n"));
+ }
}
- }
- else
- {
- if (rel_type == reltype_rela)
+ else if (rel_type == reltype_rela)
{
if (do_wide)
printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\n"));
@@ -2035,18 +2277,16 @@ dump_relocations (Filedata * filedata,
type = get_reloc_type (filedata, inf);
symtab_index = get_reloc_symindex (inf);
- if (is_32bit_elf)
- {
- printf ("%8.8lx %8.8lx ",
- (unsigned long) offset & 0xffffffff,
- (unsigned long) inf & 0xffffffff);
- }
- else
+ if (dump_reloc)
{
- printf (do_wide
- ? "%16.16" PRIx64 " %16.16" PRIx64 " "
- : "%12.12" PRIx64 " %12.12" PRIx64 " ",
- offset, inf);
+ if (is_32bit_elf)
+ printf ("%8.8" PRIx32 " %8.8" PRIx32 " ",
+ (uint32_t) offset, (uint32_t) inf);
+ else
+ printf (do_wide
+ ? "%16.16" PRIx64 " %16.16" PRIx64 " "
+ : "%12.12" PRIx64 " %12.12" PRIx64 " ",
+ offset, inf);
}
switch (filedata->file_header.e_machine)
@@ -2396,10 +2636,15 @@ dump_relocations (Filedata * filedata,
break;
}
- if (rtype == NULL)
- printf (_("unrecognized: %-7lx"), (unsigned long) type & 0xffffffff);
- else
- printf (do_wide ? "%-22s" : "%-17.17s", rtype);
+ char *symbol_name = NULL;
+ if (dump_reloc)
+ {
+ if (rtype == NULL)
+ printf (_("unrecognized: %-7lx"),
+ (unsigned long) type & 0xffffffff);
+ else
+ printf (do_wide ? "%-22s" : "%-17.17s", rtype);
+ }
if (filedata->file_header.e_machine == EM_ALPHA
&& rtype != NULL
@@ -2418,23 +2663,29 @@ dump_relocations (Filedata * filedata,
default: rtype = NULL;
}
- if (rtype)
- printf (" (%s)", rtype);
- else
+ if (dump_reloc)
{
- putchar (' ');
- printf (_("<unknown addend: %" PRIx64 ">"),
- rels[i].r_addend);
- res = false;
+ if (rtype)
+ printf (" (%s)", rtype);
+ else
+ {
+ putchar (' ');
+ printf (_("<unknown addend: %" PRIx64 ">"),
+ rels[i].r_addend);
+ res = false;
+ }
}
}
else if (symtab_index)
{
if (symtab == NULL || symtab_index >= nsyms)
{
- error (_(" bad symbol index: %08lx in reloc\n"),
- (unsigned long) symtab_index);
- res = false;
+ if (dump_reloc)
+ {
+ error (_(" bad symbol index: %08lx in reloc\n"),
+ (unsigned long) symtab_index);
+ res = false;
+ }
}
else
{
@@ -2453,7 +2704,8 @@ dump_relocations (Filedata * filedata,
&sym_info,
&vna_other);
- printf (" ");
+ if (dump_reloc)
+ printf (" ");
if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC)
{
@@ -2478,13 +2730,30 @@ dump_relocations (Filedata * filedata,
else
name = strtab + psym->st_name;
- len = print_symbol_name (width, name);
- if (version_string)
- printf (sym_info == symbol_public ? "@@%s" : "@%s",
- version_string);
- printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
+ if (do_got_section_contents)
+ {
+ if (version_string)
+ symbol_name = concat (name,
+ sym_info == symbol_public
+ ? "@@" : "@",
+ version_string, NULL);
+ else
+ symbol_name = xstrdup (name);
+ }
+
+ if (dump_reloc)
+ {
+ len = print_symbol_name (width, name);
+ if (version_string)
+ printf (sym_info == symbol_public
+ ? "@@%s" : "@%s",
+ version_string);
+ printf ("()%-*s",
+ len <= width ? (width + 1) - len : 1,
+ " ");
+ }
}
- else
+ else if (dump_reloc)
{
print_vma (psym->st_value, LONG_HEX);
@@ -2499,25 +2768,49 @@ dump_relocations (Filedata * filedata,
sec_name = printable_section_name_from_index
(filedata, psym->st_shndx, NULL);
- print_symbol_name (22, sec_name);
+ if (do_got_section_contents)
+ symbol_name = xstrdup (sec_name);
+ if (dump_reloc)
+ print_symbol_name (22, sec_name);
}
else if (strtab == NULL)
- printf (_("<string table index: %3ld>"), psym->st_name);
+ {
+ if (dump_reloc)
+ printf (_("<string table index: %3ld>"),
+ psym->st_name);
+ }
else if (psym->st_name >= strtablen)
{
- error (_("<corrupt string table index: %3ld>\n"),
- psym->st_name);
- res = false;
+ if (dump_reloc)
+ {
+ error (_("<corrupt string table index: %3ld>\n"),
+ psym->st_name);
+ res = false;
+ }
}
else
{
- print_symbol_name (22, strtab + psym->st_name);
- if (version_string)
- printf (sym_info == symbol_public ? "@@%s" : "@%s",
- version_string);
+ if (dump_reloc)
+ {
+ print_symbol_name (22, strtab + psym->st_name);
+ if (version_string)
+ printf (sym_info == symbol_public
+ ? "@@%s" : "@%s",
+ version_string);
+ }
+ if (do_got_section_contents)
+ {
+ if (version_string)
+ symbol_name = concat (strtab + psym->st_name,
+ sym_info == symbol_public
+ ? "@@" : "@",
+ version_string, NULL);
+ else
+ symbol_name = xstrdup (strtab + psym->st_name);
+ }
}
- if (rel_type == reltype_rela)
+ if (dump_reloc && rel_type == reltype_rela)
{
uint64_t off = rels[i].r_addend;
@@ -2528,7 +2821,7 @@ dump_relocations (Filedata * filedata,
}
}
}
- else if (rel_type == reltype_rela)
+ else if (dump_reloc && rel_type == reltype_rela)
{
uint64_t off = rels[i].r_addend;
@@ -2539,37 +2832,50 @@ dump_relocations (Filedata * filedata,
printf ("%" PRIx64, off);
}
- if (filedata->file_header.e_machine == EM_SPARCV9
- && rtype != NULL
- && streq (rtype, "R_SPARC_OLO10"))
- printf (" + %" PRIx64, ELF64_R_TYPE_DATA (inf));
-
- putchar ('\n');
+ if (do_got_section_contents)
+ {
+ all_relocations[i].r_offset = offset;
+ all_relocations[i].r_name = rtype;
+ all_relocations[i].r_symbol = symbol_name;
+ all_relocations[i].r_addend = rels[i].r_addend;
+ all_relocations[i].r_type = rel_type;
+ }
- if (! is_32bit_elf && filedata->file_header.e_machine == EM_MIPS)
+ if (dump_reloc)
{
- uint64_t type2 = ELF64_MIPS_R_TYPE2 (inf);
- uint64_t type3 = ELF64_MIPS_R_TYPE3 (inf);
- const char * rtype2 = elf_mips_reloc_type (type2);
- const char * rtype3 = elf_mips_reloc_type (type3);
+ if (filedata->file_header.e_machine == EM_SPARCV9
+ && rtype != NULL
+ && streq (rtype, "R_SPARC_OLO10"))
+ printf (" + %" PRIx64, ELF64_R_TYPE_DATA (inf));
- printf (" Type2: ");
+ putchar ('\n');
- if (rtype2 == NULL)
- printf (_("unrecognized: %-7lx"),
- (unsigned long) type2 & 0xffffffff);
- else
- printf ("%-17.17s", rtype2);
+ if (! is_32bit_elf
+ && filedata->file_header.e_machine == EM_MIPS)
+ {
+ uint64_t type2 = ELF64_MIPS_R_TYPE2 (inf);
+ uint64_t type3 = ELF64_MIPS_R_TYPE3 (inf);
+ const char * rtype2 = elf_mips_reloc_type (type2);
+ const char * rtype3 = elf_mips_reloc_type (type3);
- printf ("\n Type3: ");
+ printf (" Type2: ");
- if (rtype3 == NULL)
- printf (_("unrecognized: %-7lx"),
- (unsigned long) type3 & 0xffffffff);
- else
- printf ("%-17.17s", rtype3);
+ if (rtype2 == NULL)
+ printf (_("unrecognized: %-7lx"),
+ (unsigned long) type2 & 0xffffffff);
+ else
+ printf ("%-17.17s", rtype2);
- putchar ('\n');
+ printf ("\n Type3: ");
+
+ if (rtype3 == NULL)
+ printf (_("unrecognized: %-7lx"),
+ (unsigned long) type3 & 0xffffffff);
+ else
+ printf ("%-17.17s", rtype3);
+
+ putchar ('\n');
+ }
}
}
@@ -6097,7 +6403,8 @@ enum long_option_values
OPTION_NO_RECURSE_LIMIT,
OPTION_NO_DEMANGLING,
OPTION_NO_EXTRA_SYM_INFO,
- OPTION_SYM_BASE
+ OPTION_SYM_BASE,
+ OPTION_GOT_CONTENTS
};
static struct option options[] =
@@ -6160,6 +6467,7 @@ static struct option options[] =
#endif
{"sframe", optional_argument, 0, OPTION_SFRAME_DUMP},
{"sym-base", optional_argument, 0, OPTION_SYM_BASE},
+ {"got-contents", no_argument, 0, OPTION_GOT_CONTENTS},
{0, no_argument, 0, 0}
};
@@ -6171,7 +6479,7 @@ usage (FILE * stream)
fprintf (stream, _(" Display information about the contents of ELF format files\n"));
fprintf (stream, _(" Options are:\n"));
fprintf (stream, _("\
- -a --all Equivalent to: -h -l -S -s -r -d -V -A -I\n"));
+ -a --all Equivalent to: -h -l -S -s -r -d -V -A -I --got-contents\n"));
fprintf (stream, _("\
-h --file-header Display the ELF file header\n"));
fprintf (stream, _("\
@@ -6317,6 +6625,8 @@ usage (FILE * stream)
fprintf (stream, _("\
-I --histogram Display histogram of bucket list lengths\n"));
fprintf (stream, _("\
+ --got-contents Display GOT section contents\n"));
+ fprintf (stream, _("\
-W --wide Allow output width to exceed 80 characters\n"));
fprintf (stream, _("\
-T --silent-truncation If a symbol name is truncated, do not add [...] suffix\n"));
@@ -6441,6 +6751,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
do_histogram = true;
do_arch = true;
do_notes = true;
+ do_got_section_contents = true;
break;
case 'g':
@@ -6700,6 +7011,11 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
}
break;
+ case OPTION_GOT_CONTENTS:
+ do_got_section_contents = true;
+ do_dump = true;
+ break;
+
default:
/* xgettext:c-format */
error (_("Invalid option '-%c'\n"), c);
@@ -9437,7 +9753,8 @@ rel_type_from_sh_type (unsigned int sh_type)
static bool
display_relocations (Elf_Internal_Shdr * section,
- Filedata * filedata)
+ Filedata * filedata,
+ bool dump_reloc)
{
relocation_type rel_type = rel_type_from_sh_type (section->sh_type);
@@ -9449,19 +9766,23 @@ display_relocations (Elf_Internal_Shdr * section,
if (rel_size == 0)
return false;
- if (filedata->is_separate)
- printf (_("\nIn linked file '%s' relocation section "),
- printable_string (filedata->file_name, 0));
- else
- printf (_("\nRelocation section "));
+ if (dump_reloc)
+ {
+ if (filedata->is_separate)
+ printf (_("\nIn linked file '%s' relocation section "),
+ printable_string (filedata->file_name, 0));
+ else
+ printf (_("\nRelocation section "));
- if (filedata->string_table == NULL)
- printf ("%d", section->sh_name);
- else
- printf ("'%s'", printable_section_name (filedata, section));
+ if (filedata->string_table == NULL)
+ printf ("%d", section->sh_name);
+ else
+ printf ("'%s'", printable_section_name (filedata, section));
+ }
- uint64_t num_rela = rel_size / section->sh_entsize;
uint64_t rel_offset = section->sh_offset;
+ uint64_t num_rela = rel_size / section->sh_entsize;
+ uint64_t num_reloc;
if (rel_type == reltype_relr)
{
@@ -9470,26 +9791,33 @@ display_relocations (Elf_Internal_Shdr * section,
the number of words in the compressed RELR format. So also provide
the number of locations affected. */
- uint64_t num_reloc = count_relr_relocations (filedata, section);
+ num_reloc = count_relr_relocations (filedata, section);
- printf (_(" at offset %#" PRIx64), rel_offset);
- printf (ngettext (" contains %" PRIu64 " entry which relocates",
- " contains %" PRIu64 " entries which relocate",
- num_rela), num_rela);
- printf (ngettext (" %" PRIu64 " location:\n",
- " %" PRIu64 " locations:\n",
- num_reloc), num_reloc);
+ if (dump_reloc)
+ {
+ printf (_(" at offset %#" PRIx64), rel_offset);
+ printf (ngettext (" contains %" PRIu64 " entry which relocates",
+ " contains %" PRIu64 " entries which relocate",
+ num_rela), num_rela);
+ printf (ngettext (" %" PRIu64 " location:\n",
+ " %" PRIu64 " locations:\n",
+ num_reloc), num_reloc);
+ }
}
else
{
- printf (ngettext (" at offset %#" PRIx64
- " contains %" PRIu64 " entry:\n",
- " at offset %#" PRIx64
- " contains %" PRIu64 " entries:\n",
- num_rela),
- rel_offset, num_rela);
+ num_reloc = num_rela;
+ if (dump_reloc)
+ printf (ngettext (" at offset %#" PRIx64
+ " contains %" PRIu64 " entry:\n",
+ " at offset %#" PRIx64
+ " contains %" PRIu64 " entries:\n",
+ num_rela),
+ rel_offset, num_rela);
}
+ update_all_relocations (num_reloc);
+
Elf_Internal_Shdr * symsec;
Elf_Internal_Sym * symtab = NULL;
uint64_t nsyms = 0;
@@ -9524,12 +9852,15 @@ display_relocations (Elf_Internal_Shdr * section,
res = dump_relr_relocations (filedata, section->sh_size,
section->sh_entsize,
section->sh_offset,
- symtab, nsyms, strtab, strtablen);
+ symtab, nsyms, strtab, strtablen,
+ dump_reloc);
else
res = dump_relocations (filedata, rel_offset, rel_size,
symtab, nsyms, strtab, strtablen,
rel_type,
- symsec == NULL ? false : symsec->sh_type == SHT_DYNSYM);
+ symsec == NULL
+ ? false : symsec->sh_type == SHT_DYNSYM,
+ dump_reloc);
free (strtab);
free (symtab);
@@ -9543,14 +9874,16 @@ process_relocs (Filedata * filedata)
{
uint64_t rel_size;
uint64_t rel_offset;
+ unsigned int rel_entsz;
- if (!do_reloc)
+ if (!do_reloc && !do_got_section_contents)
return true;
if (do_using_dynamic)
{
relocation_type rel_type;
const char * name;
+ const char * entsz_name;
bool has_dynamic_reloc;
unsigned int i;
@@ -9584,16 +9917,37 @@ process_relocs (Filedata * filedata)
}
}
- if (filedata->is_separate)
- printf
- (_("\nIn linked file '%s' section '%s' at offset %#" PRIx64
- " contains %" PRId64 " bytes:\n"),
- filedata->file_name, name, rel_offset, rel_size);
- else
- printf
- (_("\n'%s' relocation section at offset %#" PRIx64
- " contains %" PRId64 " bytes:\n"),
- name, rel_offset, rel_size);
+ switch (rel_type)
+ {
+ default:
+ abort ();
+ case reltype_rel:
+ rel_entsz = filedata->dynamic_info[DT_RELENT];
+ entsz_name = "DT_RELENT";
+ break;
+ case reltype_rela:
+ rel_entsz = filedata->dynamic_info[DT_RELAENT];
+ entsz_name = "DT_RELAENT";
+ break;
+ case reltype_relr:
+ rel_entsz = filedata->dynamic_info[DT_RELRENT];
+ entsz_name = "DT_RELRENT";
+ break;
+ }
+
+ if (do_reloc)
+ {
+ if (filedata->is_separate)
+ printf
+ (_("\nIn linked file '%s' section '%s' at offset"
+ "%#" PRIx64 " contains %" PRId64 " bytes:\n"),
+ filedata->file_name, name, rel_offset, rel_size);
+ else
+ printf
+ (_("\n'%s' relocation section at offset %#" PRIx64
+ " contains %" PRId64 " bytes:\n"),
+ name, rel_offset, rel_size);
+ }
if (rel_type == reltype_relr)
dump_relr_relocations (filedata,
@@ -9603,24 +9957,37 @@ process_relocs (Filedata * filedata)
filedata->dynamic_symbols,
filedata->num_dynamic_syms,
filedata->dynamic_strings,
- filedata->dynamic_strings_length);
+ filedata->dynamic_strings_length,
+ do_reloc);
else
- dump_relocations (filedata,
- offset_from_vma (filedata, rel_offset,
- rel_size),
- rel_size,
- filedata->dynamic_symbols,
- filedata->num_dynamic_syms,
- filedata->dynamic_strings,
- filedata->dynamic_strings_length,
- rel_type, true /* is_dynamic */);
+ {
+ if (rel_entsz == 0)
+ {
+ printf (_("<missing or corrupt dynamic tag: %s>\n"),
+ entsz_name);
+ continue;
+ }
+
+ update_all_relocations (rel_size / rel_entsz);
+
+ dump_relocations (filedata,
+ offset_from_vma (filedata, rel_offset,
+ rel_size),
+ rel_size,
+ filedata->dynamic_symbols,
+ filedata->num_dynamic_syms,
+ filedata->dynamic_strings,
+ filedata->dynamic_strings_length,
+ rel_type, true /* is_dynamic */,
+ do_reloc);
+ }
}
if (is_ia64_vms (filedata)
&& process_ia64_vms_dynamic_relocs (filedata))
has_dynamic_reloc = true;
- if (! has_dynamic_reloc)
+ if (do_reloc && ! has_dynamic_reloc)
{
if (filedata->is_separate)
printf (_("\nThere are no dynamic relocations in linked file '%s'.\n"),
@@ -9639,11 +10006,11 @@ process_relocs (Filedata * filedata)
i < filedata->file_header.e_shnum;
i++, section++)
{
- if (display_relocations (section, filedata))
+ if (display_relocations (section, filedata, do_reloc))
found = true;
}
- if (! found)
+ if (do_reloc && ! found)
{
/* Users sometimes forget the -D option, so try to be helpful. */
for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++)
@@ -17627,7 +17994,7 @@ process_section_contents (Filedata * filedata)
case SHT_RELA:
case SHT_REL:
case SHT_RELR:
- res &= display_relocations (section, filedata);
+ res &= display_relocations (section, filedata, true);
break;
case SHT_NOTE:
@@ -19644,8 +20011,11 @@ get_mips_reg_size (int reg_size)
: -1;
}
+/* If DUMP_GOT is true, display only the GOT related contents.
+ Otherwise, display all MIPS specific information. */
+
static bool
-process_mips_specific (Filedata * filedata)
+process_mips_specific (Filedata * filedata, bool dump_got)
{
Elf_Internal_Dyn * entry;
Elf_Internal_Shdr *sect = NULL;
@@ -19664,60 +20034,63 @@ process_mips_specific (Filedata * filedata)
uint64_t symtabno = 0;
bool res = true;
- if (! process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL,
- display_mips_gnu_attribute))
- res = false;
-
- sect = find_section (filedata, ".MIPS.abiflags");
-
- if (sect != NULL)
+ if (!dump_got)
{
- Elf_External_ABIFlags_v0 *abiflags_ext;
- Elf_Internal_ABIFlags_v0 abiflags_in;
+ if (! process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL,
+ display_mips_gnu_attribute))
+ res = false;
- if (sizeof (Elf_External_ABIFlags_v0) != sect->sh_size)
- {
- error (_("Corrupt MIPS ABI Flags section.\n"));
- res = false;
- }
- else
+ sect = find_section (filedata, ".MIPS.abiflags");
+
+ if (sect != NULL)
{
- abiflags_ext = get_data (NULL, filedata, sect->sh_offset, 1,
- sect->sh_size, _("MIPS ABI Flags section"));
- if (abiflags_ext)
+ Elf_External_ABIFlags_v0 *abiflags_ext;
+ Elf_Internal_ABIFlags_v0 abiflags_in;
+
+ if (sizeof (Elf_External_ABIFlags_v0) != sect->sh_size)
{
- abiflags_in.version = BYTE_GET (abiflags_ext->version);
- abiflags_in.isa_level = BYTE_GET (abiflags_ext->isa_level);
- abiflags_in.isa_rev = BYTE_GET (abiflags_ext->isa_rev);
- abiflags_in.gpr_size = BYTE_GET (abiflags_ext->gpr_size);
- abiflags_in.cpr1_size = BYTE_GET (abiflags_ext->cpr1_size);
- abiflags_in.cpr2_size = BYTE_GET (abiflags_ext->cpr2_size);
- abiflags_in.fp_abi = BYTE_GET (abiflags_ext->fp_abi);
- abiflags_in.isa_ext = BYTE_GET (abiflags_ext->isa_ext);
- abiflags_in.ases = BYTE_GET (abiflags_ext->ases);
- abiflags_in.flags1 = BYTE_GET (abiflags_ext->flags1);
- abiflags_in.flags2 = BYTE_GET (abiflags_ext->flags2);
-
- printf ("\nMIPS ABI Flags Version: %d\n", abiflags_in.version);
- printf ("\nISA: MIPS%d", abiflags_in.isa_level);
- if (abiflags_in.isa_rev > 1)
- printf ("r%d", abiflags_in.isa_rev);
- printf ("\nGPR size: %d",
- get_mips_reg_size (abiflags_in.gpr_size));
- printf ("\nCPR1 size: %d",
- get_mips_reg_size (abiflags_in.cpr1_size));
- printf ("\nCPR2 size: %d",
- get_mips_reg_size (abiflags_in.cpr2_size));
- fputs ("\nFP ABI: ", stdout);
- print_mips_fp_abi_value (abiflags_in.fp_abi);
- fputs ("ISA Extension: ", stdout);
- print_mips_isa_ext (abiflags_in.isa_ext);
- fputs ("\nASEs:", stdout);
- print_mips_ases (abiflags_in.ases);
- printf ("\nFLAGS 1: %8.8lx", abiflags_in.flags1);
- printf ("\nFLAGS 2: %8.8lx", abiflags_in.flags2);
- fputc ('\n', stdout);
- free (abiflags_ext);
+ error (_("Corrupt MIPS ABI Flags section.\n"));
+ res = false;
+ }
+ else
+ {
+ abiflags_ext = get_data (NULL, filedata, sect->sh_offset, 1,
+ sect->sh_size, _("MIPS ABI Flags section"));
+ if (abiflags_ext)
+ {
+ abiflags_in.version = BYTE_GET (abiflags_ext->version);
+ abiflags_in.isa_level = BYTE_GET (abiflags_ext->isa_level);
+ abiflags_in.isa_rev = BYTE_GET (abiflags_ext->isa_rev);
+ abiflags_in.gpr_size = BYTE_GET (abiflags_ext->gpr_size);
+ abiflags_in.cpr1_size = BYTE_GET (abiflags_ext->cpr1_size);
+ abiflags_in.cpr2_size = BYTE_GET (abiflags_ext->cpr2_size);
+ abiflags_in.fp_abi = BYTE_GET (abiflags_ext->fp_abi);
+ abiflags_in.isa_ext = BYTE_GET (abiflags_ext->isa_ext);
+ abiflags_in.ases = BYTE_GET (abiflags_ext->ases);
+ abiflags_in.flags1 = BYTE_GET (abiflags_ext->flags1);
+ abiflags_in.flags2 = BYTE_GET (abiflags_ext->flags2);
+
+ printf ("\nMIPS ABI Flags Version: %d\n", abiflags_in.version);
+ printf ("\nISA: MIPS%d", abiflags_in.isa_level);
+ if (abiflags_in.isa_rev > 1)
+ printf ("r%d", abiflags_in.isa_rev);
+ printf ("\nGPR size: %d",
+ get_mips_reg_size (abiflags_in.gpr_size));
+ printf ("\nCPR1 size: %d",
+ get_mips_reg_size (abiflags_in.cpr1_size));
+ printf ("\nCPR2 size: %d",
+ get_mips_reg_size (abiflags_in.cpr2_size));
+ fputs ("\nFP ABI: ", stdout);
+ print_mips_fp_abi_value (abiflags_in.fp_abi);
+ fputs ("ISA Extension: ", stdout);
+ print_mips_isa_ext (abiflags_in.isa_ext);
+ fputs ("\nASEs:", stdout);
+ print_mips_ases (abiflags_in.ases);
+ printf ("\nFLAGS 1: %8.8lx", abiflags_in.flags1);
+ printf ("\nFLAGS 2: %8.8lx", abiflags_in.flags2);
+ fputc ('\n', stdout);
+ free (abiflags_ext);
+ }
}
}
}
@@ -19865,7 +20238,7 @@ process_mips_specific (Filedata * filedata)
break;
}
- if (liblist_offset != 0 && liblistno != 0 && do_dynamic)
+ if (!dump_got && liblist_offset != 0 && liblistno != 0 && do_dynamic)
{
Elf32_External_Lib * elib;
size_t cnt;
@@ -19950,7 +20323,7 @@ process_mips_specific (Filedata * filedata)
res = false;
}
- if (options_offset != 0)
+ if (!dump_got && options_offset != 0)
{
Elf_External_Options * eopt;
size_t offset;
@@ -20199,7 +20572,7 @@ process_mips_specific (Filedata * filedata)
res = false;
}
- if (conflicts_offset != 0 && conflictsno != 0)
+ if (!dump_got && conflicts_offset != 0 && conflictsno != 0)
{
Elf32_Conflict * iconf;
size_t cnt;
@@ -20558,6 +20931,206 @@ process_nds32_specific (Filedata * filedata)
return true;
}
+static int
+elf_relocation_cmp (const void *p, const void *q)
+{
+ const elf_relocation *rp = (const elf_relocation *) p;
+ const elf_relocation *rq = (const elf_relocation *) q;
+
+ return (rp->r_offset > rq->r_offset
+ ? 1
+ : (rp->r_offset < rq->r_offset ? -1 : 0));
+}
+
+static void
+display_elf_relocation_at (uint64_t offset, uint64_t g)
+{
+ bool matched = false;
+
+ for (size_t i = 0; i < all_relocations_count; i++)
+ if (all_relocations_root[i].r_offset == offset)
+ {
+ if (do_wide)
+ printf (" %-22s", all_relocations_root[i].r_name);
+ else
+ printf (" %-17.17s", all_relocations_root[i].r_name);
+
+ uint64_t off;
+ switch (all_relocations_root[i].r_type)
+ {
+ default:
+ abort ();
+ case reltype_rel:
+ case reltype_relr:
+ off = g;
+ break;
+ case reltype_rela:
+ off = all_relocations_root[i].r_addend;
+ break;
+ }
+
+ if (all_relocations_root[i].r_symbol)
+ {
+ printf (" %s", all_relocations_root[i].r_symbol);
+ if ((int64_t) off < 0)
+ printf (" - %" PRIx64, -off);
+ else
+ printf (" + %" PRIx64, off);
+ }
+ else
+ {
+ if ((int64_t) off < 0)
+ printf (" -%" PRIx64, -off);
+ else
+ printf (" %" PRIx64, off);
+ }
+
+ matched = true;
+ break;
+ }
+ else if (all_relocations_root[i].r_offset > offset)
+ break;
+
+ if (!matched)
+ {
+ if (do_wide)
+ printf ("%*c", 24, ' ');
+ else
+ printf ("%*c", 19, ' ');
+ printf ("%" PRIx64, g);
+ }
+}
+
+static bool
+process_got_section_contents (Filedata * filedata)
+{
+ Elf_Internal_Shdr * section;
+ unsigned int i;
+ uint64_t entries;
+ unsigned char *data;
+ bool res = true;
+
+ if (!do_got_section_contents)
+ return res;
+
+ switch (filedata->file_header.e_machine)
+ {
+ case EM_MIPS:
+ case EM_MIPS_RS3_LE:
+ /* process_mips_specific also displays GOT related contents. */
+ if (!do_arch)
+ res = process_mips_specific (filedata, true);
+ goto out;
+ }
+
+ qsort (all_relocations_root, all_relocations_count,
+ sizeof (elf_relocation), elf_relocation_cmp);
+
+ initialise_dumps_byname (filedata);
+
+ for (i = 0, section = filedata->section_headers;
+ i < filedata->file_header.e_shnum;
+ i++, section++)
+ if (section->sh_type == SHT_PROGBITS
+ && section->sh_size != 0)
+ {
+ const char *name = printable_section_name (filedata, section);
+
+ if (!startswith (name, ".got"))
+ continue;
+
+ data = (unsigned char *) get_section_contents (section,
+ filedata);
+ if (data == NULL)
+ {
+ res = false;
+ goto out;
+ }
+
+ uint32_t entsz = section->sh_entsize;
+ entries = section->sh_size / entsz;
+ if (entries == 1)
+ printf (_("\nGlobal Offset Table '%s' contains 1 entry:\n"),
+ name);
+ else
+ printf (_("\nGlobal Offset Table '%s' contains %" PRIu64
+ " entries:\n"), name, entries);
+
+ uint64_t g;
+
+ if (is_32bit_elf)
+ {
+ uint32_t j, n = entries;
+ uint32_t addr;
+ struct got32
+ {
+ unsigned char bytes[4];
+ } *got;
+
+ if (do_wide)
+ printf (_(" Index: Address Reloc Sym. Name + Addend/Value\n"));
+ /* |---9---| |---8--| |---------22---------| |........... */
+ else
+ printf (_(" Index: Address Reloc Sym. Name + Addend/Value\n"));
+ /* |--7--| |---8--| |-------17------| |........... */
+
+ addr = section->sh_addr;
+ got = (struct got32 *) data;
+ for (j = 0; j < n; j++)
+ {
+ g = BYTE_GET (got[j].bytes);
+ if (do_wide)
+ printf ("%8" PRIu32 ": %8.8" PRIx32, j, addr);
+ else
+ printf ("%6" PRIu32 ": %8.8" PRIx32, j, addr);
+ display_elf_relocation_at (addr, g);
+ putchar ('\n');
+ addr += entsz;
+ }
+ }
+ else
+ {
+ uint64_t j, addr;
+ struct got64
+ {
+ unsigned char bytes[4];
+ } *got;
+
+ if (do_wide)
+ printf (_(" Index: Address Reloc Sym. Name + Addend/Value\n"));
+ /* |---9---| |------16------| |---------22---------| |........... */
+ else
+ printf (_(" Index: Address Reloc Sym. Name + Addend/Value\n"));
+ /* |--7--| |----12----| |------17-------| |........... */
+
+ addr = section->sh_addr;
+ got = (struct got64 *) data;
+ for (j = 0; j < entries; j++)
+ {
+ g = BYTE_GET (got[j].bytes);
+ if (do_wide)
+ printf ("%8" PRIu64 ": %16.16" PRIx64, j, addr);
+ else
+ printf ("%6" PRIu64 ": %12.12" PRIx64, j, addr);
+ display_elf_relocation_at (addr, g);
+ putchar ('\n');
+ addr += entsz;
+ }
+ }
+
+ free (data);
+ }
+
+ out:
+ for (size_t j = 0; j < all_relocations_count; j++)
+ free (all_relocations_root[j].r_symbol);
+ free (all_relocations_root);
+ all_relocations_root = NULL;
+ all_relocations = NULL;
+ all_relocations_count = 0;
+ return res;
+}
+
static bool
process_gnu_liblist (Filedata * filedata)
{
@@ -23469,7 +24042,7 @@ process_arch_specific (Filedata * filedata)
case EM_MIPS:
case EM_MIPS_RS3_LE:
- return process_mips_specific (filedata);
+ return process_mips_specific (filedata, false);
case EM_MSP430:
return process_attributes (filedata, "mspabi", SHT_MSP430_ATTRIBUTES,
@@ -23833,6 +24406,9 @@ process_object (Filedata * filedata)
if (! process_section_contents (filedata))
res = false;
+ if (! process_got_section_contents (filedata))
+ res = false;
+
if (have_separate_files)
{
separate_info * d;
diff --git a/ld/testsuite/ld-i386/binutils.exp b/ld/testsuite/ld-i386/binutils.exp
new file mode 100644
index 00000000000..5069c59ca9e
--- /dev/null
+++ b/ld/testsuite/ld-i386/binutils.exp
@@ -0,0 +1,45 @@
+# Expect script for ELF/i386 binutils tests on linker outputs.
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if ![is_elf_format] {
+ return
+}
+
+if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } {
+ return
+}
+
+run_ld_link_tests [list \
+ [list \
+ "Build libgot-1.so" \
+ "-shared -melf_i386 --no-ld-generated-unwind-info \
+ -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
+ $NO_DT_RELR_LDFLAGS" \
+ "" \
+ "--32 -mx86-used-note=no --generate-missing-build-notes=no" \
+ {got-1.s} \
+ {{readelf -rW libgot-1a.rd} \
+ {readelf -aW libgot-1b.rd} \
+ {readelf --got-contents libgot-1c.rd} \
+ {readelf {--got-contents -W} libgot-1d.rd}} \
+ "libgot-1.so" \
+ ] \
+]
diff --git a/ld/testsuite/ld-i386/got-1.s b/ld/testsuite/ld-i386/got-1.s
new file mode 100644
index 00000000000..30e45f9be43
--- /dev/null
+++ b/ld/testsuite/ld-i386/got-1.s
@@ -0,0 +1,7 @@
+ .text
+ .globl func
+ .type func, @function
+func:
+ call *foo@GOT(%ebx)
+ jmp bar@PLT
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-i386/libgot-1a.rd b/ld/testsuite/ld-i386/libgot-1a.rd
new file mode 100644
index 00000000000..b8609b8fbe2
--- /dev/null
+++ b/ld/testsuite/ld-i386/libgot-1a.rd
@@ -0,0 +1,9 @@
+
+Relocation section '.rel.dyn' at offset 0x128 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name
+0+2001fc 00000206 R_386_GLOB_DAT 00000000 foo
+
+Relocation section '.rel.plt' at offset 0x130 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name
+0+20020c 00000307 R_386_JUMP_SLOT 00000000 bar
+#pass
diff --git a/ld/testsuite/ld-i386/libgot-1b.rd b/ld/testsuite/ld-i386/libgot-1b.rd
new file mode 100644
index 00000000000..faebdb49e0d
--- /dev/null
+++ b/ld/testsuite/ld-i386/libgot-1b.rd
@@ -0,0 +1,119 @@
+ELF Header:
+ Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
+ Class: ELF32
+ Data: 2's complement, little endian
+ Version: 1 \(current\)
+ OS/ABI: UNIX - System V
+ ABI Version: 0
+ Type: DYN \(Shared object file\)
+ Machine: Intel 80386
+ Version: 0x1
+ Entry point address: 0x0
+ Start of program headers: 52 \(bytes into file\)
+ Start of section headers: 768 \(bytes into file\)
+ Flags: 0x0
+ Size of this header: 52 \(bytes\)
+ Size of program headers: 32 \(bytes\)
+ Number of program headers: 4
+ Size of section headers: 40 \(bytes\)
+ Number of section headers: 14
+ Section header string table index: 13
+
+Section Headers:
+ \[Nr\] Name Type Addr Off Size ES Flg Lk Inf Al
+ \[ 0\] NULL 00000000 000000 000000 00 0 0 0
+ \[ 1\] .hash HASH 000000b4 0000b4 000024 04 A 2 0 4
+ \[ 2\] .dynsym DYNSYM 000000d8 0000d8 000040 10 A 3 1 4
+ \[ 3\] .dynstr STRTAB 00000118 000118 00000e 00 A 0 0 1
+ \[ 4\] .rel.dyn REL 00000128 000128 000008 08 A 2 0 4
+ \[ 5\] .rel.plt REL 00000130 000130 000008 08 AI 2 10 4
+ \[ 6\] .plt PROGBITS 00000140 000140 000020 04 AX 0 0 16
+ \[ 7\] .text PROGBITS 00000160 000160 00000b 00 AX 0 0 1
+ \[ 8\] .dynamic DYNAMIC 0020016c 00016c 000090 08 WA 3 0 4
+ \[ 9\] .got PROGBITS 002001fc 0001fc 000004 04 WA 0 0 4
+ \[10\] .got.plt PROGBITS 00200200 000200 000010 04 WA 0 0 4
+ \[11\] .symtab SYMTAB 00000000 000210 000060 10 12 3 4
+ \[12\] .strtab STRTAB 00000000 000270 00002d 00 0 0 1
+ \[13\] .shstrtab STRTAB 00000000 00029d 000060 00 0 0 1
+Key to Flags:
+ W \(write\), A \(alloc\), X \(execute\), M \(merge\), S \(strings\), I \(info\),
+ L \(link order\), O \(extra OS processing required\), G \(group\), T \(TLS\),
+ C \(compressed\), x \(unknown\), o \(OS specific\), E \(exclude\),
+ D \(mbind\), p \(processor specific\)
+
+There are no section groups in this file.
+
+Program Headers:
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ LOAD 0x000000 0x00000000 0x00000000 0x0016b 0x0016b R E 0x200000
+ LOAD 0x00016c 0x0020016c 0x0020016c 0x000a4 0x000a4 RW 0x200000
+ DYNAMIC 0x00016c 0x0020016c 0x0020016c 0x00090 0x00090 RW 0x4
+ GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
+
+ Section to Segment mapping:
+ Segment Sections...
+ 00 .hash .dynsym .dynstr .rel.dyn .rel.plt .plt .text
+ 01 .dynamic .got .got.plt
+ 02 .dynamic
+ 03
+
+Dynamic section at offset 0x16c contains 13 entries:
+ Tag Type Name/Value
+ 0x00000004 \(HASH\) 0xb4
+ 0x00000005 \(STRTAB\) 0x118
+ 0x00000006 \(SYMTAB\) 0xd8
+ 0x0000000a \(STRSZ\) 14 \(bytes\)
+ 0x0000000b \(SYMENT\) 16 \(bytes\)
+ 0x00000003 \(PLTGOT\) 0x200200
+ 0x00000002 \(PLTRELSZ\) 8 \(bytes\)
+ 0x00000014 \(PLTREL\) REL
+ 0x00000017 \(JMPREL\) 0x130
+ 0x00000011 \(REL\) 0x128
+ 0x00000012 \(RELSZ\) 8 \(bytes\)
+ 0x00000013 \(RELENT\) 8 \(bytes\)
+ 0x00000000 \(NULL\) 0x0
+
+Relocation section '.rel.dyn' at offset 0x128 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name
+0+2001fc 00000206 R_386_GLOB_DAT 00000000 foo
+
+Relocation section '.rel.plt' at offset 0x130 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name
+0+20020c 00000307 R_386_JUMP_SLOT 00000000 bar
+No processor specific unwind information to decode
+
+Symbol table '.dynsym' contains 4 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ +[a-f0-9]+: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ +[a-f0-9]+: 00000160 0 FUNC GLOBAL DEFAULT 7 func
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar
+
+Symbol table '.symtab' contains 6 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ +[a-f0-9]+: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ +[a-f0-9]+: 0020016c 0 OBJECT LOCAL DEFAULT 8 _DYNAMIC
+ +[a-f0-9]+: 00200200 0 OBJECT LOCAL DEFAULT 10 _GLOBAL_OFFSET_TABLE_
+ +[a-f0-9]+: 00000160 0 FUNC GLOBAL DEFAULT 7 func
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar
+
+Histogram for bucket list length \(total of 3 buckets\):
+ Length Number % of total Coverage
+ 0 1 \( 33.3%\)
+ 1 1 \( 33.3%\) 33.3%
+ 2 1 \( 33.3%\) 100.0%
+
+No version information found in this file.
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 002001fc R_386_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200200 20016c
+ +[0-9]+: 00200204 0
+ +[0-9]+: 00200208 0
+ +[0-9]+: 0020020c R_386_JUMP_SLOT bar \+ 156
+#pass
diff --git a/ld/testsuite/ld-i386/libgot-1c.rd b/ld/testsuite/ld-i386/libgot-1c.rd
new file mode 100644
index 00000000000..374b03f1658
--- /dev/null
+++ b/ld/testsuite/ld-i386/libgot-1c.rd
@@ -0,0 +1,12 @@
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 002001fc R_386_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200200 20016c
+ +[0-9]+: 00200204 0
+ +[0-9]+: 00200208 0
+ +[0-9]+: 0020020c R_386_JUMP_SLOT bar \+ 156
+#pass
diff --git a/ld/testsuite/ld-i386/libgot-1d.rd b/ld/testsuite/ld-i386/libgot-1d.rd
new file mode 100644
index 00000000000..632b47be743
--- /dev/null
+++ b/ld/testsuite/ld-i386/libgot-1d.rd
@@ -0,0 +1,12 @@
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 002001fc R_386_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200200 20016c
+ +[0-9]+: 00200204 0
+ +[0-9]+: 00200208 0
+ +[0-9]+: 0020020c R_386_JUMP_SLOT bar \+ 156
+#pass
diff --git a/ld/testsuite/ld-x86-64/binutils.exp b/ld/testsuite/ld-x86-64/binutils.exp
new file mode 100644
index 00000000000..fef997368db
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/binutils.exp
@@ -0,0 +1,59 @@
+# Expect script for ELF/x86-64 binutils tests on linker outputs.
+# Copyright (C) 2025 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+
+if ![is_elf_format] {
+ return
+}
+
+if { ![istarget "x86_64-*-*"] } {
+ return
+}
+
+run_ld_link_tests [list \
+ [list \
+ "Build libgot-1.so" \
+ "-shared -melf_x86_64 --no-ld-generated-unwind-info \
+ -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
+ -z nomark-plt $NO_DT_RELR_LDFLAGS" \
+ "" \
+ "--64 -mx86-used-note=no --generate-missing-build-notes=no" \
+ {got-1.s} \
+ {{readelf -rW libgot-1a.rd} \
+ {readelf -aW libgot-1b.rd} \
+ {readelf --got-contents libgot-1c.rd} \
+ {readelf {--got-contents -W} libgot-1d.rd}} \
+ "libgot-1.so" \
+ ] \
+ [list \
+ "Build libgot-1-x32.so" \
+ "-shared -melf32_x86_64 --no-ld-generated-unwind-info \
+ -z noseparate-code -z max-page-size=0x200000 --hash-style=sysv \
+ -z nomark-plt $NO_DT_RELR_LDFLAGS" \
+ "" \
+ "--x32 -mx86-used-note=no --generate-missing-build-notes=no" \
+ {got-1.s} \
+ {{readelf -rW libgot-1a-x32.rd} \
+ {readelf -aW libgot-1b-x32.rd} \
+ {readelf --got-contents libgot-1c-x32.rd} \
+ {readelf {--got-contents -W} libgot-1d-x32.rd}} \
+ "libgot-1-x32.so" \
+ ] \
+]
diff --git a/ld/testsuite/ld-x86-64/got-1.s b/ld/testsuite/ld-x86-64/got-1.s
new file mode 100644
index 00000000000..76370691f1d
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/got-1.s
@@ -0,0 +1,7 @@
+ .text
+ .globl func
+ .type func, @function
+func:
+ call *foo@GOTPCREL(%rip)
+ jmp bar@PLT
+ .section .note.GNU-stack,"",@progbits
diff --git a/ld/testsuite/ld-x86-64/libgot-1a-x32.rd b/ld/testsuite/ld-x86-64/libgot-1a-x32.rd
new file mode 100644
index 00000000000..6861d6588d6
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1a-x32.rd
@@ -0,0 +1,9 @@
+
+Relocation section '.rela.dyn' at offset 0x128 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name \+ Addend
+0+200200 00000206 R_X86_64_GLOB_DAT 00000000 foo \+ 0
+
+Relocation section '.rela.plt' at offset 0x134 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name \+ Addend
+0+200220 00000307 R_X86_64_JUMP_SLOT 00000000 bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1a.rd b/ld/testsuite/ld-x86-64/libgot-1a.rd
new file mode 100644
index 00000000000..8ed447003c7
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1a.rd
@@ -0,0 +1,9 @@
+
+Relocation section '.rela.dyn' at offset 0x1b8 contains 1 entry:
+ Offset Info Type Symbol's Value Symbol's Name \+ Addend
+0+200340 0000000200000006 R_X86_64_GLOB_DAT 0000000000000000 foo \+ 0
+
+Relocation section '.rela.plt' at offset 0x1d0 contains 1 entry:
+ Offset Info Type Symbol's Value Symbol's Name \+ Addend
+0+200360 0000000300000007 R_X86_64_JUMP_SLOT 0000000000000000 bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1b-x32.rd b/ld/testsuite/ld-x86-64/libgot-1b-x32.rd
new file mode 100644
index 00000000000..f900303fcce
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1b-x32.rd
@@ -0,0 +1,119 @@
+ELF Header:
+ Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
+ Class: ELF32
+ Data: 2's complement, little endian
+ Version: 1 \(current\)
+ OS/ABI: UNIX - System V
+ ABI Version: 0
+ Type: DYN \(Shared object file\)
+ Machine: Advanced Micro Devices X86-64
+ Version: 0x1
+ Entry point address: 0x0
+ Start of program headers: 52 \(bytes into file\)
+ Start of section headers: 792 \(bytes into file\)
+ Flags: 0x0
+ Size of this header: 52 \(bytes\)
+ Size of program headers: 32 \(bytes\)
+ Number of program headers: 4
+ Size of section headers: 40 \(bytes\)
+ Number of section headers: 14
+ Section header string table index: 13
+
+Section Headers:
+ \[Nr\] Name Type Addr Off Size ES Flg Lk Inf Al
+ \[ 0\] NULL 00000000 000000 000000 00 0 0 0
+ \[ 1\] .hash HASH 000000b4 0000b4 000024 04 A 2 0 4
+ \[ 2\] .dynsym DYNSYM 000000d8 0000d8 000040 10 A 3 1 4
+ \[ 3\] .dynstr STRTAB 00000118 000118 00000e 00 A 0 0 1
+ \[ 4\] .rela.dyn RELA 00000128 000128 00000c 0c A 2 0 4
+ \[ 5\] .rela.plt RELA 00000134 000134 00000c 0c AI 2 10 4
+ \[ 6\] .plt PROGBITS 00000140 000140 000020 10 AX 0 0 16
+ \[ 7\] .text PROGBITS 00000160 000160 00000b 00 AX 0 0 1
+ \[ 8\] .dynamic DYNAMIC 0020016c 00016c 000090 08 WA 3 0 4
+ \[ 9\] .got PROGBITS 00200200 000200 000008 08 WA 0 0 8
+ \[10\] .got.plt PROGBITS 00200208 000208 000020 08 WA 0 0 8
+ \[11\] .symtab SYMTAB 00000000 000228 000060 10 12 3 4
+ \[12\] .strtab STRTAB 00000000 000288 00002d 00 0 0 1
+ \[13\] .shstrtab STRTAB 00000000 0002b5 000062 00 0 0 1
+Key to Flags:
+ W \(write\), A \(alloc\), X \(execute\), M \(merge\), S \(strings\), I \(info\),
+ L \(link order\), O \(extra OS processing required\), G \(group\), T \(TLS\),
+ C \(compressed\), x \(unknown\), o \(OS specific\), E \(exclude\),
+ D \(mbind\), l \(large\), p \(processor specific\)
+
+There are no section groups in this file.
+
+Program Headers:
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ LOAD 0x000000 0x00000000 0x00000000 0x0016b 0x0016b R E 0x200000
+ LOAD 0x00016c 0x0020016c 0x0020016c 0x000bc 0x000bc RW 0x200000
+ DYNAMIC 0x00016c 0x0020016c 0x0020016c 0x00090 0x00090 RW 0x4
+ GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
+
+ Section to Segment mapping:
+ Segment Sections...
+ 00 .hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text
+ 01 .dynamic .got .got.plt
+ 02 .dynamic
+ 03
+
+Dynamic section at offset 0x16c contains 13 entries:
+ Tag Type Name/Value
+ 0x00000004 \(HASH\) 0xb4
+ 0x00000005 \(STRTAB\) 0x118
+ 0x00000006 \(SYMTAB\) 0xd8
+ 0x0000000a \(STRSZ\) 14 \(bytes\)
+ 0x0000000b \(SYMENT\) 16 \(bytes\)
+ 0x00000003 \(PLTGOT\) 0x200208
+ 0x00000002 \(PLTRELSZ\) 12 \(bytes\)
+ 0x00000014 \(PLTREL\) RELA
+ 0x00000017 \(JMPREL\) 0x134
+ 0x00000007 \(RELA\) 0x128
+ 0x00000008 \(RELASZ\) 12 \(bytes\)
+ 0x00000009 \(RELAENT\) 12 \(bytes\)
+ 0x00000000 \(NULL\) 0x0
+
+Relocation section '.rela.dyn' at offset 0x128 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name \+ Addend
+0+200200 00000206 R_X86_64_GLOB_DAT 00000000 foo \+ 0
+
+Relocation section '.rela.plt' at offset 0x134 contains 1 entry:
+ Offset Info Type Sym. Value Symbol's Name \+ Addend
+0+200220 00000307 R_X86_64_JUMP_SLOT 00000000 bar \+ 0
+No processor specific unwind information to decode
+
+Symbol table '.dynsym' contains 4 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ +[a-f0-9]+: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ +[a-f0-9]+: 00000160 0 FUNC GLOBAL DEFAULT 7 func
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar
+
+Symbol table '.symtab' contains 6 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ +[a-f0-9]+: 00000000 0 NOTYPE LOCAL DEFAULT UND
+ +[a-f0-9]+: 0020016c 0 OBJECT LOCAL DEFAULT 8 _DYNAMIC
+ +[a-f0-9]+: 00200208 0 OBJECT LOCAL DEFAULT 10 _GLOBAL_OFFSET_TABLE_
+ +[a-f0-9]+: 00000160 0 FUNC GLOBAL DEFAULT 7 func
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND foo
+ +[a-f0-9]+: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar
+
+Histogram for bucket list length \(total of 3 buckets\):
+ Length Number % of total Coverage
+ 0 1 \( 33.3%\)
+ 1 1 \( 33.3%\) 33.3%
+ 2 1 \( 33.3%\) 100.0%
+
+No version information found in this file.
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200200 R_X86_64_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200208 20016c
+ +[0-9]+: 00200210 0
+ +[0-9]+: 00200218 0
+ +[0-9]+: 00200220 R_X86_64_JUMP_SLOT bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1b.rd b/ld/testsuite/ld-x86-64/libgot-1b.rd
new file mode 100644
index 00000000000..18e432475fc
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1b.rd
@@ -0,0 +1,119 @@
+ELF Header:
+ Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
+ Class: ELF64
+ Data: 2's complement, little endian
+ Version: 1 \(current\)
+ OS/ABI: UNIX - System V
+ ABI Version: 0
+ Type: DYN \(Shared object file\)
+ Machine: Advanced Micro Devices X86-64
+ Version: 0x1
+ Entry point address: 0x0
+ Start of program headers: 64 \(bytes into file\)
+ Start of section headers: 1160 \(bytes into file\)
+ Flags: 0x0
+ Size of this header: 64 \(bytes\)
+ Size of program headers: 56 \(bytes\)
+ Number of program headers: 4
+ Size of section headers: 64 \(bytes\)
+ Number of section headers: 14
+ Section header string table index: 13
+
+Section Headers:
+ \[Nr\] Name Type Address Off Size ES Flg Lk Inf Al
+ \[ 0\] NULL 0000000000000000 000000 000000 00 0 0 0
+ \[ 1\] .hash HASH 0000000000000120 000120 000024 04 A 2 0 8
+ \[ 2\] .dynsym DYNSYM 0000000000000148 000148 000060 18 A 3 1 8
+ \[ 3\] .dynstr STRTAB 00000000000001a8 0001a8 00000e 00 A 0 0 1
+ \[ 4\] .rela.dyn RELA 00000000000001b8 0001b8 000018 18 A 2 0 8
+ \[ 5\] .rela.plt RELA 00000000000001d0 0001d0 000018 18 AI 2 10 8
+ \[ 6\] .plt PROGBITS 00000000000001f0 0001f0 000020 10 AX 0 0 16
+ \[ 7\] .text PROGBITS 0000000000000210 000210 00000b 00 AX 0 0 1
+ \[ 8\] .dynamic DYNAMIC 0000000000200220 000220 000120 10 WA 3 0 8
+ \[ 9\] .got PROGBITS 0000000000200340 000340 000008 08 WA 0 0 8
+ \[10\] .got.plt PROGBITS 0000000000200348 000348 000020 08 WA 0 0 8
+ \[11\] .symtab SYMTAB 0000000000000000 000368 000090 18 12 3 8
+ \[12\] .strtab STRTAB 0000000000000000 0003f8 00002d 00 0 0 1
+ \[13\] .shstrtab STRTAB 0000000000000000 000425 000062 00 0 0 1
+Key to Flags:
+ W \(write\), A \(alloc\), X \(execute\), M \(merge\), S \(strings\), I \(info\),
+ L \(link order\), O \(extra OS processing required\), G \(group\), T \(TLS\),
+ C \(compressed\), x \(unknown\), o \(OS specific\), E \(exclude\),
+ D \(mbind\), l \(large\), p \(processor specific\)
+
+There are no section groups in this file.
+
+Program Headers:
+ Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+ LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x00021b 0x00021b R E 0x200000
+ LOAD 0x000220 0x0000000000200220 0x0000000000200220 0x000148 0x000148 RW 0x200000
+ DYNAMIC 0x000220 0x0000000000200220 0x0000000000200220 0x000120 0x000120 RW 0x8
+ GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
+
+ Section to Segment mapping:
+ Segment Sections...
+ 00 .hash .dynsym .dynstr .rela.dyn .rela.plt .plt .text
+ 01 .dynamic .got .got.plt
+ 02 .dynamic
+ 03
+
+Dynamic section at offset 0x220 contains 13 entries:
+ Tag Type Name/Value
+ 0x0000000000000004 \(HASH\) 0x120
+ 0x0000000000000005 \(STRTAB\) 0x1a8
+ 0x0000000000000006 \(SYMTAB\) 0x148
+ 0x000000000000000a \(STRSZ\) 14 \(bytes\)
+ 0x000000000000000b \(SYMENT\) 24 \(bytes\)
+ 0x0000000000000003 \(PLTGOT\) 0x200348
+ 0x0000000000000002 \(PLTRELSZ\) 24 \(bytes\)
+ 0x0000000000000014 \(PLTREL\) RELA
+ 0x0000000000000017 \(JMPREL\) 0x1d0
+ 0x0000000000000007 \(RELA\) 0x1b8
+ 0x0000000000000008 \(RELASZ\) 24 \(bytes\)
+ 0x0000000000000009 \(RELAENT\) 24 \(bytes\)
+ 0x0000000000000000 \(NULL\) 0x0
+
+Relocation section '.rela.dyn' at offset 0x1b8 contains 1 entry:
+ Offset Info Type Symbol's Value Symbol's Name \+ Addend
+0+200340 0000000200000006 R_X86_64_GLOB_DAT 0000000000000000 foo \+ 0
+
+Relocation section '.rela.plt' at offset 0x1d0 contains 1 entry:
+ Offset Info Type Symbol's Value Symbol's Name \+ Addend
+0+200360 0000000300000007 R_X86_64_JUMP_SLOT 0000000000000000 bar \+ 0
+No processor specific unwind information to decode
+
+Symbol table '.dynsym' contains 4 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+ +[a-f0-9]+: 0000000000000210 0 FUNC GLOBAL DEFAULT 7 func
+ +[a-f0-9]+: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND foo
+ +[a-f0-9]+: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar
+
+Symbol table '.symtab' contains 6 entries:
+ Num: Value Size Type Bind Vis Ndx Name
+ +[a-f0-9]+: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
+ +[a-f0-9]+: 0000000000200220 0 OBJECT LOCAL DEFAULT 8 _DYNAMIC
+ +[a-f0-9]+: 0000000000200348 0 OBJECT LOCAL DEFAULT 10 _GLOBAL_OFFSET_TABLE_
+ +[a-f0-9]+: 0000000000000210 0 FUNC GLOBAL DEFAULT 7 func
+ +[a-f0-9]+: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND foo
+ +[a-f0-9]+: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND bar
+
+Histogram for bucket list length \(total of 3 buckets\):
+ Length Number % of total Coverage
+ 0 1 \( 33.3%\)
+ 1 1 \( 33.3%\) 33.3%
+ 2 1 \( 33.3%\) 100.0%
+
+No version information found in this file.
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 0000000000200340 R_X86_64_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 0000000000200348 200220
+ +[0-9]+: 0000000000200350 0
+ +[0-9]+: 0000000000200358 0
+ +[0-9]+: 0000000000200360 R_X86_64_JUMP_SLOT bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1c-x32.rd b/ld/testsuite/ld-x86-64/libgot-1c-x32.rd
new file mode 100644
index 00000000000..a3bdacf1fa4
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1c-x32.rd
@@ -0,0 +1,12 @@
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200200 R_X86_64_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200208 20016c
+ +[0-9]+: 00200210 0
+ +[0-9]+: 00200218 0
+ +[0-9]+: 00200220 R_X86_64_JUMP_SLO bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1c.rd b/ld/testsuite/ld-x86-64/libgot-1c.rd
new file mode 100644
index 00000000000..fc1a2605848
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1c.rd
@@ -0,0 +1,12 @@
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 000000200340 R_X86_64_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 000000200348 200220
+ +[0-9]+: 000000200350 0
+ +[0-9]+: 000000200358 0
+ +[0-9]+: 000000200360 R_X86_64_JUMP_SLO bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1d-x32.rd b/ld/testsuite/ld-x86-64/libgot-1d-x32.rd
new file mode 100644
index 00000000000..3e2693e0f52
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1d-x32.rd
@@ -0,0 +1,12 @@
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200200 R_X86_64_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 00200208 20016c
+ +[0-9]+: 00200210 0
+ +[0-9]+: 00200218 0
+ +[0-9]+: 00200220 R_X86_64_JUMP_SLOT bar \+ 0
+#pass
diff --git a/ld/testsuite/ld-x86-64/libgot-1d.rd b/ld/testsuite/ld-x86-64/libgot-1d.rd
new file mode 100644
index 00000000000..341840e9081
--- /dev/null
+++ b/ld/testsuite/ld-x86-64/libgot-1d.rd
@@ -0,0 +1,12 @@
+
+Global Offset Table '.got' contains 1 entry:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 0000000000200340 R_X86_64_GLOB_DAT foo \+ 0
+
+Global Offset Table '.got.plt' contains 4 entries:
+ Index: Address Reloc Sym. Name \+ Addend/Value
+ +[0-9]+: 0000000000200348 200220
+ +[0-9]+: 0000000000200350 0
+ +[0-9]+: 0000000000200358 0
+ +[0-9]+: 0000000000200360 R_X86_64_JUMP_SLOT bar \+ 0
+#pass
More information about the Binutils-cvs
mailing list