aboutsummaryrefslogtreecommitdiff
path: root/binutils/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r--binutils/readelf.c1263
1 files changed, 949 insertions, 314 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c
index dd1871d..705b776 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,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,201 @@ 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"));
if (relrs == NULL)
- return false;
+ {
+ relrs = get_data (NULL, filedata, relr_offset, 1, relr_size,
+ _("RELR relocation data"));
+ if (relrs == NULL)
+ return false;
+ }
/* 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 +2109,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 +2149,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 +2157,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 (symtab);
free (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 +2208,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 +2234,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 +2283,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 +2642,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 +2669,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 +2710,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 +2736,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 +2774,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 +2827,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 +2838,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');
+ }
}
}
@@ -2584,9 +2895,12 @@ get_aarch64_dynamic_type (unsigned long type)
{
switch (type)
{
- case DT_AARCH64_BTI_PLT: return "AARCH64_BTI_PLT";
- case DT_AARCH64_PAC_PLT: return "AARCH64_PAC_PLT";
+ case DT_AARCH64_BTI_PLT: return "AARCH64_BTI_PLT";
+ case DT_AARCH64_PAC_PLT: return "AARCH64_PAC_PLT";
case DT_AARCH64_VARIANT_PCS: return "AARCH64_VARIANT_PCS";
+ case DT_AARCH64_MEMTAG_MODE: return "AARCH64_MEMTAG_MODE";
+ case DT_AARCH64_MEMTAG_STACK: return "AARCH64_MEMTAG_STACK";
+
default:
return NULL;
}
@@ -5964,6 +6278,7 @@ get_os_specific_section_type_name (Filedata * filedata, unsigned int sh_type)
case SHT_GNU_HASH: return "GNU_HASH";
case SHT_GNU_LIBLIST: return "GNU_LIBLIST";
case SHT_GNU_OBJECT_ONLY: return "GNU_OBJECT_ONLY";
+ case SHT_GNU_SFRAME: return "GNU_SFRAME";
case SHT_SUNW_move: return "SUNW_MOVE";
case SHT_SUNW_COMDAT: return "SUNW_COMDAT";
@@ -6094,7 +6409,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[] =
@@ -6157,6 +6473,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}
};
@@ -6168,7 +6485,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, _("\
@@ -6314,6 +6631,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"));
@@ -6438,6 +6757,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':
@@ -6538,6 +6858,8 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
dump_any_debugging = true;
dwarf_select_sections_all ();
}
+ else if (strcmp (optarg, "sframe-internal-only") == 0)
+ warn (_("Unrecognized debug option 'sframe-internal-only'\n"));
else
{
do_debugging = false;
@@ -6583,9 +6905,15 @@ parse_args (struct dump_data *dumpdata, int argc, char ** argv)
break;
case OPTION_SFRAME_DUMP:
do_sframe = true;
+ /* Fix PR/32589 but keep the error messaging same ? */
+ if (optarg != NULL && strcmp (optarg, "") == 0)
+ {
+ do_dump = true;
+ error (_("Section name must be provided\n"));
+ }
/* Providing section name is optional. request_dump (), however,
thrives on non NULL optarg. Handle it explicitly here. */
- if (optarg != NULL)
+ else if (optarg != NULL)
request_dump (dumpdata, SFRAME_DUMP);
else
{
@@ -6689,6 +7017,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);
@@ -6819,7 +7152,7 @@ process_file_header (Filedata * filedata)
return false;
if (! filedata->is_separate)
- init_dwarf_regnames_by_elf_machine_code (header->e_machine);
+ init_dwarf_by_elf_machine_code (header->e_machine);
if (do_header)
{
@@ -8359,6 +8692,7 @@ process_section_headers (Filedata * filedata)
case SHT_NOTE:
case SHT_PROGBITS:
+ case SHT_GNU_SFRAME:
/* Having a zero sized section is not illegal according to the
ELF standard, but it might be an indication that something
is wrong. So issue a warning if we are running in lint mode. */
@@ -9425,7 +9759,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);
@@ -9437,19 +9772,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)
{
@@ -9458,26 +9798,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;
@@ -9509,12 +9856,23 @@ 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->sh_size,
+ section->sh_entsize,
+ section->sh_offset,
+ relrs,
+ symtab, nsyms, strtab, strtablen,
+ dump_reloc);
+ /* RELRS has been freed by dump_relr_relocations. */
+ relrs = NULL;
+ }
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);
@@ -9528,14 +9886,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;
@@ -9543,57 +9903,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;
+ }
}
- 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)
+ 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"),
@@ -9612,11 +10019,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++)
@@ -17102,44 +17509,6 @@ dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata)
#endif
static bool
-dump_section_as_sframe (Elf_Internal_Shdr * section, Filedata * filedata)
-{
- void * data = NULL;
- sframe_decoder_ctx *sfd_ctx = NULL;
- const char *print_name = printable_section_name (filedata, section);
-
- bool ret = true;
- size_t sf_size;
- int err = 0;
-
- if (strcmp (print_name, "") == 0)
- {
- error (_("Section name must be provided \n"));
- ret = false;
- return ret;
- }
-
- data = get_section_contents (section, filedata);
- sf_size = section->sh_size;
- /* Decode the contents of the section. */
- sfd_ctx = sframe_decode ((const char*)data, sf_size, &err);
- if (!sfd_ctx)
- {
- ret = false;
- error (_("SFrame decode failure: %s\n"), sframe_errmsg (err));
- goto fail;
- }
-
- printf (_("Contents of the SFrame section %s:"), print_name);
- /* Dump the contents as text. */
- dump_sframe (sfd_ctx, section->sh_addr);
-
- fail:
- free (data);
- return ret;
-}
-
-static bool
load_specific_debug_section (enum dwarf_section_display_enum debug,
const Elf_Internal_Shdr * sec,
void * data)
@@ -17518,6 +17887,7 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, Filedata * fileda
if (streq (sec->uncompressed_name, name)
|| (id == line && startswith (name, ".debug_line."))
+ || (id == sframe && section->sh_type == SHT_GNU_SFRAME)
|| streq (sec->compressed_name, name))
{
bool secondary = (section != find_section (filedata, name));
@@ -17527,6 +17897,8 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, Filedata * fileda
if (i == line && startswith (name, ".debug_line."))
sec->name = name;
+ else if (id == sframe && section->sh_type == SHT_GNU_SFRAME)
+ sec->name = name;
else if (streq (sec->uncompressed_name, name))
sec->name = sec->uncompressed_name;
else
@@ -17635,7 +18007,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:
@@ -17706,7 +18078,7 @@ process_section_contents (Filedata * filedata)
#endif
if (dump & SFRAME_DUMP)
{
- if (! dump_section_as_sframe (section, filedata))
+ if (! display_debug_section (i, section, filedata))
res = false;
}
}
@@ -17779,13 +18151,17 @@ display_tag_value (signed int tag,
else if (tag & 1)
{
/* PR 17531 file: 027-19978-0.004. */
- size_t maxlen = (end - p) - 1;
+ size_t maxlen = end - p;
putchar ('"');
if (maxlen > 0)
{
+ maxlen -= 1; /* Remove \0 from the character count. */
print_symbol_name ((int) maxlen, (const char *) p);
- p += strnlen ((char *) p, maxlen) + 1;
+ size_t len = strnlen ((char *) p, maxlen);
+ if (len == maxlen && p[maxlen] != '\0')
+ printf (_("<corrupt string tag>"));
+ p += len + 1;
}
else
{
@@ -19648,8 +20024,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;
@@ -19668,60 +20047,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)
+ {
+ error (_("Corrupt MIPS ABI Flags section.\n"));
+ res = false;
+ }
+ else
{
- 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);
+ 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);
+ }
}
}
}
@@ -19869,7 +20251,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;
@@ -19954,7 +20336,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;
@@ -20203,7 +20585,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;
@@ -20562,6 +20944,229 @@ 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;
+ 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)
{
@@ -21288,6 +21893,33 @@ decode_aarch64_feature_1_and (unsigned int bitmask)
}
static void
+decode_riscv_feature_1_and (unsigned int bitmask)
+{
+ while (bitmask)
+ {
+ unsigned int bit = bitmask & (- bitmask);
+
+ bitmask &= ~ bit;
+ switch (bit)
+ {
+ case GNU_PROPERTY_RISCV_FEATURE_1_CFI_LP_UNLABELED:
+ printf ("CFI_LP_UNLABELED");
+ break;
+
+ case GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS:
+ printf ("CFI_SS");
+ break;
+
+ default:
+ printf (_("<unknown: %x>"), bit);
+ break;
+ }
+ if (bitmask)
+ printf (", ");
+ }
+}
+
+static void
decode_1_needed (unsigned int bitmask)
{
while (bitmask)
@@ -21477,6 +22109,18 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
goto next;
}
}
+ else if (filedata->file_header.e_machine == EM_RISCV)
+ {
+ if (type == GNU_PROPERTY_RISCV_FEATURE_1_AND)
+ {
+ printf ("RISC-V AND feature: ");
+ if (datasz != 4)
+ printf (_("<corrupt length: %#x> "), datasz);
+ else
+ decode_riscv_feature_1_and (byte_get (ptr, 4));
+ goto next;
+ }
+ }
}
else
{
@@ -21709,8 +22353,13 @@ print_v850_note (Elf_Internal_Note * pnote)
{
unsigned int val;
+ printf (" %s: ", get_v850_elf_note_type (pnote->type));
+
if (pnote->descsz != 4)
- return false;
+ {
+ printf ("<corrupt descsz: %#lx>\n", pnote->descsz);
+ return false;
+ }
val = byte_get ((unsigned char *) pnote->descdata, pnote->descsz);
@@ -23279,10 +23928,15 @@ process_v850_notes (Filedata * filedata, uint64_t offset, uint64_t length)
" %#" PRIx64 " with length %#" PRIx64 ":\n"),
offset, length);
- while ((char *) external + sizeof (Elf_External_Note) < end)
+ while ((char *) external < end)
{
- Elf_External_Note * next;
+ char *next;
Elf_Internal_Note inote;
+ size_t data_remaining = end - (char *) external;
+
+ if (data_remaining < offsetof (Elf_External_Note, name))
+ break;
+ data_remaining -= offsetof (Elf_External_Note, name);
inote.type = BYTE_GET (external->type);
inote.namesz = BYTE_GET (external->namesz);
@@ -23290,47 +23944,25 @@ process_v850_notes (Filedata * filedata, uint64_t offset, uint64_t length)
inote.descsz = BYTE_GET (external->descsz);
inote.descdata = inote.namedata + align_power (inote.namesz, 2);
inote.descpos = offset + (inote.descdata - (char *) pnotes);
+ next = inote.descdata + align_power (inote.descsz, 2);
- if (inote.descdata < (char *) pnotes || inote.descdata >= end)
- {
- warn (_("Corrupt note: name size is too big: %lx\n"), inote.namesz);
- inote.descdata = inote.namedata;
- inote.namesz = 0;
- }
-
- next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
-
- if ( ((char *) next > end)
- || ((char *) next < (char *) pnotes))
+ if ((size_t) (inote.descdata - inote.namedata) < inote.namesz
+ || (size_t) (inote.descdata - inote.namedata) > data_remaining
+ || (size_t) (next - inote.descdata) < inote.descsz
+ || ((size_t) (next - inote.descdata)
+ > data_remaining - (size_t) (inote.descdata - inote.namedata)))
{
- warn (_("corrupt descsz found in note at offset %#tx\n"),
+ warn (_("note with invalid namesz and/or descsz found at offset %#tx\n"),
(char *) external - (char *) pnotes);
- warn (_(" type: %#lx, namesize: %#lx, descsize: %#lx\n"),
- inote.type, inote.namesz, inote.descsz);
+ warn (_(" type: %#lx, namesize: %#lx, descsize: %#lx, alignment: %u\n"),
+ inote.type, inote.namesz, inote.descsz, 2);
break;
}
- external = next;
-
- /* Prevent out-of-bounds indexing. */
- if ( inote.namedata + inote.namesz > end
- || inote.namedata + inote.namesz < inote.namedata)
- {
- warn (_("corrupt namesz found in note at offset %#zx\n"),
- (char *) external - (char *) pnotes);
- warn (_(" type: %#lx, namesize: %#lx, descsize: %#lx\n"),
- inote.type, inote.namesz, inote.descsz);
- break;
- }
-
- printf (" %s: ", get_v850_elf_note_type (inote.type));
+ external = (Elf_External_Note *) next;
if (! print_v850_note (& inote))
- {
- res = false;
- printf ("<corrupt sizes: namesz: %#lx, descsz: %#lx>\n",
- inote.namesz, inote.descsz);
- }
+ res = false;
}
free (pnotes);
@@ -23446,7 +24078,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,
@@ -23810,6 +24442,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;