X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=5e8fe824b3e4f395015c867ffc21fb80308a81f1;hb=92434a14b97bf07546701613a16aaf4d8a3b3eca;hp=0c676f2b228510d31d5781265f1a0f8be82bb172;hpb=fe944acf8f858cfe6bcfd00670a88847a464717c;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 0c676f2b22..5e8fe824b3 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -1,5 +1,5 @@ /* readelf.c -- display contents of an ELF format file - Copyright (C) 1998-2018 Free Software Foundation, Inc. + Copyright (C) 1998-2019 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -60,6 +60,7 @@ #include "bucomm.h" #include "elfcomm.h" #include "dwarf.h" +#include "ctf-api.h" #include "elf/common.h" #include "elf/external.h" @@ -98,9 +99,11 @@ #include "elf/cr16.h" #include "elf/cris.h" #include "elf/crx.h" +#include "elf/csky.h" #include "elf/d10v.h" #include "elf/d30v.h" #include "elf/dlx.h" +#include "elf/bpf.h" #include "elf/epiphany.h" #include "elf/fr30.h" #include "elf/frv.h" @@ -119,6 +122,7 @@ #include "elf/m32r.h" #include "elf/m68k.h" #include "elf/m68hc11.h" +#include "elf/s12z.h" #include "elf/mcore.h" #include "elf/mep.h" #include "elf/metag.h" @@ -180,6 +184,7 @@ typedef struct elf_section_list #define DEBUG_DUMP (1 << 2) /* The -w command line switch. */ #define STRING_DUMP (1 << 3) /* The -p command line switch. */ #define RELOC_DUMP (1 << 4) /* The -R command line switch. */ +#define CTF_DUMP (1 << 5) /* The --ctf command line switch. */ typedef unsigned char dump_type; @@ -246,12 +251,17 @@ static bfd_boolean do_dump = FALSE; static bfd_boolean do_version = FALSE; static bfd_boolean do_histogram = FALSE; static bfd_boolean do_debugging = FALSE; +static bfd_boolean do_ctf = FALSE; static bfd_boolean do_arch = FALSE; static bfd_boolean do_notes = FALSE; static bfd_boolean do_archive_index = FALSE; static bfd_boolean is_32bit_elf = FALSE; static bfd_boolean decompress_dumps = FALSE; +static char *dump_ctf_parent_name; +static char *dump_ctf_symtab_name; +static char *dump_ctf_strtab_name; + struct group_list { struct group_list * next; @@ -396,10 +406,11 @@ get_data (void * var, return NULL; } - /* Be kind to memory chekers (eg valgrind, address sanitizer) by not + /* Be kind to memory checkers (eg valgrind, address sanitizer) by not attempting to allocate memory when the read is bound to fail. */ - if (amt > filedata->file_size - || offset + archive_file_offset + amt > filedata->file_size) + if (archive_file_offset > filedata->file_size + || offset > filedata->file_size - archive_file_offset + || amt > filedata->file_size - archive_file_offset - offset) { if (reason) error (_("Reading %s bytes extends past end of file for %s\n"), @@ -778,6 +789,7 @@ guess_is_rela (unsigned int e_machine) case EM_SCORE: case EM_XGATE: case EM_NFP: + case EM_BPF: return FALSE; /* Targets that use RELA relocations. */ @@ -796,6 +808,7 @@ guess_is_rela (unsigned int e_machine) case EM_CR16: case EM_CRIS: case EM_CRX: + case EM_CSKY: case EM_D30V: case EM_CYGNUS_D30V: case EM_FR30: @@ -1274,6 +1287,10 @@ dump_relocations (Filedata * filedata, rtype = elf_m68hc11_reloc_type (type); break; + case EM_S12Z: + rtype = elf_s12z_reloc_type (type); + break; + case EM_68K: rtype = elf_m68k_reloc_type (type); break; @@ -1343,6 +1360,10 @@ dump_relocations (Filedata * filedata, rtype = elf_frv_reloc_type (type); break; + case EM_CSKY: + rtype = elf_csky_reloc_type (type); + break; + case EM_FT32: rtype = elf_ft32_reloc_type (type); break; @@ -1470,6 +1491,10 @@ dump_relocations (Filedata * filedata, rtype = elf_visium_reloc_type (type); break; + case EM_BPF: + rtype = elf_bpf_reloc_type (type); + break; + case EM_ADAPTEVA_EPIPHANY: rtype = elf_epiphany_reloc_type (type); break; @@ -1785,6 +1810,19 @@ dump_relocations (Filedata * filedata, return res; } +static const char * +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_VARIANT_PCS: return "AARCH64_VARIANT_PCS"; + default: + return NULL; + } +} + static const char * get_mips_dynamic_type (unsigned long type) { @@ -2158,6 +2196,9 @@ get_dynamic_type (Filedata * filedata, unsigned long type) switch (filedata->file_header.e_machine) { + case EM_AARCH64: + result = get_aarch64_dynamic_type (type); + break; case EM_MIPS: case EM_MIPS_RS3_LE: result = get_mips_dynamic_type (type); @@ -2371,7 +2412,7 @@ get_machine_name (unsigned e_machine) case EM_TPC: return "Tenor Network TPC processor"; case EM_SNP1K: return "Trebia SNP 1000 processor"; /* 100 */ - case EM_ST200: return "STMicroelectronics ST200 microcontroller"; + case EM_ST200: return "STMicroelectronics ST200 microcontroller"; case EM_IP2K_OLD: case EM_IP2K: return "Ubicom IP2xxx 8-bit microcontrollers"; case EM_MAX: return "MAX Processor"; @@ -2487,7 +2528,7 @@ get_machine_name (unsigned e_machine) case EM_MT: return "Morpho Techologies MT processor"; case EM_ALPHA: return "Alpha"; case EM_WEBASSEMBLY: return "Web Assembly"; - case EM_DLX: return "OpenDLX"; + case EM_DLX: return "OpenDLX"; case EM_XSTORMY16: return "Sanyo XStormy16 CPU core"; case EM_IQ2000: return "Vitesse IQ2000"; case EM_M32C_OLD: @@ -2495,6 +2536,8 @@ get_machine_name (unsigned e_machine) case EM_CYGNUS_MEP: return "Toshiba MeP Media Engine"; case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY"; case EM_CYGNUS_FRV: return "Fujitsu FR-V"; + case EM_S12Z: return "Freescale S12Z"; + case EM_CSKY: return "C-SKY"; default: snprintf (buff, sizeof (buff), _(": 0x%x"), e_machine); @@ -3391,7 +3434,9 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) case E_MIPS_MACH_9000: strcat (buf, ", 9000"); break; case E_MIPS_MACH_LS2E: strcat (buf, ", loongson-2e"); break; case E_MIPS_MACH_LS2F: strcat (buf, ", loongson-2f"); break; - case E_MIPS_MACH_LS3A: strcat (buf, ", loongson-3a"); break; + case E_MIPS_MACH_GS464: strcat (buf, ", gs464"); break; + case E_MIPS_MACH_GS464E: strcat (buf, ", gs464e"); break; + case E_MIPS_MACH_GS264E: strcat (buf, ", gs264e"); break; case E_MIPS_MACH_OCTEON: strcat (buf, ", octeon"); break; case E_MIPS_MACH_OCTEON2: strcat (buf, ", octeon2"); break; case E_MIPS_MACH_OCTEON3: strcat (buf, ", octeon3"); break; @@ -3466,6 +3511,9 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) if (e_flags & EF_RISCV_RVC) strcat (buf, ", RVC"); + if (e_flags & EF_RISCV_RVE) + strcat (buf, ", RVE"); + switch (e_flags & EF_RISCV_FLOAT_ABI) { case EF_RISCV_FLOAT_ABI_SOFT: @@ -3671,6 +3719,8 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) ? ", uses String instructions" : ", bans String instructions"); if (e_flags & E_FLAG_RX_V2) strcat (buf, ", V2"); + if (e_flags & E_FLAG_RX_V3) + strcat (buf, ", V3"); break; case EM_S390: @@ -3912,6 +3962,7 @@ get_segment_type (Filedata * filedata, unsigned long p_type) case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; case PT_GNU_STACK: return "GNU_STACK"; case PT_GNU_RELRO: return "GNU_RELRO"; + case PT_GNU_PROPERTY: return "GNU_PROPERTY"; default: if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI) @@ -4183,6 +4234,16 @@ get_v850_section_type_name (unsigned int sh_type) } } +static const char * +get_riscv_section_type_name (unsigned int sh_type) +{ + switch (sh_type) + { + case SHT_RISCV_ATTRIBUTES: return "RISCV_ATTRIBUTES"; + default: return NULL; + } +} + static const char * get_section_type_name (Filedata * filedata, unsigned int sh_type) { @@ -4208,7 +4269,7 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type) case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; case SHT_GNU_HASH: return "GNU_HASH"; case SHT_GROUP: return "GROUP"; - case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICIES"; + case SHT_SYMTAB_SHNDX: return "SYMTAB SECTION INDICES"; case SHT_GNU_verdef: return "VERDEF"; case SHT_GNU_verneed: return "VERNEED"; case SHT_GNU_versym: return "VERSYM"; @@ -4263,6 +4324,9 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type) case EM_CYGNUS_V850: result = get_v850_section_type_name (sh_type); break; + case EM_RISCV: + result = get_riscv_section_type_name (sh_type); + break; default: result = NULL; break; @@ -4337,6 +4401,10 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type) #define OPTION_DWARF_DEPTH 514 #define OPTION_DWARF_START 515 #define OPTION_DWARF_CHECK 516 +#define OPTION_CTF_DUMP 517 +#define OPTION_CTF_PARENT 518 +#define OPTION_CTF_SYMBOLS 519 +#define OPTION_CTF_STRINGS 520 static struct option options[] = { @@ -4375,6 +4443,12 @@ static struct option options[] = {"dwarf-start", required_argument, 0, OPTION_DWARF_START}, {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK}, + {"ctf", required_argument, 0, OPTION_CTF_DUMP}, + + {"ctf-symbols", required_argument, 0, OPTION_CTF_SYMBOLS}, + {"ctf-strings", required_argument, 0, OPTION_CTF_STRINGS}, + {"ctf-parent", required_argument, 0, OPTION_CTF_PARENT}, + {"version", no_argument, 0, 'v'}, {"wide", no_argument, 0, 'W'}, {"help", no_argument, 0, 'H'}, @@ -4424,6 +4498,15 @@ usage (FILE * stream) --dwarf-depth=N Do not display DIEs at depth N or greater\n\ --dwarf-start=N Display DIEs starting with N, at the same depth\n\ or deeper\n")); + fprintf (stream, _("\ + --ctf= Display CTF info from section \n\ + --ctf-parent=\n\ + Use section as the CTF parent\n\n\ + --ctf-symbols=\n\ + Use section as the CTF external symtab\n\n\ + --ctf-strings=\n\ + Use section as the CTF external strtab\n\n")); + #ifdef SUPPORT_DISASSEMBLY fprintf (stream, _("\ -i --instruction-dump=\n\ @@ -4651,6 +4734,19 @@ parse_args (Filedata * filedata, int argc, char ** argv) case OPTION_DWARF_CHECK: dwarf_check = TRUE; break; + case OPTION_CTF_DUMP: + do_ctf = TRUE; + request_dump (filedata, CTF_DUMP); + break; + case OPTION_CTF_SYMBOLS: + dump_ctf_symtab_name = strdup (optarg); + break; + case OPTION_CTF_STRINGS: + dump_ctf_strtab_name = strdup (optarg); + break; + case OPTION_CTF_PARENT: + dump_ctf_parent_name = strdup (optarg); + break; case OPTION_DYN_SYMS: do_dyn_syms = TRUE; break; @@ -4749,12 +4845,12 @@ process_file_header (Filedata * filedata) get_elf_class (header->e_ident[EI_CLASS])); printf (_(" Data: %s\n"), get_data_encoding (header->e_ident[EI_DATA])); - printf (_(" Version: %d %s\n"), + printf (_(" Version: %d%s\n"), header->e_ident[EI_VERSION], (header->e_ident[EI_VERSION] == EV_CURRENT - ? "(current)" + ? _(" (current)") : (header->e_ident[EI_VERSION] != EV_NONE - ? _("") + ? _(" ") : ""))); printf (_(" OS/ABI: %s\n"), get_osabi_name (filedata, header->e_ident[EI_OSABI])); @@ -4765,45 +4861,57 @@ process_file_header (Filedata * filedata) printf (_(" Machine: %s\n"), get_machine_name (header->e_machine)); printf (_(" Version: 0x%lx\n"), - (unsigned long) header->e_version); + header->e_version); printf (_(" Entry point address: ")); - print_vma ((bfd_vma) header->e_entry, PREFIX_HEX); + print_vma (header->e_entry, PREFIX_HEX); printf (_("\n Start of program headers: ")); - print_vma ((bfd_vma) header->e_phoff, DEC); + print_vma (header->e_phoff, DEC); printf (_(" (bytes into file)\n Start of section headers: ")); - print_vma ((bfd_vma) header->e_shoff, DEC); + print_vma (header->e_shoff, DEC); printf (_(" (bytes into file)\n")); printf (_(" Flags: 0x%lx%s\n"), - (unsigned long) header->e_flags, + header->e_flags, get_machine_flags (filedata, header->e_flags, header->e_machine)); - printf (_(" Size of this header: %ld (bytes)\n"), - (long) header->e_ehsize); - printf (_(" Size of program headers: %ld (bytes)\n"), - (long) header->e_phentsize); - printf (_(" Number of program headers: %ld"), - (long) header->e_phnum); + printf (_(" Size of this header: %u (bytes)\n"), + header->e_ehsize); + printf (_(" Size of program headers: %u (bytes)\n"), + header->e_phentsize); + printf (_(" Number of program headers: %u"), + header->e_phnum); if (filedata->section_headers != NULL && header->e_phnum == PN_XNUM && filedata->section_headers[0].sh_info != 0) - printf (" (%ld)", (long) filedata->section_headers[0].sh_info); + { + header->e_phnum = filedata->section_headers[0].sh_info; + printf (" (%u)", header->e_phnum); + } putc ('\n', stdout); - printf (_(" Size of section headers: %ld (bytes)\n"), - (long) header->e_shentsize); - printf (_(" Number of section headers: %ld"), - (long) header->e_shnum); + printf (_(" Size of section headers: %u (bytes)\n"), + header->e_shentsize); + printf (_(" Number of section headers: %u"), + header->e_shnum); if (filedata->section_headers != NULL && header->e_shnum == SHN_UNDEF) - printf (" (%ld)", (long) filedata->section_headers[0].sh_size); + { + header->e_shnum = filedata->section_headers[0].sh_size; + printf (" (%u)", header->e_shnum); + } putc ('\n', stdout); - printf (_(" Section header string table index: %ld"), - (long) header->e_shstrndx); + printf (_(" Section header string table index: %u"), + header->e_shstrndx); if (filedata->section_headers != NULL && header->e_shstrndx == (SHN_XINDEX & 0xffff)) - printf (" (%u)", filedata->section_headers[0].sh_link); - else if (header->e_shstrndx != SHN_UNDEF - && header->e_shstrndx >= header->e_shnum) - printf (_(" ")); + { + header->e_shstrndx = filedata->section_headers[0].sh_link; + printf (" (%u)", header->e_shstrndx); + } + if (header->e_shstrndx != SHN_UNDEF + && header->e_shstrndx >= header->e_shnum) + { + header->e_shstrndx = SHN_UNDEF; + printf (_(" ")); + } putc ('\n', stdout); } @@ -5189,7 +5297,8 @@ process_program_headers (Filedata * filedata) segment. Check this after matching against the section headers so we don't warn on debuginfo file (which have NOBITS .dynamic sections). */ - if (dynamic_addr + dynamic_size >= filedata->file_size) + if (dynamic_addr > filedata->file_size + || dynamic_size > filedata->file_size - dynamic_addr) { error (_("the dynamic segment offset + size exceeds the size of the file\n")); dynamic_addr = dynamic_size = 0; @@ -5321,6 +5430,7 @@ get_32bit_section_headers (Filedata * filedata, bfd_boolean probe) { if (!probe) error (_("Out of memory reading %u section headers\n"), num); + free (shdrs); return FALSE; } @@ -5387,6 +5497,7 @@ get_64bit_section_headers (Filedata * filedata, bfd_boolean probe) { if (! probe) error (_("Out of memory reading %u section headers\n"), num); + free (shdrs); return FALSE; } @@ -5425,6 +5536,7 @@ get_32bit_elf_symbols (Filedata * filedata, Elf_Internal_Sym * isyms = NULL; Elf_Internal_Sym * psym; unsigned int j; + elf_section_list * entry; if (section->sh_size == 0) { @@ -5466,30 +5578,35 @@ get_32bit_elf_symbols (Filedata * filedata, if (esyms == NULL) goto exit_point; - { - elf_section_list * entry; - - shndx = NULL; - for (entry = symtab_shndx_list; entry != NULL; entry = entry->next) - if (entry->hdr->sh_link == (unsigned long) (section - filedata->section_headers)) - { - shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, - entry->hdr->sh_offset, - 1, entry->hdr->sh_size, - _("symbol table section indicies")); - if (shndx == NULL) - goto exit_point; - /* PR17531: file: heap-buffer-overflow */ - else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) - { - error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"), - printable_section_name (filedata, entry->hdr), - (unsigned long) entry->hdr->sh_size, - (unsigned long) section->sh_size); - goto exit_point; - } + shndx = NULL; + for (entry = symtab_shndx_list; entry != NULL; entry = entry->next) + { + if (entry->hdr->sh_link != (unsigned long) (section - filedata->section_headers)) + continue; + + if (shndx != NULL) + { + error (_("Multiple symbol table index sections associated with the same symbol section\n")); + free (shndx); + } + + shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, + entry->hdr->sh_offset, + 1, entry->hdr->sh_size, + _("symbol table section indices")); + if (shndx == NULL) + goto exit_point; + + /* PR17531: file: heap-buffer-overflow */ + if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) + { + error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"), + printable_section_name (filedata, entry->hdr), + (unsigned long) entry->hdr->sh_size, + (unsigned long) section->sh_size); + goto exit_point; } - } + } isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym)); @@ -5516,10 +5633,8 @@ get_32bit_elf_symbols (Filedata * filedata, } exit_point: - if (shndx != NULL) - free (shndx); - if (esyms != NULL) - free (esyms); + free (shndx); + free (esyms); if (num_syms_return != NULL) * num_syms_return = isyms == NULL ? 0 : number; @@ -5538,6 +5653,7 @@ get_64bit_elf_symbols (Filedata * filedata, Elf_Internal_Sym * isyms = NULL; Elf_Internal_Sym * psym; unsigned int j; + elf_section_list * entry; if (section->sh_size == 0) { @@ -5579,30 +5695,35 @@ get_64bit_elf_symbols (Filedata * filedata, if (!esyms) goto exit_point; - { - elf_section_list * entry; - - shndx = NULL; - for (entry = symtab_shndx_list; entry != NULL; entry = entry->next) - if (entry->hdr->sh_link == (unsigned long) (section - filedata->section_headers)) - { - shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, - entry->hdr->sh_offset, - 1, entry->hdr->sh_size, - _("symbol table section indicies")); - if (shndx == NULL) - goto exit_point; - /* PR17531: file: heap-buffer-overflow */ - else if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) - { - error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"), - printable_section_name (filedata, entry->hdr), - (unsigned long) entry->hdr->sh_size, - (unsigned long) section->sh_size); - goto exit_point; - } + shndx = NULL; + for (entry = symtab_shndx_list; entry != NULL; entry = entry->next) + { + if (entry->hdr->sh_link != (unsigned long) (section - filedata->section_headers)) + continue; + + if (shndx != NULL) + { + error (_("Multiple symbol table index sections associated with the same symbol section\n")); + free (shndx); + } + + shndx = (Elf_External_Sym_Shndx *) get_data (NULL, filedata, + entry->hdr->sh_offset, + 1, entry->hdr->sh_size, + _("symbol table section indices")); + if (shndx == NULL) + goto exit_point; + + /* PR17531: file: heap-buffer-overflow */ + if (entry->hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number) + { + error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"), + printable_section_name (filedata, entry->hdr), + (unsigned long) entry->hdr->sh_size, + (unsigned long) section->sh_size); + goto exit_point; } - } + } isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym)); @@ -5631,10 +5752,8 @@ get_64bit_elf_symbols (Filedata * filedata, } exit_point: - if (shndx != NULL) - free (shndx); - if (esyms != NULL) - free (esyms); + free (shndx); + free (esyms); if (num_syms_return != NULL) * num_syms_return = isyms == NULL ? 0 : number; @@ -6259,14 +6378,21 @@ process_section_headers (Filedata * filedata) /* Check the sh_link field. */ switch (section->sh_type) { + case SHT_REL: + case SHT_RELA: + if (section->sh_link == 0 + && (filedata->file_header.e_type == ET_EXEC + || filedata->file_header.e_type == ET_DYN)) + /* A dynamic relocation section where all entries use a + zero symbol index need not specify a symtab section. */ + break; + /* Fall through. */ case SHT_SYMTAB_SHNDX: case SHT_GROUP: case SHT_HASH: case SHT_GNU_HASH: case SHT_GNU_versym: - case SHT_REL: - case SHT_RELA: - if (section->sh_link < 1 + if (section->sh_link == 0 || section->sh_link >= filedata->file_header.e_shnum || (filedata->section_headers[section->sh_link].sh_type != SHT_SYMTAB && filedata->section_headers[section->sh_link].sh_type != SHT_DYNSYM)) @@ -6280,7 +6406,7 @@ process_section_headers (Filedata * filedata) case SHT_GNU_verneed: case SHT_GNU_verdef: case SHT_GNU_LIBLIST: - if (section->sh_link < 1 + if (section->sh_link == 0 || section->sh_link >= filedata->file_header.e_shnum || filedata->section_headers[section->sh_link].sh_type != SHT_STRTAB) warn (_("[%2u]: Link field (%u) should index a string section.\n"), @@ -6313,29 +6439,24 @@ process_section_headers (Filedata * filedata) { case SHT_REL: case SHT_RELA: - if (section->sh_info < 1 + if (section->sh_info == 0 + && (filedata->file_header.e_type == ET_EXEC + || filedata->file_header.e_type == ET_DYN)) + /* Dynamic relocations apply to segments, so they do not + need to specify the section they relocate. */ + break; + if (section->sh_info == 0 || section->sh_info >= filedata->file_header.e_shnum || (filedata->section_headers[section->sh_info].sh_type != SHT_PROGBITS && filedata->section_headers[section->sh_info].sh_type != SHT_NOBITS && filedata->section_headers[section->sh_info].sh_type != SHT_NOTE && filedata->section_headers[section->sh_info].sh_type != SHT_INIT_ARRAY + && filedata->section_headers[section->sh_info].sh_type != SHT_FINI_ARRAY + && filedata->section_headers[section->sh_info].sh_type != SHT_PREINIT_ARRAY /* FIXME: Are other section types valid ? */ && filedata->section_headers[section->sh_info].sh_type < SHT_LOOS)) - { - if (section->sh_info == 0 - && (filedata->file_header.e_type == ET_EXEC - || filedata->file_header.e_type == ET_DYN - /* These next two tests may be redundant, but - they have been left in for paranoia's sake. */ - || streq (SECTION_NAME (section), ".rel.dyn") - || streq (SECTION_NAME (section), ".rela.dyn"))) - /* Dynamic relocations apply to segments, not sections, so - they do not need an sh_info value. */ - ; - else - warn (_("[%2u]: Info field (%u) should index a relocatable section.\n"), - i, section->sh_info); - } + warn (_("[%2u]: Info field (%u) should index a relocatable section.\n"), + i, section->sh_info); break; case SHT_DYNAMIC: @@ -6499,8 +6620,7 @@ process_section_headers (Filedata * filedata) } else if (do_section_details) { - printf (" %-15.15s ", - get_section_type_name (filedata, section->sh_type)); + putchar (' '); print_vma (section->sh_addr, LONG_HEX); if ((long) section->sh_offset == section->sh_offset) printf (" %16.16lx", (unsigned long) section->sh_offset); @@ -6794,7 +6914,7 @@ process_section_groups (Filedata * filedata) printable_section_name (filedata, section), (unsigned long) section->sh_entsize, (unsigned long) section->sh_size); - break; + continue; } start = (unsigned char *) get_data (NULL, filedata, section->sh_offset, @@ -6834,7 +6954,7 @@ process_section_groups (Filedata * filedata) error (_("section [%5u] in group section [%5u] > maximum section [%5u]\n"), entry, i, filedata->file_header.e_shnum - 1); if (num_group_errors == 10) - warn (_("Further error messages about overlarge group section indicies suppressed\n")); + warn (_("Further error messages about overlarge group section indices suppressed\n")); } continue; } @@ -7556,14 +7676,14 @@ slurp_ia64_unwind_table (Filedata * filedata, for (rp = rela; rp < rela + nrelas; ++rp) { - relname = elf_ia64_reloc_type (get_reloc_type (filedata, rp->r_info)); - sym = aux->symtab + get_reloc_symindex (rp->r_info); + unsigned int sym_ndx; + unsigned int r_type = get_reloc_type (filedata, rp->r_info); + relname = elf_ia64_reloc_type (r_type); /* PR 17531: file: 9fa67536. */ if (relname == NULL) { - warn (_("Skipping unknown relocation type: %u\n"), - get_reloc_type (filedata, rp->r_info)); + warn (_("Skipping unknown relocation type: %u\n"), r_type); continue; } @@ -7582,6 +7702,15 @@ slurp_ia64_unwind_table (Filedata * filedata, continue; } + sym_ndx = get_reloc_symindex (rp->r_info); + if (sym_ndx >= aux->nsyms) + { + warn (_("Skipping reloc with invalid symbol index: %u\n"), + sym_ndx); + continue; + } + sym = aux->symtab + sym_ndx; + switch (rp->r_offset / eh_addr_size % 3) { case 0: @@ -8012,19 +8141,40 @@ slurp_hppa_unwind_table (Filedata * filedata, for (rp = rela; rp < rela + nrelas; ++rp) { - relname = elf_hppa_reloc_type (get_reloc_type (filedata, rp->r_info)); - sym = aux->symtab + get_reloc_symindex (rp->r_info); + unsigned int sym_ndx; + unsigned int r_type = get_reloc_type (filedata, rp->r_info); + relname = elf_hppa_reloc_type (r_type); + + if (relname == NULL) + { + warn (_("Skipping unknown relocation type: %u\n"), r_type); + continue; + } /* R_PARISC_SEGREL32 or R_PARISC_SEGREL64. */ if (! const_strneq (relname, "R_PARISC_SEGREL")) { - warn (_("Skipping unexpected relocation type %s\n"), relname); + warn (_("Skipping unexpected relocation type: %s\n"), relname); continue; } i = rp->r_offset / unw_ent_size; + if (i >= aux->table_len) + { + warn (_("Skipping reloc with overlarge offset: %lx\n"), i); + continue; + } + + sym_ndx = get_reloc_symindex (rp->r_info); + if (sym_ndx >= aux->nsyms) + { + warn (_("Skipping reloc with invalid symbol index: %u\n"), + sym_ndx); + continue; + } + sym = aux->symtab + sym_ndx; - switch ((rp->r_offset % unw_ent_size) / eh_addr_size) + switch ((rp->r_offset % unw_ent_size) / 4) { case 0: aux->table[i].start.section = sym->st_shndx; @@ -8092,7 +8242,7 @@ hppa_process_unwind (Filedata * filedata) { if (streq (SECTION_NAME (sec), ".PARISC.unwind")) { - unsigned long num_unwind = sec->sh_size / (2 * eh_addr_size + 8); + unsigned long num_unwind = sec->sh_size / 16; printf (ngettext ("\nUnwind section '%s' at offset 0x%lx " "contains %lu entry:\n", @@ -8105,8 +8255,8 @@ hppa_process_unwind (Filedata * filedata) if (! slurp_hppa_unwind_table (filedata, &aux, sec)) res = FALSE; - - if (aux.table_len > 0) + + if (res && aux.table_len > 0) { if (! dump_hppa_unwind (filedata, &aux)) res = FALSE; @@ -8765,21 +8915,28 @@ decode_tic6x_unwind_bytecode (Filedata * filedata, } printf (_("pop frame {")); - reg = nregs - 1; - for (i = i * 2; i > 0; i--) + if (nregs == 0) + { + printf (_("*corrupt* - no registers specified")); + } + else { - if (regpos[reg].offset == i - 1) + reg = nregs - 1; + for (i = i * 2; i > 0; i--) { - name = tic6x_unwind_regnames[regpos[reg].reg]; - if (reg > 0) - reg--; - } - else - name = _("[pad]"); + if (regpos[reg].offset == i - 1) + { + name = tic6x_unwind_regnames[regpos[reg].reg]; + if (reg > 0) + reg--; + } + else + name = _("[pad]"); - fputs (name, stdout); - if (i > 1) - printf (", "); + fputs (name, stdout); + if (i > 1) + printf (", "); + } } printf ("}"); @@ -8872,6 +9029,11 @@ decode_arm_unwind (Filedata * filedata, remaining = 4; } + else + { + addr.section = SHN_UNDEF; + addr.offset = 0; + } if ((word & 0x80000000) == 0) { @@ -9248,6 +9410,21 @@ process_unwind (Filedata * filedata) return TRUE; } +static void +dynamic_section_aarch64_val (Elf_Internal_Dyn * entry) +{ + switch (entry->d_tag) + { + case DT_AARCH64_BTI_PLT: + case DT_AARCH64_PAC_PLT: + break; + default: + print_vma (entry->d_un.d_ptr, PREFIX_HEX); + break; + } + putchar ('\n'); +} + static void dynamic_section_mips_val (Elf_Internal_Dyn * entry) { @@ -9664,6 +9841,11 @@ process_dynamic_section (Filedata * filedata) section.sh_entsize = sizeof (Elf64_External_Sym); section.sh_name = filedata->string_table_length; + if (dynamic_symbols != NULL) + { + error (_("Multiple dynamic symbol table sections found\n")); + free (dynamic_symbols); + } dynamic_symbols = GET_ELF_SYMBOLS (filedata, §ion, & num_dynamic_syms); if (num_dynamic_syms < 1) { @@ -9707,11 +9889,16 @@ process_dynamic_section (Filedata * filedata) continue; } + if (dynamic_strings != NULL) + { + error (_("Multiple dynamic string tables found\n")); + free (dynamic_strings); + } + dynamic_strings = (char *) get_data (NULL, filedata, offset, 1, str_tab_len, _("dynamic string table")); dynamic_strings_length = dynamic_strings == NULL ? 0 : str_tab_len; - break; } } @@ -9754,6 +9941,11 @@ process_dynamic_section (Filedata * filedata) if (!extsyminfo) return FALSE; + if (dynamic_syminfo != NULL) + { + error (_("Multiple dynamic symbol information sections found\n")); + free (dynamic_syminfo); + } dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); if (dynamic_syminfo == NULL) { @@ -10247,6 +10439,9 @@ process_dynamic_section (Filedata * filedata) { switch (filedata->file_header.e_machine) { + case EM_AARCH64: + dynamic_section_aarch64_val (entry); + break; case EM_MIPS: case EM_MIPS_RS3_LE: dynamic_section_mips_val (entry); @@ -10344,7 +10539,7 @@ process_version_sections (Filedata * filedata) printable_section_name (filedata, section), section->sh_info); - printf (_(" Addr: 0x")); + printf (_(" Addr: 0x")); printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %u (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, @@ -10636,7 +10831,7 @@ process_version_sections (Filedata * filedata) total), printable_section_name (filedata, section), (unsigned long) total); - printf (_(" Addr: ")); + printf (_(" Addr: 0x")); printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %u (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, @@ -10939,6 +11134,19 @@ get_symbol_visibility (unsigned int visibility) } } +static const char * +get_alpha_symbol_other (unsigned int other) +{ + switch (other) + { + case STO_ALPHA_NOPV: return "NOPV"; + case STO_ALPHA_STD_GPLOAD: return "STD GPLOAD"; + default: + error (_("Unrecognized alpah specific other value: %u"), other); + return _(""); + } +} + static const char * get_solaris_symbol_visibility (unsigned int visibility) { @@ -10951,6 +11159,22 @@ get_solaris_symbol_visibility (unsigned int visibility) } } +static const char * +get_aarch64_symbol_other (unsigned int other) +{ + static char buf[32]; + + if (other & STO_AARCH64_VARIANT_PCS) + { + other &= ~STO_AARCH64_VARIANT_PCS; + if (other == 0) + return "VARIANT_PCS"; + snprintf (buf, sizeof buf, "VARIANT_PCS | %x", other); + return buf; + } + return NULL; +} + static const char * get_mips_symbol_other (unsigned int other) { @@ -11036,11 +11260,16 @@ get_ia64_symbol_other (Filedata * filedata, unsigned int other) static const char * get_ppc64_symbol_other (unsigned int other) { - if (PPC64_LOCAL_ENTRY_OFFSET (other) != 0) + if ((other & ~STO_PPC64_LOCAL_MASK) != 0) + return NULL; + + other >>= STO_PPC64_LOCAL_BIT; + if (other <= 6) { static char buf[32]; - snprintf (buf, sizeof buf, _(": %d"), - PPC64_LOCAL_ENTRY_OFFSET (other)); + if (other >= 2) + other = ppc64_decode_local_entry (other); + snprintf (buf, sizeof buf, _(": %d"), other); return buf; } return NULL; @@ -11057,6 +11286,12 @@ get_symbol_other (Filedata * filedata, unsigned int other) switch (filedata->file_header.e_machine) { + case EM_ALPHA: + result = get_alpha_symbol_other (other); + break; + case EM_AARCH64: + result = get_aarch64_symbol_other (other); + break; case EM_MIPS: result = get_mips_symbol_other (other); break; @@ -11243,6 +11478,7 @@ get_symbol_version_string (Filedata * filedata, unsigned char data[2]; unsigned short vers_data; unsigned long offset; + unsigned short max_vd_ndx; if (!is_dynsym || version_info[DT_VERSIONTAGIDX (DT_VERSYM)] == 0) @@ -11257,9 +11493,11 @@ get_symbol_version_string (Filedata * filedata, vers_data = byte_get (data, 2); - if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data <= 1) + if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data == 0) return NULL; + max_vd_ndx = 0; + /* Usually we'd only see verdef for defined symbols, and verneed for undefined symbols. However, symbols defined by the linker in .dynbss for variables copied from a shared library in order to @@ -11292,20 +11530,28 @@ get_symbol_version_string (Filedata * filedata, ivd.vd_ndx = 0; ivd.vd_aux = 0; ivd.vd_next = 0; + ivd.vd_flags = 0; } else { ivd.vd_ndx = BYTE_GET (evd.vd_ndx); ivd.vd_aux = BYTE_GET (evd.vd_aux); ivd.vd_next = BYTE_GET (evd.vd_next); + ivd.vd_flags = BYTE_GET (evd.vd_flags); } + if ((ivd.vd_ndx & VERSYM_VERSION) > max_vd_ndx) + max_vd_ndx = ivd.vd_ndx & VERSYM_VERSION; + off += ivd.vd_next; } while (ivd.vd_ndx != (vers_data & VERSYM_VERSION) && ivd.vd_next != 0); if (ivd.vd_ndx == (vers_data & VERSYM_VERSION)) { + if (ivd.vd_ndx == 1 && ivd.vd_flags == VER_FLG_BASE) + return NULL; + off -= ivd.vd_next; off += ivd.vd_aux; @@ -11388,6 +11634,9 @@ get_symbol_version_string (Filedata * filedata, return (ivna.vna_name < strtab_size ? strtab + ivna.vna_name : _("")); } + else if ((max_vd_ndx || (vers_data & VERSYM_VERSION) != 1) + && (vers_data & VERSYM_VERSION) > max_vd_ndx) + return _(""); } return NULL; } @@ -12247,6 +12496,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) case EM_AARCH64: return (reloc_type == 258 || reloc_type == 1); /* R_AARCH64_ABS32 || R_AARCH64_P32_ABS32 */ + case EM_BPF: + return reloc_type == 11; /* R_BPF_DATA_32 */ case EM_ADAPTEVA_EPIPHANY: return reloc_type == 3; case EM_ALPHA: @@ -12269,6 +12520,8 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) return reloc_type == 3; /* R_CR16_NUM32. */ case EM_CRX: return reloc_type == 15; /* R_CRX_NUM32. */ + case EM_CSKY: + return reloc_type == 1; /* R_CKCORE_ADDR32. */ case EM_CYGNUS_FRV: return reloc_type == 1; case EM_CYGNUS_D10V: @@ -12308,6 +12561,9 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) case EM_68HC11: case EM_68HC12: return reloc_type == 6; /* R_M68HC11_32. */ + case EM_S12Z: + return reloc_type == 7 || /* R_S12Z_EXT32 */ + reloc_type == 6; /* R_S12Z_CW32. */ case EM_MCORE: return reloc_type == 1; /* R_MCORE_ADDR32. */ case EM_CYGNUS_MEP: @@ -12342,7 +12598,7 @@ is_32bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) case EM_OR1K: return reloc_type == 1; /* R_OR1K_32. */ case EM_PARISC: - return (reloc_type == 1 /* R_PARISC_DIR32. */ + return (reloc_type == 1 /* R_PARISC_DIR32. */ || reloc_type == 2 /* R_PARISC_DIR21L. */ || reloc_type == 41); /* R_PARISC_SECREL32. */ case EM_PJ: @@ -12459,6 +12715,8 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type) return reloc_type == 26; /* R_PPC_REL32. */ case EM_PPC64: return reloc_type == 26; /* R_PPC64_REL32. */ + case EM_RISCV: + return reloc_type == 57; /* R_RISCV_32_PCREL. */ case EM_S390_OLD: case EM_S390: return reloc_type == 5; /* R_390_PC32. */ @@ -12480,6 +12738,8 @@ is_32bit_pcrel_reloc (Filedata * filedata, unsigned int reloc_type) case EM_L1OM: case EM_K1OM: return reloc_type == 2; /* R_X86_64_PC32. */ + case EM_VAX: + return reloc_type == 4; /* R_VAX_PCREL32. */ case EM_XTENSA_OLD: case EM_XTENSA: return reloc_type == 14; /* R_XTENSA_32_PCREL. */ @@ -12643,6 +12903,8 @@ is_16bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) return reloc_type == 9; /* R_NIOS_16. */ case EM_OR1K: return reloc_type == 2; /* R_OR1K_16. */ + case EM_RISCV: + return reloc_type == 55; /* R_RISCV_SET16. */ case EM_TI_PRU: return reloc_type == 8; /* R_PRU_BFD_RELOC_16. */ case EM_TI_C6000: @@ -12659,6 +12921,36 @@ is_16bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) } } +/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is + a 8-bit absolute RELA relocation used in DWARF debug sections. */ + +static bfd_boolean +is_8bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) +{ + switch (filedata->file_header.e_machine) + { + case EM_RISCV: + return reloc_type == 54; /* R_RISCV_SET8. */ + default: + return FALSE; + } +} + +/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is + a 6-bit absolute RELA relocation used in DWARF debug sections. */ + +static bfd_boolean +is_6bit_abs_reloc (Filedata * filedata, unsigned int reloc_type) +{ + switch (filedata->file_header.e_machine) + { + case EM_RISCV: + return reloc_type == 53; /* R_RISCV_SET6. */ + default: + return FALSE; + } +} + /* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is a 32-bit inplace add RELA relocation used in DWARF debug sections. */ @@ -12787,6 +13079,21 @@ is_8bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type) } } +/* Like is_32bit_abs_reloc except that it returns TRUE iff RELOC_TYPE is + a 6-bit inplace sub RELA relocation used in DWARF debug sections. */ + +static bfd_boolean +is_6bit_inplace_sub_reloc (Filedata * filedata, unsigned int reloc_type) +{ + switch (filedata->file_header.e_machine) + { + case EM_RISCV: + return reloc_type == 52; /* R_RISCV_SUB6. */ + default: + return FALSE; + } +} + /* Returns TRUE iff RELOC_TYPE is a NONE relocation used for discarded relocation entries (possibly formerly used for SHT_GROUP sections). */ @@ -12906,7 +13213,6 @@ apply_relocations (Filedata * filedata, { Elf_Internal_Shdr * relsec; unsigned char * end = start + size; - bfd_boolean res = TRUE; if (relocs_return != NULL) { @@ -12990,6 +13296,9 @@ apply_relocations (Filedata * filedata, reloc_size = 3; else if (is_16bit_abs_reloc (filedata, reloc_type)) reloc_size = 2; + else if (is_8bit_abs_reloc (filedata, reloc_type) + || is_6bit_abs_reloc (filedata, reloc_type)) + reloc_size = 1; else if ((reloc_subtract = is_32bit_inplace_sub_reloc (filedata, reloc_type)) || is_32bit_inplace_add_reloc (filedata, reloc_type)) @@ -13018,6 +13327,12 @@ apply_relocations (Filedata * filedata, reloc_size = 1; reloc_inplace = TRUE; } + else if ((reloc_subtract = is_6bit_inplace_sub_reloc (filedata, + reloc_type))) + { + reloc_size = 1; + reloc_inplace = TRUE; + } else { static unsigned int prev_reloc = 0; @@ -13026,7 +13341,6 @@ apply_relocations (Filedata * filedata, warn (_("unable to apply unsupported reloc type %d to section %s\n"), reloc_type, printable_section_name (filedata, section)); prev_reloc = reloc_type; - res = FALSE; continue; } @@ -13036,7 +13350,6 @@ apply_relocations (Filedata * filedata, warn (_("skipping invalid relocation offset 0x%lx in section %s\n"), (unsigned long) rp->r_offset, printable_section_name (filedata, section)); - res = FALSE; continue; } @@ -13045,7 +13358,6 @@ apply_relocations (Filedata * filedata, { warn (_("skipping invalid relocation symbol index 0x%lx in section %s\n"), sym_index, printable_section_name (filedata, section)); - res = FALSE; continue; } sym = symtab + sym_index; @@ -13071,7 +13383,6 @@ apply_relocations (Filedata * filedata, get_symbol_type (filedata, ELF_ST_TYPE (sym->st_info)), printable_section_name (filedata, relsec), (long int)(rp - relocs)); - res = FALSE; continue; } @@ -13090,7 +13401,12 @@ apply_relocations (Filedata * filedata, || filedata->file_header.e_machine == EM_CYGNUS_D30V) && reloc_type == 12) || reloc_inplace) - addend += byte_get (rloc, reloc_size); + { + if (is_6bit_inplace_sub_reloc (filedata, reloc_type)) + addend += byte_get (rloc, reloc_size) & 0x3f; + else + addend += byte_get (rloc, reloc_size); + } if (is_32bit_pcrel_reloc (filedata, reloc_type) || is_64bit_pcrel_reloc (filedata, reloc_type)) @@ -13101,6 +13417,16 @@ apply_relocations (Filedata * filedata, byte_put (rloc, (addend + sym->st_value) - rp->r_offset, reloc_size); } + else if (is_6bit_abs_reloc (filedata, reloc_type) + || is_6bit_inplace_sub_reloc (filedata, reloc_type)) + { + if (reloc_subtract) + addend -= sym->st_value; + else + addend += sym->st_value; + addend = (addend & 0x3f) | (byte_get (rloc, reloc_size) & 0xc0); + byte_put (rloc, addend, reloc_size); + } else if (reloc_subtract) byte_put (rloc, addend - sym->st_value, reloc_size); else @@ -13123,7 +13449,7 @@ apply_relocations (Filedata * filedata, break; } - return res; + return TRUE; } #ifdef SUPPORT_DISASSEMBLY @@ -13249,12 +13575,6 @@ dump_section_as_strings (Elf_Internal_Shdr * section, Filedata * filedata) printable_section_name (filedata, section), chdr.ch_type); return FALSE; } - else if (chdr.ch_addralign != section->sh_addralign) - { - warn (_("compressed section '%s' is corrupted\n"), - printable_section_name (filedata, section)); - return FALSE; - } uncompressed_size = chdr.ch_size; start += compression_header_size; new_size -= compression_header_size; @@ -13396,12 +13716,6 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, printable_section_name (filedata, section), chdr.ch_type); return FALSE; } - else if (chdr.ch_addralign != section->sh_addralign) - { - warn (_("compressed section '%s' is corrupted\n"), - printable_section_name (filedata, section)); - return FALSE; - } uncompressed_size = chdr.ch_size; start += compression_header_size; new_size -= compression_header_size; @@ -13517,18 +13831,172 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, return TRUE; } +static ctf_sect_t * +shdr_to_ctf_sect (ctf_sect_t *buf, Elf_Internal_Shdr *shdr, Filedata *filedata) +{ + buf->cts_name = SECTION_NAME (shdr); + buf->cts_size = shdr->sh_size; + buf->cts_entsize = shdr->sh_entsize; + + return buf; +} + +/* Formatting callback function passed to ctf_dump. Returns either the pointer + it is passed, or a pointer to newly-allocated storage, in which case + dump_ctf() will free it when it no longer needs it. */ + +static char *dump_ctf_indent_lines (ctf_sect_names_t sect ATTRIBUTE_UNUSED, + char *s, void *arg) +{ + const char *blanks = arg; + char *new_s; + + if (asprintf (&new_s, "%s%s", blanks, s) < 0) + return s; + return new_s; +} + static bfd_boolean -load_specific_debug_section (enum dwarf_section_display_enum debug, - const Elf_Internal_Shdr * sec, - void * data) +dump_section_as_ctf (Elf_Internal_Shdr * section, Filedata * filedata) { - struct dwarf_section * section = &debug_displays [debug].section; - char buf [64]; - Filedata * filedata = (Filedata *) data; - - if (section->start != NULL) + Elf_Internal_Shdr * parent_sec = NULL; + Elf_Internal_Shdr * symtab_sec = NULL; + Elf_Internal_Shdr * strtab_sec = NULL; + void * data = NULL; + void * symdata = NULL; + void * strdata = NULL; + void * parentdata = NULL; + ctf_sect_t ctfsect, symsect, strsect, parentsect; + ctf_sect_t * symsectp = NULL; + ctf_sect_t * strsectp = NULL; + ctf_file_t * ctf = NULL; + ctf_file_t * parent = NULL; + + const char *things[] = {"Labels", "Data objects", "Function objects", + "Variables", "Types", "Strings", ""}; + const char **thing; + int err; + bfd_boolean ret = FALSE; + size_t i; + + shdr_to_ctf_sect (&ctfsect, section, filedata); + data = get_section_contents (section, filedata); + ctfsect.cts_data = data; + + if (dump_ctf_symtab_name) { - /* If it is already loaded, do nothing. */ + if ((symtab_sec = find_section (filedata, dump_ctf_symtab_name)) == NULL) + { + error (_("No symbol section named %s\n"), dump_ctf_symtab_name); + goto fail; + } + if ((symdata = (void *) get_data (NULL, filedata, + symtab_sec->sh_offset, 1, + symtab_sec->sh_size, + _("symbols"))) == NULL) + goto fail; + symsectp = shdr_to_ctf_sect (&symsect, symtab_sec, filedata); + symsect.cts_data = symdata; + } + if (dump_ctf_strtab_name) + { + if ((strtab_sec = find_section (filedata, dump_ctf_strtab_name)) == NULL) + { + error (_("No string table section named %s\n"), + dump_ctf_strtab_name); + goto fail; + } + if ((strdata = (void *) get_data (NULL, filedata, + strtab_sec->sh_offset, 1, + strtab_sec->sh_size, + _("strings"))) == NULL) + goto fail; + strsectp = shdr_to_ctf_sect (&strsect, strtab_sec, filedata); + strsect.cts_data = strdata; + } + if (dump_ctf_parent_name) + { + if ((parent_sec = find_section (filedata, dump_ctf_parent_name)) == NULL) + { + error (_("No CTF parent section named %s\n"), dump_ctf_parent_name); + goto fail; + } + if ((parentdata = (void *) get_data (NULL, filedata, + parent_sec->sh_offset, 1, + parent_sec->sh_size, + _("CTF parent"))) == NULL) + goto fail; + shdr_to_ctf_sect (&parentsect, parent_sec, filedata); + parentsect.cts_data = parentdata; + } + + /* Load the CTF file and dump it. */ + + if ((ctf = ctf_bufopen (&ctfsect, symsectp, strsectp, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; + } + + if (parentdata) + { + if ((parent = ctf_bufopen (&parentsect, symsectp, strsectp, &err)) == NULL) + { + error (_("CTF open failure: %s\n"), ctf_errmsg (err)); + goto fail; + } + + ctf_import (ctf, parent); + } + + ret = TRUE; + + printf (_("\nDump of CTF section '%s':\n"), + printable_section_name (filedata, section)); + + for (i = 1, thing = things; *thing[0]; thing++, i++) + { + ctf_dump_state_t *s = NULL; + char *item; + + printf ("\n %s:\n", *thing); + while ((item = ctf_dump (ctf, &s, i, dump_ctf_indent_lines, + (void *) " ")) != NULL) + { + printf ("%s\n", item); + free (item); + } + + if (ctf_errno (ctf)) + { + error (_("Iteration failed: %s, %s\n"), *thing, + ctf_errmsg (ctf_errno (ctf))); + ret = FALSE; + } + } + + fail: + ctf_file_close (ctf); + ctf_file_close (parent); + free (parentdata); + free (data); + free (symdata); + free (strdata); + return ret; +} + +static bfd_boolean +load_specific_debug_section (enum dwarf_section_display_enum debug, + const Elf_Internal_Shdr * sec, + void * data) +{ + struct dwarf_section * section = &debug_displays [debug].section; + char buf [64]; + Filedata * filedata = (Filedata *) data; + + if (section->start != NULL) + { + /* If it is already loaded, do nothing. */ if (streq (section->filename, filedata->file_name)) return TRUE; free (section->start); @@ -13571,12 +14039,6 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, section->name, chdr.ch_type); return FALSE; } - else if (chdr.ch_addralign != sec->sh_addralign) - { - warn (_("compressed section '%s' is corrupted\n"), - section->name); - return FALSE; - } uncompressed_size = chdr.ch_size; start += compression_header_size; size -= compression_header_size; @@ -13860,6 +14322,12 @@ process_section_contents (Filedata * filedata) if (! display_debug_section (i, section, filedata)) res = FALSE; } + + if (dump & CTF_DUMP) + { + if (! dump_section_as_ctf (section, filedata)) + res = FALSE; + } } /* Check to see if the user requested a @@ -14126,6 +14594,12 @@ display_arc_attribute (unsigned char * p, printf (" Tag_ARC_ISA_mpy_option: %d\n", val); break; + case Tag_ARC_ATR_version: + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ARC_ATR_version: %d\n", val); + break; + default: return display_tag_value (tag & 1, p, end); } @@ -14146,7 +14620,7 @@ typedef struct static const char * arm_attr_tag_CPU_arch[] = {"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2", "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8", "v8-R", "v8-M.baseline", - "v8-M.mainline"}; + "v8-M.mainline", "", "", "", "v8.1-M.mainline"}; static const char * arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"}; static const char * arm_attr_tag_THUMB_ISA_use[] = {"No", "Thumb-1", "Thumb-2", "Yes"}; @@ -14210,6 +14684,9 @@ static const char * arm_attr_tag_Virtualization_use[] = static const char * arm_attr_tag_MPextension_use_legacy[] = {"Not Allowed", "Allowed"}; +static const char * arm_attr_tag_MVE_arch[] = + {"No MVE", "MVE Integer only", "MVE Integer and FP"}; + #define LOOKUP(id, name) \ {id, #name, 0x80 | ARRAY_SIZE(arm_attr_tag_##name), arm_attr_tag_##name} static arm_attr_public_tag arm_attr_public_tags[] = @@ -14249,6 +14726,7 @@ static arm_attr_public_tag arm_attr_public_tags[] = LOOKUP(42, MPextension_use), LOOKUP(44, DIV_use), LOOKUP(46, DSP_extension), + LOOKUP(48, MVE_arch), {64, "nodefaults", 0, NULL}, {65, "also_compatible_with", 0, NULL}, LOOKUP(66, T2EE_use), @@ -15068,7 +15546,7 @@ display_raw_attribute (unsigned char * p, unsigned char const * const end) unsigned long addr = 0; size_t bytes = end - p; - assert (end > p); + assert (end >= p); while (bytes) { int j; @@ -15193,6 +15671,88 @@ display_msp430x_attribute (unsigned char * p, return p; } +struct riscv_attr_tag_t { + const char *name; + int tag; +}; + +static struct riscv_attr_tag_t riscv_attr_tag[] = +{ +#define T(tag) {"Tag_RISCV_" #tag, Tag_RISCV_##tag} + T(arch), + T(priv_spec), + T(priv_spec_minor), + T(priv_spec_revision), + T(unaligned_access), + T(stack_align), +#undef T +}; + +static unsigned char * +display_riscv_attribute (unsigned char *p, + const unsigned char * const end) +{ + unsigned int len; + int val; + int tag; + struct riscv_attr_tag_t *attr = NULL; + unsigned i; + + tag = read_uleb128 (p, &len, end); + p += len; + + /* Find the name of attribute. */ + for (i = 0; i < ARRAY_SIZE (riscv_attr_tag); i++) + { + if (riscv_attr_tag[i].tag == tag) + { + attr = &riscv_attr_tag[i]; + break; + } + } + + if (attr) + printf (" %s: ", attr->name); + else + return display_tag_value (tag, p, end); + + switch (tag) + { + case Tag_RISCV_priv_spec: + case Tag_RISCV_priv_spec_minor: + case Tag_RISCV_priv_spec_revision: + val = read_uleb128 (p, &len, end); + p += len; + printf (_("%d\n"), val); + break; + case Tag_RISCV_unaligned_access: + val = read_uleb128 (p, &len, end); + p += len; + switch (val) + { + case 0: + printf (_("No unaligned access\n")); + break; + case 1: + printf (_("Unaligned access\n")); + break; + } + break; + case Tag_RISCV_stack_align: + val = read_uleb128 (p, &len, end); + p += len; + printf (_("%d-bytes\n"), val); + break; + case Tag_RISCV_arch: + p = display_tag_value (-1, p, end); + break; + default: + return display_tag_value (tag, p, end); + } + + return p; +} + static bfd_boolean process_attributes (Filedata * filedata, const char * public_name, @@ -15493,6 +16053,18 @@ print_mips_ases (unsigned int mask) fputs ("\n\tXPA ASE", stdout); if (mask & AFL_ASE_MIPS16E2) fputs ("\n\tMIPS16e2 ASE", stdout); + if (mask & AFL_ASE_CRC) + fputs ("\n\tCRC ASE", stdout); + if (mask & AFL_ASE_GINV) + fputs ("\n\tGINV ASE", stdout); + if (mask & AFL_ASE_LOONGSON_MMI) + fputs ("\n\tLoongson MMI ASE", stdout); + if (mask & AFL_ASE_LOONGSON_CAM) + fputs ("\n\tLoongson CAM ASE", stdout); + if (mask & AFL_ASE_LOONGSON_EXT) + fputs ("\n\tLoongson EXT ASE", stdout); + if (mask & AFL_ASE_LOONGSON_EXT2) + fputs ("\n\tLoongson EXT2 ASE", stdout); if (mask == 0) fprintf (stdout, "\n\t%s", _("None")); else if ((mask & ~AFL_ASE_MASK) != 0) @@ -15519,9 +16091,6 @@ print_mips_isa_ext (unsigned int isa_ext) case AFL_EXT_OCTEONP: fputs ("Cavium Networks OcteonP", stdout); break; - case AFL_EXT_LOONGSON_3A: - fputs ("Loongson 3A", stdout); - break; case AFL_EXT_OCTEON: fputs ("Cavium Networks Octeon", stdout); break; @@ -15905,6 +16474,12 @@ process_mips_specific (Filedata * filedata) error (_("No MIPS_OPTIONS header found\n")); return FALSE; } + /* PR 24243 */ + if (sect->sh_size < sizeof (* eopt)) + { + error (_("The MIPS options section is too small.\n")); + return FALSE; + } eopt = (Elf_External_Options *) get_data (NULL, filedata, options_offset, 1, sect->sh_size, _("options")); @@ -16589,7 +17164,7 @@ get_note_type (Filedata * filedata, unsigned e_type) case NT_PPC_TM_CVMX: return _("NT_PPC_TM_CVMX (ppc checkpointed Altivec registers)"); case NT_PPC_TM_CVSX: - return _("NT_PPC_TM_VSX (ppc checkpointed VSX registers)"); + return _("NT_PPC_TM_CVSX (ppc checkpointed VSX registers)"); case NT_PPC_TM_SPR: return _("NT_PPC_TM_SPR (ppc TM special purpose registers)"); case NT_PPC_TM_CTAR: @@ -16797,9 +17372,88 @@ get_gnu_elf_note_type (unsigned e_type) } } +static void +decode_x86_compat_isa (unsigned int bitmask) +{ + while (bitmask) + { + unsigned int bit = bitmask & (- bitmask); + + bitmask &= ~ bit; + switch (bit) + { + case GNU_PROPERTY_X86_COMPAT_ISA_1_486: + printf ("i486"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_586: + printf ("586"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_686: + printf ("686"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE: + printf ("SSE"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE2: + printf ("SSE2"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE3: + printf ("SSE3"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_SSSE3: + printf ("SSSE3"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE4_1: + printf ("SSE4_1"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_SSE4_2: + printf ("SSE4_2"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX: + printf ("AVX"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX2: + printf ("AVX2"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512F: + printf ("AVX512F"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512CD: + printf ("AVX512CD"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512ER: + printf ("AVX512ER"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512PF: + printf ("AVX512PF"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512VL: + printf ("AVX512VL"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512DQ: + printf ("AVX512DQ"); + break; + case GNU_PROPERTY_X86_COMPAT_ISA_1_AVX512BW: + printf ("AVX512BW"); + break; + default: + printf (_(""), bit); + break; + } + if (bitmask) + printf (", "); + } +} + static void decode_x86_isa (unsigned int bitmask) { + if (!bitmask) + { + printf (_("")); + return; + } + while (bitmask) { unsigned int bit = bitmask & (- bitmask); @@ -16807,25 +17461,84 @@ decode_x86_isa (unsigned int bitmask) bitmask &= ~ bit; switch (bit) { - case GNU_PROPERTY_X86_ISA_1_486: printf ("i486"); break; - case GNU_PROPERTY_X86_ISA_1_586: printf ("586"); break; - case GNU_PROPERTY_X86_ISA_1_686: printf ("686"); break; - case GNU_PROPERTY_X86_ISA_1_SSE: printf ("SSE"); break; - case GNU_PROPERTY_X86_ISA_1_SSE2: printf ("SSE2"); break; - case GNU_PROPERTY_X86_ISA_1_SSE3: printf ("SSE3"); break; - case GNU_PROPERTY_X86_ISA_1_SSSE3: printf ("SSSE3"); break; - case GNU_PROPERTY_X86_ISA_1_SSE4_1: printf ("SSE4_1"); break; - case GNU_PROPERTY_X86_ISA_1_SSE4_2: printf ("SSE4_2"); break; - case GNU_PROPERTY_X86_ISA_1_AVX: printf ("AVX"); break; - case GNU_PROPERTY_X86_ISA_1_AVX2: printf ("AVX2"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512F: printf ("AVX512F"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512CD: printf ("AVX512CD"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512ER: printf ("AVX512ER"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512PF: printf ("AVX512PF"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512VL: printf ("AVX512VL"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512DQ: printf ("AVX512DQ"); break; - case GNU_PROPERTY_X86_ISA_1_AVX512BW: printf ("AVX512BW"); break; - default: printf (_(""), bit); break; + case GNU_PROPERTY_X86_ISA_1_CMOV: + printf ("CMOV"); + break; + case GNU_PROPERTY_X86_ISA_1_SSE: + printf ("SSE"); + break; + case GNU_PROPERTY_X86_ISA_1_SSE2: + printf ("SSE2"); + break; + case GNU_PROPERTY_X86_ISA_1_SSE3: + printf ("SSE3"); + break; + case GNU_PROPERTY_X86_ISA_1_SSSE3: + printf ("SSSE3"); + break; + case GNU_PROPERTY_X86_ISA_1_SSE4_1: + printf ("SSE4_1"); + break; + case GNU_PROPERTY_X86_ISA_1_SSE4_2: + printf ("SSE4_2"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX: + printf ("AVX"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX2: + printf ("AVX2"); + break; + case GNU_PROPERTY_X86_ISA_1_FMA: + printf ("FMA"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512F: + printf ("AVX512F"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512CD: + printf ("AVX512CD"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512ER: + printf ("AVX512ER"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512PF: + printf ("AVX512PF"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512VL: + printf ("AVX512VL"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512DQ: + printf ("AVX512DQ"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512BW: + printf ("AVX512BW"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS: + printf ("AVX512_4FMAPS"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW: + printf ("AVX512_4VNNIW"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_BITALG: + printf ("AVX512_BITALG"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_IFMA: + printf ("AVX512_IFMA"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_VBMI: + printf ("AVX512_VBMI"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2: + printf ("AVX512_VBMI2"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_VNNI: + printf ("AVX512_VNNI"); + break; + case GNU_PROPERTY_X86_ISA_1_AVX512_BF16: + printf ("AVX512_BF16"); + break; + default: + printf (_(""), bit); + break; } if (bitmask) printf (", "); @@ -16833,8 +17546,14 @@ decode_x86_isa (unsigned int bitmask) } static void -decode_x86_feature (unsigned int type, unsigned int bitmask) +decode_x86_feature_1 (unsigned int bitmask) { + if (!bitmask) + { + printf (_("")); + return; + } + while (bitmask) { unsigned int bit = bitmask & (- bitmask); @@ -16843,27 +17562,93 @@ decode_x86_feature (unsigned int type, unsigned int bitmask) switch (bit) { case GNU_PROPERTY_X86_FEATURE_1_IBT: - switch (type) - { - case GNU_PROPERTY_X86_FEATURE_1_AND: - printf ("IBT"); - break; - default: - /* This should never happen. */ - abort (); - } + printf ("IBT"); break; case GNU_PROPERTY_X86_FEATURE_1_SHSTK: - switch (type) - { - case GNU_PROPERTY_X86_FEATURE_1_AND: - printf ("SHSTK"); - break; - default: - /* This should never happen. */ - abort (); - } + printf ("SHSTK"); + break; + default: + printf (_(""), bit); + break; + } + if (bitmask) + printf (", "); + } +} + +static void +decode_x86_feature_2 (unsigned int bitmask) +{ + if (!bitmask) + { + printf (_("")); + return; + } + + while (bitmask) + { + unsigned int bit = bitmask & (- bitmask); + + bitmask &= ~ bit; + switch (bit) + { + case GNU_PROPERTY_X86_FEATURE_2_X86: + printf ("x86"); + break; + case GNU_PROPERTY_X86_FEATURE_2_X87: + printf ("x87"); + break; + case GNU_PROPERTY_X86_FEATURE_2_MMX: + printf ("MMX"); + break; + case GNU_PROPERTY_X86_FEATURE_2_XMM: + printf ("XMM"); + break; + case GNU_PROPERTY_X86_FEATURE_2_YMM: + printf ("YMM"); + break; + case GNU_PROPERTY_X86_FEATURE_2_ZMM: + printf ("ZMM"); + break; + case GNU_PROPERTY_X86_FEATURE_2_FXSR: + printf ("FXSR"); + break; + case GNU_PROPERTY_X86_FEATURE_2_XSAVE: + printf ("XSAVE"); + break; + case GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT: + printf ("XSAVEOPT"); + break; + case GNU_PROPERTY_X86_FEATURE_2_XSAVEC: + printf ("XSAVEC"); + break; + default: + printf (_(""), bit); + break; + } + if (bitmask) + printf (", "); + } +} + +static void +decode_aarch64_feature_1_and (unsigned int bitmask) +{ + while (bitmask) + { + unsigned int bit = bitmask & (- bitmask); + + bitmask &= ~ bit; + switch (bit) + { + case GNU_PROPERTY_AARCH64_FEATURE_1_BTI: + printf ("BTI"); + break; + + case GNU_PROPERTY_AARCH64_FEATURE_1_PAC: + printf ("PAC"); break; + default: printf (_(""), bit); break; @@ -16918,36 +17703,107 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote) || filedata->file_header.e_machine == EM_IAMCU || filedata->file_header.e_machine == EM_386) { + unsigned int bitmask; + + if (datasz == 4) + bitmask = byte_get (ptr, 4); + else + bitmask = 0; + switch (type) { case GNU_PROPERTY_X86_ISA_1_USED: - printf ("x86 ISA used: "); if (datasz != 4) - printf (_(" "), datasz); + printf (_("x86 ISA used: "), + datasz); else - decode_x86_isa (byte_get (ptr, 4)); + { + printf ("x86 ISA used: "); + decode_x86_isa (bitmask); + } goto next; case GNU_PROPERTY_X86_ISA_1_NEEDED: - printf ("x86 ISA needed: "); if (datasz != 4) - printf (_(" "), datasz); + printf (_("x86 ISA needed: "), + datasz); else - decode_x86_isa (byte_get (ptr, 4)); + { + printf ("x86 ISA needed: "); + decode_x86_isa (bitmask); + } goto next; case GNU_PROPERTY_X86_FEATURE_1_AND: - printf ("x86 feature: "); if (datasz != 4) - printf (_(" "), datasz); + printf (_("x86 feature: "), + datasz); + else + { + printf ("x86 feature: "); + decode_x86_feature_1 (bitmask); + } + goto next; + + case GNU_PROPERTY_X86_FEATURE_2_USED: + if (datasz != 4) + printf (_("x86 feature used: "), + datasz); + else + { + printf ("x86 feature used: "); + decode_x86_feature_2 (bitmask); + } + goto next; + + case GNU_PROPERTY_X86_FEATURE_2_NEEDED: + if (datasz != 4) + printf (_("x86 feature needed: "), datasz); else - decode_x86_feature (type, byte_get (ptr, 4)); + { + printf ("x86 feature needed: "); + decode_x86_feature_2 (bitmask); + } + goto next; + + case GNU_PROPERTY_X86_COMPAT_ISA_1_USED: + if (datasz != 4) + printf (_("x86 ISA used: "), + datasz); + else + { + printf ("x86 ISA used: "); + decode_x86_compat_isa (bitmask); + } + goto next; + + case GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED: + if (datasz != 4) + printf (_("x86 ISA needed: "), + datasz); + else + { + printf ("x86 ISA needed: "); + decode_x86_compat_isa (bitmask); + } goto next; default: break; } } + else if (filedata->file_header.e_machine == EM_AARCH64) + { + if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) + { + printf ("AArch64 feature: "); + if (datasz != 4) + printf (_(" "), datasz); + else + decode_aarch64_feature_1_and (byte_get (ptr, 4)); + goto next; + } + } } else { @@ -17099,7 +17955,7 @@ print_gnu_note (Filedata * filedata, Elf_Internal_Note *pnote) case NT_GNU_PROPERTY_TYPE_0: print_gnu_property_note (filedata, pnote); break; - + default: /* Handle unrecognised types. An error message should have already been created by get_gnu_elf_note_type(), so all that we need to do is to @@ -17219,10 +18075,23 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote) return TRUE; case NT_NETBSD_MARCH: - printf (" NetBSD\t0x%08lx\tMARCH <%s>\n", pnote->descsz, + printf (" NetBSD\t\t0x%08lx\tMARCH <%s>\n", pnote->descsz, pnote->descdata); return TRUE; +#ifdef NT_NETBSD_PAX + case NT_NETBSD_PAX: + version = byte_get ((unsigned char *) pnote->descdata, sizeof (version)); + printf (" NetBSD\t\t0x%08lx\tPaX <%s%s%s%s%s%s>\n", pnote->descsz, + ((version & NT_NETBSD_PAX_MPROTECT) ? "+mprotect" : ""), + ((version & NT_NETBSD_PAX_NOMPROTECT) ? "-mprotect" : ""), + ((version & NT_NETBSD_PAX_GUARD) ? "+guard" : ""), + ((version & NT_NETBSD_PAX_NOGUARD) ? "-guard" : ""), + ((version & NT_NETBSD_PAX_ASLR) ? "+ASLR" : ""), + ((version & NT_NETBSD_PAX_NOASLR) ? "-ASLR" : "")); + return TRUE; +#endif + default: printf (" NetBSD\t0x%08lx\tUnknown note type: (0x%08lx)\n", pnote->descsz, pnote->type); @@ -17266,18 +18135,29 @@ get_netbsd_elfcore_note_type (Filedata * filedata, unsigned e_type) { static char buff[64]; - if (e_type == NT_NETBSDCORE_PROCINFO) - return _("NetBSD procinfo structure"); + switch (e_type) + { + case NT_NETBSDCORE_PROCINFO: + /* NetBSD core "procinfo" structure. */ + return _("NetBSD procinfo structure"); - /* As of Jan 2002 there are no other machine-independent notes - defined for NetBSD core files. If the note type is less - than the start of the machine-dependent note types, we don't - understand it. */ +#ifdef NT_NETBSDCORE_AUXV + case NT_NETBSDCORE_AUXV: + return _("NetBSD ELF auxiliary vector data"); +#endif - if (e_type < NT_NETBSDCORE_FIRSTMACH) - { - snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); - return buff; + default: + /* As of Jan 2002 there are no other machine-independent notes + defined for NetBSD core files. If the note type is less + than the start of the machine-dependent note types, we don't + understand it. */ + + if (e_type < NT_NETBSDCORE_FIRSTMACH) + { + snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); + return buff; + } + break; } switch (filedata->file_header.e_machine) @@ -17301,6 +18181,23 @@ get_netbsd_elfcore_note_type (Filedata * filedata, unsigned e_type) } break; + /* On SuperH, PT_GETREGS == mach+3 and PT_GETFPREGS == mach+5. + There's also old PT___GETREGS40 == mach + 1 for old reg + structure which lacks GBR. */ + case EM_SH: + switch (e_type) + { + case NT_NETBSDCORE_FIRSTMACH + 1: + return _("PT___GETREGS40 (old reg structure)"); + case NT_NETBSDCORE_FIRSTMACH + 3: + return _("PT_GETREGS (reg structure)"); + case NT_NETBSDCORE_FIRSTMACH + 5: + return _("PT_GETFPREGS (fpreg structure)"); + default: + break; + } + break; + /* On all other arch's, PT_GETREGS == mach+1 and PT_GETFPREGS == mach+3. */ default: @@ -17341,25 +18238,60 @@ get_stapsdt_note_type (unsigned e_type) static bfd_boolean print_stapsdt_note (Elf_Internal_Note *pnote) { - int addr_size = is_32bit_elf ? 4 : 8; + size_t len, maxlen; + unsigned long addr_size = is_32bit_elf ? 4 : 8; char *data = pnote->descdata; char *data_end = pnote->descdata + pnote->descsz; bfd_vma pc, base_addr, semaphore; char *provider, *probe, *arg_fmt; + if (pnote->descsz < (addr_size * 3)) + goto stapdt_note_too_small; + pc = byte_get ((unsigned char *) data, addr_size); data += addr_size; + base_addr = byte_get ((unsigned char *) data, addr_size); data += addr_size; + semaphore = byte_get ((unsigned char *) data, addr_size); data += addr_size; - provider = data; - data += strlen (data) + 1; - probe = data; - data += strlen (data) + 1; - arg_fmt = data; - data += strlen (data) + 1; + if (data >= data_end) + goto stapdt_note_too_small; + maxlen = data_end - data; + len = strnlen (data, maxlen); + if (len < maxlen) + { + provider = data; + data += len + 1; + } + else + goto stapdt_note_too_small; + + if (data >= data_end) + goto stapdt_note_too_small; + maxlen = data_end - data; + len = strnlen (data, maxlen); + if (len < maxlen) + { + probe = data; + data += len + 1; + } + else + goto stapdt_note_too_small; + + if (data >= data_end) + goto stapdt_note_too_small; + maxlen = data_end - data; + len = strnlen (data, maxlen); + if (len < maxlen) + { + arg_fmt = data; + data += len + 1; + } + else + goto stapdt_note_too_small; printf (_(" Provider: %s\n"), provider); printf (_(" Name: %s\n"), probe); @@ -17373,6 +18305,11 @@ print_stapsdt_note (Elf_Internal_Note *pnote) printf (_(" Arguments: %s\n"), arg_fmt); return data == data_end; + + stapdt_note_too_small: + printf (_(" \n")); + error (_("corrupt stapdt note - the data size is too small\n")); + return FALSE; } static const char * @@ -17419,42 +18356,77 @@ get_ia64_vms_note_type (unsigned e_type) static bfd_boolean print_ia64_vms_note (Elf_Internal_Note * pnote) { + int maxlen = pnote->descsz; + + if (maxlen < 2 || (unsigned long) maxlen != pnote->descsz) + goto desc_size_fail; + switch (pnote->type) { case NT_VMS_MHD: - if (pnote->descsz > 36) - { - size_t l = strlen (pnote->descdata + 34); - printf (_(" Creation date : %.17s\n"), pnote->descdata); - printf (_(" Last patch date: %.17s\n"), pnote->descdata + 17); - printf (_(" Module name : %s\n"), pnote->descdata + 34); - printf (_(" Module version : %s\n"), pnote->descdata + 34 + l + 1); - } + if (maxlen <= 36) + goto desc_size_fail; + + int l = (int) strnlen (pnote->descdata + 34, maxlen - 34); + + printf (_(" Creation date : %.17s\n"), pnote->descdata); + printf (_(" Last patch date: %.17s\n"), pnote->descdata + 17); + if (l + 34 < maxlen) + { + printf (_(" Module name : %s\n"), pnote->descdata + 34); + if (l + 35 < maxlen) + printf (_(" Module version : %s\n"), pnote->descdata + 34 + l + 1); + else + printf (_(" Module version : \n")); + } else - printf (_(" Invalid size\n")); + { + printf (_(" Module name : \n")); + printf (_(" Module version : \n")); + } break; + case NT_VMS_LNM: - printf (_(" Language: %s\n"), pnote->descdata); + printf (_(" Language: %.*s\n"), maxlen, pnote->descdata); break; + #ifdef BFD64 case NT_VMS_FPMODE: printf (_(" Floating Point mode: ")); + if (maxlen < 8) + goto desc_size_fail; + /* FIXME: Generate an error if descsz > 8 ? */ + printf ("0x%016" BFD_VMA_FMT "x\n", - (bfd_vma) byte_get ((unsigned char *)pnote->descdata, 8)); + (bfd_vma) byte_get ((unsigned char *)pnote->descdata, 8)); break; + case NT_VMS_LINKTIME: printf (_(" Link time: ")); + if (maxlen < 8) + goto desc_size_fail; + /* FIXME: Generate an error if descsz > 8 ? */ + print_vms_time - ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8)); + ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8)); printf ("\n"); break; + case NT_VMS_PATCHTIME: printf (_(" Patch time: ")); + if (maxlen < 8) + goto desc_size_fail; + /* FIXME: Generate an error if descsz > 8 ? */ + print_vms_time - ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8)); + ((bfd_int64_t) byte_get ((unsigned char *)pnote->descdata, 8)); printf ("\n"); break; + case NT_VMS_ORIG_DYN: + if (maxlen < 34) + goto desc_size_fail; + printf (_(" Major id: %u, minor id: %u\n"), (unsigned) byte_get ((unsigned char *)pnote->descdata, 4), (unsigned) byte_get ((unsigned char *)pnote->descdata + 4, 4)); @@ -17466,25 +18438,36 @@ print_ia64_vms_note (Elf_Internal_Note * pnote) (bfd_vma) byte_get ((unsigned char *)pnote->descdata + 16, 8)); printf (_(" Header flags: 0x%08x\n"), (unsigned) byte_get ((unsigned char *)pnote->descdata + 24, 4)); - printf (_(" Image id : %s\n"), pnote->descdata + 32); + printf (_(" Image id : %.*s\n"), maxlen - 32, pnote->descdata + 32); break; #endif + case NT_VMS_IMGNAM: - printf (_(" Image name: %s\n"), pnote->descdata); + printf (_(" Image name: %.*s\n"), maxlen, pnote->descdata); break; + case NT_VMS_GSTNAM: - printf (_(" Global symbol table name: %s\n"), pnote->descdata); + printf (_(" Global symbol table name: %.*s\n"), maxlen, pnote->descdata); break; + case NT_VMS_IMGID: - printf (_(" Image id: %s\n"), pnote->descdata); + printf (_(" Image id: %.*s\n"), maxlen, pnote->descdata); break; + case NT_VMS_LINKID: - printf (_(" Linker id: %s\n"), pnote->descdata); + printf (_(" Linker id: %.*s\n"), maxlen, pnote->descdata); break; + default: return FALSE; } + return TRUE; + + desc_size_fail: + printf (_(" \n")); + error (_("corrupt IA64 note: data size is too small\n")); + return FALSE; } /* Find the symbol associated with a build attribute that is attached @@ -17614,6 +18597,20 @@ get_symbol_for_build_attribute (Filedata * filedata, return saved_sym; } +/* Returns true iff addr1 and addr2 are in the same section. */ + +static bfd_boolean +same_section (Filedata * filedata, unsigned long addr1, unsigned long addr2) +{ + Elf_Internal_Shdr * a1; + Elf_Internal_Shdr * a2; + + a1 = find_section_by_address (filedata, addr1); + a2 = find_section_by_address (filedata, addr2); + + return a1 == a2 && a1 != NULL; +} + static bfd_boolean print_gnu_build_attribute_description (Elf_Internal_Note * pnote, Filedata * filedata) @@ -17674,7 +18671,7 @@ print_gnu_build_attribute_description (Elf_Internal_Note * pnote, start = byte_get ((unsigned char *) pnote->descdata, 8); end = byte_get ((unsigned char *) pnote->descdata + 8, 8); break; - + default: error (_(" \n"), pnote->descsz); printf (_(" ")); @@ -17695,8 +18692,14 @@ print_gnu_build_attribute_description (Elf_Internal_Note * pnote, if (is_open_attr) { - /* FIXME: Need to properly allow for section alignment. 16 is just the alignment used on x86_64. */ - if (global_end > 0 && start > BFD_ALIGN (global_end, 16)) + /* FIXME: Need to properly allow for section alignment. + 16 is just the alignment used on x86_64. */ + if (global_end > 0 + && start > BFD_ALIGN (global_end, 16) + /* Build notes are not guaranteed to be organised in order of + increasing address, but we should find the all of the notes + for one section in the same place. */ + && same_section (filedata, start, global_end)) warn (_("Gap in build notes detected from %#lx to %#lx\n"), global_end + 1, start - 1); @@ -17963,7 +18966,7 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) if (do_wide && left > 0) printf ("%-*s", left, " "); - + return TRUE; } @@ -18001,6 +19004,10 @@ process_note (Elf_Internal_Note * pnote, /* NetBSD-specific core file notes. */ return process_netbsd_elf_note (pnote); + else if (const_strneq (pnote->namedata, "PaX")) + /* NetBSD-specific core file notes. */ + return process_netbsd_elf_note (pnote); + else if (strneq (pnote->namedata, "SPU/", 4)) { /* SPU-specific core file notes. */ @@ -18209,7 +19216,7 @@ process_notes_at (Filedata * filedata, one version of Linux (RedHat 6.0) generates corefiles that don't comply with the ELF spec by failing to include the null byte in namesz. */ - if (inote.namedata[inote.namesz - 1] != '\0') + if (inote.namesz > 0 && inote.namedata[inote.namesz - 1] != '\0') { if ((size_t) (inote.descdata - inote.namedata) == inote.namesz) { @@ -18459,6 +19466,11 @@ process_arch_specific (Filedata * filedata) display_msp430x_attribute, display_generic_attribute); + case EM_RISCV: + return process_attributes (filedata, "riscv", SHT_RISCV_ATTRIBUTES, + display_riscv_attribute, + display_generic_attribute); + case EM_NDS32: return process_nds32_specific (filedata); @@ -18664,7 +19676,7 @@ open_debug_file (const char * pathname) static bfd_boolean process_object (Filedata * filedata) { - Filedata * separates; + bfd_boolean have_separate_files; unsigned int i; bfd_boolean res = TRUE; @@ -18741,19 +19753,26 @@ process_object (Filedata * filedata) res = FALSE; if (filedata->file_header.e_shstrndx != SHN_UNDEF) - separates = load_separate_debug_file (filedata, filedata->file_name); + have_separate_files = load_separate_debug_files (filedata, filedata->file_name); else - separates = NULL; + have_separate_files = FALSE; if (! process_section_contents (filedata)) res = FALSE; - if (separates) + if (have_separate_files) { - if (! process_section_headers (separates)) - res = FALSE; - else if (! process_section_contents (separates)) - res = FALSE; + separate_info * d; + + for (d = first_separate_info; d != NULL; d = d->next) + { + if (! process_section_headers (d->handle)) + res = FALSE; + else if (! process_section_contents (d->handle)) + res = FALSE; + } + + /* The file handles are closed by the call to free_debug_memory() below. */ } if (! process_notes (filedata)) @@ -18915,7 +19934,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) l += strnlen (arch.sym_table + l, arch.sym_size - l) + 1; } - if (arch.uses_64bit_indicies) + if (arch.uses_64bit_indices) l = (l + 7) & ~ 7; else l += l & 1; @@ -18961,7 +19980,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) /* Read the next archive header. */ if (fseek (filedata->handle, arch.next_arhdr_offset, SEEK_SET) != 0) { - error (_("%s: failed to seek to next archive header\n"), filedata->file_name); + error (_("%s: failed to seek to next archive header\n"), arch.file_name); return FALSE; } got = fread (&arch.arhdr, 1, sizeof arch.arhdr, filedata->handle); @@ -18969,7 +19988,10 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) { if (got == 0) break; - error (_("%s: failed to read archive header\n"), filedata->file_name); + /* PR 24049 - we cannot use filedata->file_name as this will + have already been freed. */ + error (_("%s: failed to read archive header\n"), arch.file_name); + ret = FALSE; break; } @@ -18989,7 +20011,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) name = get_archive_member_name (&arch, &nested_arch); if (name == NULL) { - error (_("%s: bad archive file name\n"), filedata->file_name); + error (_("%s: bad archive file name\n"), arch.file_name); ret = FALSE; break; } @@ -18998,7 +20020,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) qualified_name = make_qualified_name (&arch, &nested_arch, name); if (qualified_name == NULL) { - error (_("%s: bad archive file name\n"), filedata->file_name); + error (_("%s: bad archive file name\n"), arch.file_name); ret = FALSE; break; } @@ -19044,7 +20066,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) if (nested_arch.file == NULL) { error (_("%s: contains corrupt thin archive: %s\n"), - filedata->file_name, name); + qualified_name, name); ret = FALSE; break; } @@ -19063,7 +20085,7 @@ process_archive (Filedata * filedata, bfd_boolean is_thin_archive) thin_filedata.handle = nested_arch.file; thin_filedata.file_name = qualified_name; - + if (! process_object (& thin_filedata)) ret = FALSE; } @@ -19230,5 +20252,9 @@ main (int argc, char ** argv) if (cmdline.dump_sects != NULL) free (cmdline.dump_sects); + free (dump_ctf_symtab_name); + free (dump_ctf_strtab_name); + free (dump_ctf_parent_name); + return err ? EXIT_FAILURE : EXIT_SUCCESS; }