commit: dd5e93f8a04c854492dfbf890835b4bed6487c1d Author: Sam James <sam <AT> gentoo <DOT> org> AuthorDate: Wed Aug 27 02:48:38 2025 +0000 Commit: Sam James <sam <AT> gentoo <DOT> org> CommitDate: Wed Aug 27 02:48:38 2025 +0000 URL: https://gitweb.gentoo.org/proj/toolchain/binutils-patches.git/commit/?id=dd5e93f8
9999: add readelf -G support Bug: https://sourceware.org/PR33314 Signed-off-by: Sam James <sam <AT> gentoo.org> 9999/0007-readelf-Add-G-got-contents-options.patch | 2031 ++++++++++++++++++++ 1 file changed, 2031 insertions(+) diff --git a/9999/0007-readelf-Add-G-got-contents-options.patch b/9999/0007-readelf-Add-G-got-contents-options.patch new file mode 100644 index 0000000..5cae8ee --- /dev/null +++ b/9999/0007-readelf-Add-G-got-contents-options.patch @@ -0,0 +1,2031 @@ +From d10474f6defab5484fd8a9a79c3fa8588ca37396 Mon Sep 17 00:00:00 2001 +Message-ID: <d10474f6defab5484fd8a9a79c3fa8588ca37396.1756262897.git....@gentoo.org> +From: "H.J. Lu" <[email protected]> +Date: Tue, 26 Aug 2025 19:45:44 -0700 +Subject: [PATCH] readelf: Add -G/--got-contents options + +On Tue, Aug 26, 2025 at 02:53:40PM -0700, H.J. Lu wrote: +> Add -G/--got-contents options to readelf, inspired by the similar option +> on Solaris, to display the contents of GOT sections: +> +> $ readelf -G libfoo.so +> +> Global Offset Table '.got' contains 5 entries: +> Index: Address Reloc Sym. Name + Addend/Value +> 0: 000000002fc8 R_X86_64_GLOB_DAT bar + 0 +> 1: 000000002fd0 R_X86_64_GLOB_DAT __gmon_start__ + 0 +> 2: 000000002fd8 R_X86_64_GLOB_DAT _ITM_registerTMCloneTable + 0 +> 3: 000000002fe0 R_X86_64_GLOB_DAT __cxa_finalize@GLIBC_2.2.5 + 0 +> 4: 000000002fe8 0 +> +> Global Offset Table '.got.plt' contains 4 entries: +> Index: Address Reloc Sym. Name + Addend/Value +> 0: 000000002ff0 2dd0 +> 1: 000000002ff8 0 +> 2: 000000003000 R_X86_64_JUMP_SLO printf@GLIBC_2.2.5 + 2c0 +> 3: 000000003008 0 +> +> Any comments? +> + +The updated patch with typo fix. + +H.J. +--- + binutils/NEWS | 3 + + binutils/doc/binutils.texi | 11 +- + binutils/readelf.c | 896 +++++++++++++++++++----- + 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, 1317 insertions(+), 167 deletions(-) + create mode 100644 ld/testsuite/ld-i386/binutils.exp + create mode 100644 ld/testsuite/ld-i386/got-1.s + create mode 100644 ld/testsuite/ld-i386/libgot-1a.rd + create mode 100644 ld/testsuite/ld-i386/libgot-1b.rd + create mode 100644 ld/testsuite/ld-i386/libgot-1c.rd + create mode 100644 ld/testsuite/ld-i386/libgot-1d.rd + create mode 100644 ld/testsuite/ld-x86-64/binutils.exp + create mode 100644 ld/testsuite/ld-x86-64/got-1.s + create mode 100644 ld/testsuite/ld-x86-64/libgot-1a-x32.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1a.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1b-x32.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1b.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1c-x32.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1c.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1d-x32.rd + create mode 100644 ld/testsuite/ld-x86-64/libgot-1d.rd + +diff --git a/binutils/NEWS b/binutils/NEWS +index ccda8559897..9af862a4735 100644 +--- a/binutils/NEWS ++++ b/binutils/NEWS +@@ -1,5 +1,8 @@ + -*- text -*- + ++* Add -G/--got-contents options 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..15f31d1bcef 100644 +--- a/binutils/doc/binutils.texi ++++ b/binutils/doc/binutils.texi +@@ -5036,6 +5036,7 @@ readelf [@option{-a}|@option{--all}] + [@option{-h}|@option{--file-header}] + [@option{-l}|@option{--program-headers}|@option{--segments}] + [@option{-S}|@option{--section-headers}|@option{--sections}] ++ [@option{-G}|@option{--got-contents}] + [@option{-g}|@option{--section-groups}] + [@option{-t}|@option{--section-details}] + [@option{-e}|@option{--headers}] +@@ -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 +@@ -5143,6 +5145,13 @@ Suppress "no symbols" diagnostic. + Displays the information contained in the file's section headers, if it + has any. + ++@item -G ++@itemx --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. ++ + @item -g + @itemx --section-groups + @cindex ELF section group information +diff --git a/binutils/readelf.c b/binutils/readelf.c +index bb81c824ac3..15064daa969 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) +@@ -1836,7 +1878,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; +@@ -1861,7 +1904,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; + } + +@@ -1875,6 +1919,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: ++ break; ++ ++ 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 +@@ -1885,11 +2084,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; +@@ -1899,16 +2102,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 +@@ -1921,7 +2142,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++) +@@ -1929,19 +2150,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; + } + } +@@ -1962,7 +2199,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; +@@ -1987,38 +2225,41 @@ 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 (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) ++ if (is_32bit_elf) + { +- if (do_wide) +- printf (_(" Offset Info Type Symbol's Value Symbol's Name + Addend\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 + Addend\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 (do_wide) +- printf (_(" Offset Info Type Symbol's Value Symbol's Name\n")); ++ if (rel_type == reltype_rela) ++ { ++ if (do_wide) ++ printf (_(" Offset Info Type Symbol's 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 Symbol's Value Symbol's Name\n")); ++ else ++ printf (_(" Offset Info Type Sym. Value Sym. Name\n")); ++ } + } + } + +@@ -2036,18 +2277,17 @@ 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.8lx %8.8lx ", ++ (unsigned long) offset & 0xffffffff, ++ (unsigned long) inf & 0xffffffff); ++ else ++ printf (do_wide ++ ? "%16.16" PRIx64 " %16.16" PRIx64 " " ++ : "%12.12" PRIx64 " %12.12" PRIx64 " ", ++ offset, inf); + } + + switch (filedata->file_header.e_machine) +@@ -2397,10 +2637,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 +@@ -2419,23 +2664,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 + { +@@ -2454,7 +2705,8 @@ dump_relocations (Filedata * filedata, + &sym_info, + &vna_other); + +- printf (" "); ++ if (dump_reloc) ++ printf (" "); + + if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC) + { +@@ -2479,13 +2731,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); + +@@ -2500,25 +2769,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 (all_relocations) ++ { ++ 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; + +@@ -2529,7 +2822,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; + +@@ -2540,37 +2833,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'); ++ } + } + } + +@@ -6112,6 +6418,7 @@ static struct option options[] = + {"use-dynamic", no_argument, 0, 'D'}, + {"dynamic", no_argument, 0, 'd'}, + {"headers", no_argument, 0, 'e'}, ++ {"got-contents", no_argument, 0, 'G'}, + {"section-groups", no_argument, 0, 'g'}, + {"help", no_argument, 0, 'H'}, + {"file-header", no_argument, 0, 'h'}, +@@ -6184,6 +6491,8 @@ usage (FILE * stream) + fprintf (stream, _("\ + --sections An alias for --section-headers\n")); + fprintf (stream, _("\ ++ -G --got Display GOT section contents\n")); ++ fprintf (stream, _("\ + -g --section-groups Display the section groups\n")); + fprintf (stream, _("\ + -t --section-details Display the section details\n")); +@@ -6418,7 +6727,7 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv) + usage (stderr); + + while ((c = getopt_long +- (argc, argv, "ACDHILNPR:STU:VWXacdeghi:j:lnp:rstuvw::x:z", options, NULL)) != EOF) ++ (argc, argv, "ACDGHILNPR:STU:VWXacdeghi:j:lnp:rstuvw::x:z", options, NULL)) != EOF) + { + switch (c) + { +@@ -6442,8 +6751,13 @@ 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': ++ do_got_section_contents = true; ++ do_dump = true; ++ break; + case 'g': + do_section_groups = true; + break; +@@ -9438,7 +9752,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); + +@@ -9450,19 +9765,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) + { +@@ -9471,26 +9790,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; +@@ -9522,12 +9848,15 @@ display_relocations (Elf_Internal_Shdr * section, + bool res; + + if (rel_type == reltype_relr) +- res = dump_relr_relocations (filedata, section, symtab, nsyms, strtab, strtablen); ++ res = dump_relr_relocations (filedata, section, 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); + +@@ -9541,14 +9870,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; + +@@ -9556,57 +9887,97 @@ process_relocs (Filedata * filedata) + + for (i = 0; i < ARRAY_SIZE (dynamic_relocations); i++) + { ++ rel_size = filedata->dynamic_info[dynamic_relocations [i].size]; ++ ++ if (!rel_size) ++ continue; ++ ++ has_dynamic_reloc = true; ++ + rel_type = dynamic_relocations [i].rel_type; + name = dynamic_relocations [i].name; +- rel_size = filedata->dynamic_info[dynamic_relocations [i].size]; + rel_offset = filedata->dynamic_info[dynamic_relocations [i].reloc]; + +- if (rel_size) +- has_dynamic_reloc = true; +- + if (rel_type == reltype_unknown) + { +- if (dynamic_relocations [i].reloc == DT_JMPREL) +- switch (filedata->dynamic_info[DT_PLTREL]) +- { +- case DT_REL: +- rel_type = reltype_rel; +- break; +- case DT_RELA: +- rel_type = reltype_rela; +- break; +- } ++ if (dynamic_relocations [i].reloc != DT_JMPREL) ++ abort (); ++ ++ switch (filedata->dynamic_info[DT_PLTREL]) ++ { ++ default: ++ printf (_("<missing dynamic or corrupt tag: DT_PLTREL>\n")); ++ continue; ++ case DT_REL: ++ rel_type = reltype_rel; ++ break; ++ case DT_RELA: ++ rel_type = reltype_rela; ++ break; ++ } + } + +- if (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"), ++ (_("\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) ++ { ++ 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), ++ 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 */); ++ rel_type, true /* is_dynamic */, ++ do_reloc); + } + } + + if (is_ia64_vms (filedata)) +- if (process_ia64_vms_dynamic_relocs (filedata)) ++ if (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"), +@@ -9625,11 +9996,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++) +@@ -17613,7 +17984,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: +@@ -17704,6 +18075,196 @@ process_section_contents (Filedata * filedata) + return res; + } + ++static int ++elf_relocation_cmp (const void *p, const void *q) ++{ ++ elf_relocation *rp = (elf_relocation *) p; ++ elf_relocation *rq = (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; ++ ++ 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 void + process_mips_fpe_exception (int mask) + { +@@ -23819,6 +24380,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..eb8c14215c3 +--- /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 -G libgot-1c.rd} \ ++ {readelf -GW 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..070fa424d4d +--- /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 ++ +[a-f0-9]+: 002001fc R_386_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 00200200 20016c ++ +[a-f0-9]+: 00200204 0 ++ +[a-f0-9]+: 00200208 0 ++ +[a-f0-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..a69279ab8cc +--- /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 ++ +[a-f0-9]+: 002001fc R_386_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 00200200 20016c ++ +[a-f0-9]+: 00200204 0 ++ +[a-f0-9]+: 00200208 0 ++ +[a-f0-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..af5e3df0153 +--- /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 ++ +[a-f0-9]+: 002001fc R_386_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 00200200 20016c ++ +[a-f0-9]+: 00200204 0 ++ +[a-f0-9]+: 00200208 0 ++ +[a-f0-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..70609a8da12 +--- /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 -G libgot-1c.rd} \ ++ {readelf -GW 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 -G libgot-1c-x32.rd} \ ++ {readelf -GW 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..2245275b980 +--- /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 ++ +[a-f0-9]+: 00200200 R_X86_64_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 00200208 20016c ++ +[a-f0-9]+: 00200210 0 ++ +[a-f0-9]+: 00200218 0 ++ +[a-f0-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..9d5cc030f72 +--- /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 ++ +[a-f0-9]+: 0000000000200340 R_X86_64_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 0000000000200348 200220 ++ +[a-f0-9]+: 0000000000200350 0 ++ +[a-f0-9]+: 0000000000200358 0 ++ +[a-f0-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..bec8ac79e07 +--- /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 ++ +[a-f0-9]+: 00200200 R_X86_64_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 00200208 20016c ++ +[a-f0-9]+: 00200210 0 ++ +[a-f0-9]+: 00200218 0 ++ +[a-f0-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..4944b3111c3 +--- /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 ++ +[a-f0-9]+: 000000200340 R_X86_64_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 000000200348 200220 ++ +[a-f0-9]+: 000000200350 0 ++ +[a-f0-9]+: 000000200358 0 ++ +[a-f0-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..fdad77aab84 +--- /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 ++ +[a-f0-9]+: 00200200 R_X86_64_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 00200208 20016c ++ +[a-f0-9]+: 00200210 0 ++ +[a-f0-9]+: 00200218 0 ++ +[a-f0-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..2e0a6c1e0db +--- /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 ++ +[a-f0-9]+: 0000000000200340 R_X86_64_GLOB_DAT foo \+ 0 ++ ++Global Offset Table '.got.plt' contains 4 entries: ++ Index: Address Reloc Sym. Name \+ Addend/Value ++ +[a-f0-9]+: 0000000000200348 200220 ++ +[a-f0-9]+: 0000000000200350 0 ++ +[a-f0-9]+: 0000000000200358 0 ++ +[a-f0-9]+: 0000000000200360 R_X86_64_JUMP_SLOT bar \+ 0 ++#pass + +base-commit: f5493d6c96da9faf5f16d748cf6c899f0836b12d +-- +2.51.0 +
