aboutsummaryrefslogtreecommitdiff
path: root/binutils/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r--binutils/readelf.c1192
1 files changed, 934 insertions, 258 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c
index bb81c82..fd9722c 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)
{
@@ -832,8 +848,8 @@ print_symbol_name (signed int width, const char * symbol)
if (width_remaining < 8)
break;
printf ("\\u%02x%02x%02x",
- ((bytes[0] & 0x07) << 6) | ((bytes[1] & 0x3c) >> 2),
- ((bytes[1] & 0x03) << 6) | ((bytes[2] & 0x3c) >> 2),
+ ((bytes[0] & 0x07) << 2) | ((bytes[1] & 0x30) >> 4),
+ ((bytes[1] & 0x0f) << 4) | ((bytes[2] & 0x3c) >> 2),
((bytes[2] & 0x03) << 6) | (bytes[3] & 0x3f));
break;
@@ -1767,9 +1783,36 @@ 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)
+ Elf_Internal_Shdr * section,
+ uint64_t ** relrs_p)
{
uint64_t * relrs;
uint64_t nentries;
@@ -1794,9 +1837,6 @@ count_relr_relocations (Filedata * filedata,
if (nentries == 0)
return 0;
- /* FIXME: This call to get_data duplicates one that follows in
- dump_relr_relocations(). They could be combined into just
- one call. */
relrs = get_data (NULL, filedata, section->sh_offset, 1,
section->sh_size, _("RELR relocation data"));
if (relrs == NULL)
@@ -1826,23 +1866,27 @@ count_relr_relocations (Filedata * filedata,
}
}
- free (relrs);
+ *relrs_p = relrs;
+
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,
- Elf_Internal_Shdr * section,
- Elf_Internal_Sym * symtab,
+ uint64_t relr_size,
+ int relr_entsize,
+ uint64_t relr_offset,
+ uint64_t * relrs,
+ const Elf_Internal_Sym * symtab_p,
uint64_t nsyms,
char * strtab,
- uint64_t strtablen)
+ uint64_t strtablen,
+ bool dump_reloc)
{
- uint64_t * relrs;
uint64_t nentries, i;
- uint64_t relr_size = section->sh_size;
- int relr_entsize = section->sh_entsize;
- uint64_t relr_offset = section->sh_offset;
uint64_t where = 0;
int num_bits_in_entry;
@@ -1861,35 +1905,203 @@ 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;
}
- relrs = get_data (NULL, filedata, relr_offset, 1, relr_size, _("RELR relocation data"));
+ uint64_t *alloc_relrs = NULL;
if (relrs == NULL)
- return false;
+ {
+ relrs = get_data (NULL, filedata, relr_offset, 1, relr_size,
+ _("RELR relocation data"));
+ if (relrs == NULL)
+ return false;
+ alloc_relrs = relrs;
+ }
/* Paranoia. */
if (strtab == NULL)
strtablen = 0;
- if (symtab == NULL)
+ if (symtab_p == NULL)
nsyms = 0;
- if (symtab != NULL)
+ 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;
+ }
+
+ Elf_Internal_Sym *symtab = NULL;
+ if (symtab_p != NULL)
{
/* Symbol tables are not sorted on address, but we want a quick lookup
for the symbol associated with each address computed below, so sort
- the table then filter out unwanted entries. FIXME: This assumes that
- the symbol table will not be used later on for some other purpose. */
+ the table then filter out unwanted entries. */
+ size_t sz = nsyms * sizeof (*symtab);
+ symtab = xmemdup (symtab_p, sz, sz);
qsort (symtab, nsyms, sizeof (Elf_Internal_Sym), symcmp);
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 +2111,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 +2151,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,29 +2159,47 @@ 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;
}
}
- free (relrs);
+ free (symtab);
+ free (alloc_relrs);
return true;
}
/* 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,
@@ -1962,7 +2210,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,26 +2236,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"));
@@ -2036,18 +2285,16 @@ dump_relocations (Filedata * filedata,
type = get_reloc_type (filedata, inf);
symtab_index = get_reloc_symindex (inf);
- if (is_32bit_elf)
+ if (dump_reloc)
{
- 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);
+ 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)
@@ -2397,10 +2644,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 +2671,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 +2712,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 +2738,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 +2776,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;
@@ -2529,7 +2829,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 +2840,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');
+ }
}
}
@@ -2769,26 +3082,50 @@ get_solaris_section_type (unsigned long type)
{
switch (type)
{
- case 0x6fffffee: return "SUNW_ancillary";
- case 0x6fffffef: return "SUNW_capchain";
- case 0x6ffffff0: return "SUNW_capinfo";
- case 0x6ffffff1: return "SUNW_symsort";
- case 0x6ffffff2: return "SUNW_tlssort";
- case 0x6ffffff3: return "SUNW_LDYNSYM";
- case 0x6ffffff4: return "SUNW_dof";
- case 0x6ffffff5: return "SUNW_cap";
- case 0x6ffffff6: return "SUNW_SIGNATURE";
- case 0x6ffffff7: return "SUNW_ANNOTATE";
- case 0x6ffffff8: return "SUNW_DEBUGSTR";
- case 0x6ffffff9: return "SUNW_DEBUG";
- case 0x6ffffffa: return "SUNW_move";
- case 0x6ffffffb: return "SUNW_COMDAT";
- case 0x6ffffffc: return "SUNW_syminfo";
- case 0x6ffffffd: return "SUNW_verdef";
- case 0x6ffffffe: return "SUNW_verneed";
- case 0x6fffffff: return "SUNW_versym";
- case 0x70000000: return "SPARC_GOTDATA";
- default: return NULL;
+ case SHT_SUNW_symtabnsort:
+ return "SUNW_symtabnsort";
+ case SHT_SUNW_ancillary:
+ return "SUNW_ancillary";
+ case SHT_SUNW_phname:
+ return "SUNW_phname";
+ case SHT_SUNW_capchain:
+ return "SUNW_capchain";
+ case SHT_SUNW_capinfo:
+ return "SUNW_capinfo";
+ case SHT_SUNW_symsort:
+ return "SUNW_symsort";
+ case SHT_SUNW_tlssort:
+ return "SUNW_tlssort";
+ case SHT_SUNW_LDYNSYM:
+ return "SUNW_LDYNSYM";
+ case SHT_SUNW_dof:
+ return "SUNW_dof";
+ case SHT_SUNW_cap:
+ return "SUNW_cap";
+ case SHT_SUNW_SIGNATURE:
+ return "SUNW_SIGNATURE";
+ case SHT_SUNW_ANNOTATE:
+ return "SUNW_ANNOTATE";
+ case SHT_SUNW_DEBUGSTR:
+ return "SUNW_DEBUGSTR";
+ case SHT_SUNW_DEBUG:
+ return "SUNW_DEBUG";
+ case SHT_SUNW_move:
+ return "SUNW_move";
+ case SHT_SUNW_COMDAT:
+ return "SUNW_COMDAT";
+ case SHT_SUNW_syminfo:
+ return "SUNW_syminfo";
+ case SHT_SUNW_verdef:
+ return "SUNW_verdef";
+ case SHT_SUNW_verneed:
+ return "SUNW_verneed";
+ case SHT_SUNW_versym:
+ return "SUNW_versym";
+ case 0x70000000:
+ return "SPARC_GOTDATA";
+ default:
+ return NULL;
}
}
@@ -6098,7 +6435,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[] =
@@ -6161,6 +6499,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}
};
@@ -6172,7 +6511,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, _("\
@@ -6318,6 +6657,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"));
@@ -6442,6 +6783,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':
@@ -6701,6 +7043,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);
@@ -9438,7 +9785,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 +9798,24 @@ 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;
+ uint64_t *relrs = NULL;
if (rel_type == reltype_relr)
{
@@ -9471,26 +9824,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, &relrs);
- 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;
@@ -9512,22 +9872,38 @@ display_relocations (Elf_Internal_Shdr * section,
if (symsec->sh_type != SHT_SYMTAB
&& symsec->sh_type != SHT_DYNSYM)
- return false;
+ {
+ free (relrs);
+ return false;
+ }
}
if (symsec != NULL
&& !get_symtab (filedata, symsec, &symtab, &nsyms, &strtab, &strtablen))
- return false;
+ {
+ free (relrs);
+ return false;
+ }
bool res;
if (rel_type == reltype_relr)
- res = dump_relr_relocations (filedata, section, symtab, nsyms, strtab, strtablen);
+ {
+ res = dump_relr_relocations (filedata, section->sh_size,
+ section->sh_entsize,
+ section->sh_offset,
+ relrs,
+ symtab, nsyms, strtab, strtablen,
+ dump_reloc);
+ free (relrs);
+ }
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 +9917,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 +9934,104 @@ 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])
+ {
+ case DT_REL:
+ rel_type = reltype_rel;
+ break;
+ case DT_RELA:
+ rel_type = reltype_rela;
+ break;
+ }
+ }
+
+ 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 (rel_size)
+ 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)
+ dump_relr_relocations (filedata,
+ filedata->dynamic_info[DT_RELRSZ],
+ filedata->dynamic_info[DT_RELRENT],
+ filedata->dynamic_info[DT_RELR],
+ NULL,
+ filedata->dynamic_symbols,
+ filedata->num_dynamic_syms,
+ filedata->dynamic_strings,
+ filedata->dynamic_strings_length,
+ do_reloc);
+ else
+ {
+ 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))
- has_dynamic_reloc = true;
+ 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"),
@@ -9625,11 +10050,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 +18038,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:
@@ -19630,8 +20055,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;
@@ -19650,60 +20078,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);
+ }
}
}
}
@@ -19851,7 +20282,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;
@@ -19936,7 +20367,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;
@@ -20185,7 +20616,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;
@@ -20544,6 +20975,248 @@ 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;
+ bool found = false;
+
+ if (!do_got_section_contents)
+ return res;
+
+ switch (filedata->file_header.e_type)
+ {
+ case ET_DYN:
+ case ET_EXEC:
+ break;
+ default:
+ goto out;
+ }
+
+ 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);
+ found = true;
+ goto out;
+ }
+
+ if (all_relocations_count > 1)
+ 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;
+
+ found = true;
+
+ data = (unsigned char *) get_section_contents (section,
+ filedata);
+ if (data == NULL)
+ {
+ res = false;
+ goto out;
+ }
+
+ uint32_t entsz = section->sh_entsize;
+ /* NB: Gold, lld and mold set sh_entsize to 0 on .got and
+ .got.plt sections. */
+ if (entsz == 0)
+ {
+ if (is_32bit_elf)
+ switch (filedata->file_header.e_machine)
+ {
+ default:
+ entsz = 4;
+ break;
+ case EM_X86_64:
+ /* x32 uses 8 byte GOT sh_entsize. */
+ entsz = 8;
+ break;
+ }
+ else
+ entsz = 8;
+ }
+
+ 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:
+ if (! found)
+ {
+ if (filedata->is_separate)
+ printf (_("\nThere is no GOT section in linked file '%s'.\n"),
+ filedata->file_name);
+ else
+ printf (_("\nThere is no GOT section in this file.\n"));
+ }
+
+ 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)
{
@@ -23455,7 +24128,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,
@@ -23819,6 +24492,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;