diff options
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r-- | binutils/readelf.c | 1263 |
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; |