X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=3f424c4e63d6779c27c83a2ad8a0d02217fb696b;hb=c22b42ce308eb538050b4b5789e406b63102b35a;hp=53896ae647bf54d596528581e94472061d98c883;hpb=4dff97b2ce94bbb9c0c16e0e4129060b9a894f13;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 53896ae647..3f424c4e63 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-2017 Free Software Foundation, Inc. + Copyright (C) 1998-2019 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -98,6 +98,7 @@ #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" @@ -119,6 +120,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" @@ -131,6 +133,7 @@ #include "elf/mt.h" #include "elf/msp430.h" #include "elf/nds32.h" +#include "elf/nfp.h" #include "elf/nios2.h" #include "elf/or1k.h" #include "elf/pj.h" @@ -395,10 +398,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"), @@ -515,7 +519,8 @@ print_symbol (signed int width, const char *symbol) width = - width; extra_padding = TRUE; } - assert (width != 0); + else if (width == 0) + return 0; if (do_wide) /* Set the remaining width to a very large value. @@ -655,7 +660,8 @@ find_section (Filedata * filedata, const char * name) { unsigned int i; - assert (filedata->section_headers != NULL); + if (filedata->section_headers == NULL) + return NULL; for (i = 0; i < filedata->file_header.e_shnum; i++) if (streq (SECTION_NAME (filedata->section_headers + i), name)) @@ -672,6 +678,9 @@ find_section_by_address (Filedata * filedata, bfd_vma addr) { unsigned int i; + if (filedata->section_headers == NULL) + return NULL; + for (i = 0; i < filedata->file_header.e_shnum; i++) { Elf_Internal_Shdr *sec = filedata->section_headers + i; @@ -688,6 +697,9 @@ find_section_by_type (Filedata * filedata, unsigned int type) { unsigned int i; + if (filedata->section_headers == NULL) + return NULL; + for (i = 0; i < filedata->file_header.e_shnum; i++) { Elf_Internal_Shdr *sec = filedata->section_headers + i; @@ -707,6 +719,9 @@ find_section_in_set (Filedata * filedata, const char * name, unsigned int * set) { unsigned int i; + if (filedata->section_headers == NULL) + return NULL; + if (set != NULL) { while ((i = *set++) > 0) @@ -765,6 +780,7 @@ guess_is_rela (unsigned int e_machine) case EM_CYGNUS_M32R: case EM_SCORE: case EM_XGATE: + case EM_NFP: return FALSE; /* Targets that use RELA relocations. */ @@ -783,6 +799,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: @@ -1261,6 +1278,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; @@ -1330,6 +1351,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; @@ -1549,6 +1574,13 @@ dump_relocations (Filedata * filedata, case EM_TI_PRU: rtype = elf_pru_reloc_type (type); break; + + case EM_NFP: + if (EF_NFP_MACH (filedata->file_header.e_flags) == E_NFP_MACH_3200) + rtype = elf_nfp3200_reloc_type (type); + else + rtype = elf_nfp_reloc_type (type); + break; } if (rtype == NULL) @@ -2263,7 +2295,7 @@ get_machine_name (unsigned e_machine) case EM_PARISC: return "HPPA"; case EM_VPP550: return "Fujitsu VPP500"; case EM_SPARC32PLUS: return "Sparc v8+" ; - case EM_960: return "Intel 90860"; + case EM_960: return "Intel 80960"; case EM_PPC: return "PowerPC"; /* 20 */ case EM_PPC64: return "PowerPC64"; @@ -2461,6 +2493,7 @@ get_machine_name (unsigned e_machine) case EM_RISCV: return "RISC-V"; case EM_LANAI: return "Lanai 32-bit processor"; case EM_BPF: return "Linux BPF"; + case EM_NFP: return "Netronome Flow Processor"; /* Large numbers... */ case EM_MT: return "Morpho Techologies MT processor"; @@ -2474,6 +2507,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); @@ -2567,6 +2602,12 @@ decode_ARM_machine_flags (unsigned e_flags, char buf[]) e_flags &= ~ EF_ARM_RELEXEC; } + if (e_flags & EF_ARM_PIC) + { + strcat (buf, ", position independent"); + e_flags &= ~ EF_ARM_PIC; + } + /* Now handle EABI specific flags. */ switch (eabi) { @@ -3364,7 +3405,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; @@ -3423,10 +3466,25 @@ get_machine_flags (Filedata * filedata, unsigned e_flags, unsigned e_machine) decode_NDS32_machine_flags (e_flags, buf, sizeof buf); break; + case EM_NFP: + switch (EF_NFP_MACH (e_flags)) + { + case E_NFP_MACH_3200: + strcat (buf, ", NFP-32xx"); + break; + case E_NFP_MACH_6000: + strcat (buf, ", NFP-6xxx"); + break; + } + break; + case EM_RISCV: 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: @@ -3632,6 +3690,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: @@ -3707,6 +3767,7 @@ get_osabi_name (Filedata * filedata, unsigned int osabi) switch (osabi) { case ELFOSABI_ARM: return "ARM"; + case ELFOSABI_ARM_FDPIC: return "ARM FDPIC"; default: break; } @@ -3872,6 +3933,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) @@ -4117,6 +4179,18 @@ get_msp430x_section_type_name (unsigned int sh_type) } } +static const char * +get_nfp_section_type_name (unsigned int sh_type) +{ + switch (sh_type) + { + case SHT_NFP_MECONFIG: return "NFP_MECONFIG"; + case SHT_NFP_INITREG: return "NFP_INITREG"; + case SHT_NFP_UDEBUG: return "NFP_UDEBUG"; + default: return NULL; + } +} + static const char * get_v850_section_type_name (unsigned int sh_type) { @@ -4131,6 +4205,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) { @@ -4156,7 +4240,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"; @@ -4203,11 +4287,17 @@ get_section_type_name (Filedata * filedata, unsigned int sh_type) case EM_MSP430: result = get_msp430x_section_type_name (sh_type); break; + case EM_NFP: + result = get_nfp_section_type_name (sh_type); + break; case EM_V800: case EM_V850: 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; @@ -4694,12 +4784,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])); @@ -4710,45 +4800,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); } @@ -4761,7 +4863,7 @@ process_file_header (Filedata * filedata) header->e_shnum = filedata->section_headers[0].sh_size; if (header->e_shstrndx == (SHN_XINDEX & 0xffff)) header->e_shstrndx = filedata->section_headers[0].sh_link; - else if (header->e_shstrndx >= header->e_shnum) + if (header->e_shstrndx >= header->e_shnum) header->e_shstrndx = SHN_UNDEF; free (filedata->section_headers); filedata->section_headers = NULL; @@ -5134,7 +5236,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; @@ -5266,6 +5369,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; } @@ -5332,6 +5436,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; } @@ -5370,6 +5475,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) { @@ -5411,30 +5517,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)); @@ -5461,10 +5572,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; @@ -5483,6 +5592,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) { @@ -5524,30 +5634,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)); @@ -5576,10 +5691,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; @@ -6204,14 +6317,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)) @@ -6225,7 +6345,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"), @@ -6258,26 +6378,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 - && (streq (SECTION_NAME (section), ".rel.dyn") - || streq (SECTION_NAME (section), ".rela.dyn"))) - /* The .rel.dyn and .rela.dyn sections have an sh_info field - of zero. The relocations in these sections may apply - to many different sections. */ - ; - 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: @@ -6441,8 +6559,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); @@ -6776,7 +6893,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; } @@ -7498,14 +7615,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; } @@ -7524,6 +7641,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: @@ -7954,19 +8080,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; + } - switch ((rp->r_offset % unw_ent_size) / eh_addr_size) + 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) / 4) { case 0: aux->table[i].start.section = sym->st_shndx; @@ -8034,7 +8181,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", @@ -8047,8 +8194,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; @@ -8707,21 +8854,28 @@ decode_tic6x_unwind_bytecode (Filedata * filedata, } printf (_("pop frame {")); - reg = nregs - 1; - for (i = i * 2; i > 0; i--) + if (nregs == 0) { - if (regpos[reg].offset == i - 1) + printf (_("*corrupt* - no registers specified")); + } + else + { + 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 ("}"); @@ -9606,6 +9760,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) { @@ -9640,7 +9799,7 @@ process_dynamic_section (Filedata * filedata) if (archive_file_offset != 0) str_tab_len = archive_file_size - offset; else - str_tab_len = filedata->file_size; + str_tab_len = filedata->file_size - offset; if (str_tab_len < 1) { @@ -9649,11 +9808,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; } } @@ -9696,6 +9860,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) { @@ -9996,6 +10165,21 @@ process_dynamic_section (Filedata * filedata) printf (" PIE"); val ^= DF_1_PIE; } + if (val & DF_1_KMOD) + { + printf (" KMOD"); + val ^= DF_1_KMOD; + } + if (val & DF_1_WEAKFILTER) + { + printf (" WEAKFILTER"); + val ^= DF_1_WEAKFILTER; + } + if (val & DF_1_NOCOMMON) + { + printf (" NOCOMMON"); + val ^= DF_1_NOCOMMON; + } if (val != 0) printf (" %lx", val); puts (""); @@ -10199,7 +10383,7 @@ process_dynamic_section (Filedata * filedata) static char * get_ver_flags (unsigned int flags) { - static char buff[32]; + static char buff[128]; buff[0] = 0; @@ -10963,11 +11147,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; @@ -11170,6 +11359,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) @@ -11184,9 +11374,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 @@ -11219,20 +11411,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; @@ -11315,6 +11515,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; } @@ -12196,6 +12399,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: @@ -12235,6 +12440,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: @@ -12269,7 +12477,8 @@ 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: case EM_PJ_OLD: @@ -12385,6 +12594,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. */ @@ -12569,6 +12780,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: @@ -12585,6 +12798,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. */ @@ -12713,6 +12956,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). */ @@ -12832,7 +13090,6 @@ apply_relocations (Filedata * filedata, { Elf_Internal_Shdr * relsec; unsigned char * end = start + size; - bfd_boolean res = TRUE; if (relocs_return != NULL) { @@ -12916,6 +13173,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)) @@ -12944,6 +13204,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; @@ -12952,7 +13218,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; } @@ -12962,7 +13227,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; } @@ -12971,7 +13235,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; @@ -12997,7 +13260,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; } @@ -13016,7 +13278,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)) @@ -13027,6 +13294,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 @@ -13049,7 +13326,7 @@ apply_relocations (Filedata * filedata, break; } - return res; + return TRUE; } #ifdef SUPPORT_DISASSEMBLY @@ -13175,12 +13452,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; @@ -13322,12 +13593,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; @@ -13497,12 +13762,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; @@ -13574,7 +13833,13 @@ load_debug_section (enum dwarf_section_display_enum debug, void * data) Elf_Internal_Shdr * sec; Filedata * filedata = (Filedata *) data; - if (filedata->string_table == NULL) + /* Without section headers we cannot find any sections. */ + if (filedata->section_headers == NULL) + return FALSE; + + if (filedata->string_table == NULL + && filedata->file_header.e_shstrndx != SHN_UNDEF + && filedata->file_header.e_shstrndx < filedata->file_header.e_shnum) { Elf_Internal_Shdr * strs; @@ -13583,11 +13848,12 @@ load_debug_section (enum dwarf_section_display_enum debug, void * data) if (strs != NULL && strs->sh_size != 0) { - filedata->string_table = (char *) get_data (NULL, filedata, strs->sh_offset, - 1, strs->sh_size, - _("string table")); + filedata->string_table + = (char *) get_data (NULL, filedata, strs->sh_offset, + 1, strs->sh_size, _("string table")); - filedata->string_table_length = filedata->string_table != NULL ? strs->sh_size : 0; + filedata->string_table_length + = filedata->string_table != NULL ? strs->sh_size : 0; } } @@ -14045,6 +14311,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); } @@ -14987,7 +15259,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; @@ -15112,6 +15384,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, @@ -15412,6 +15766,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) @@ -15438,9 +15804,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; @@ -16508,7 +16871,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: @@ -16584,9 +16947,9 @@ get_note_type (Filedata * filedata, unsigned e_type) case NT_ARCH: return _("NT_ARCH (architecture)"); case NT_GNU_BUILD_ATTRIBUTE_OPEN: - return _("NT_GNU_BUILD_ATTRIBUTE_OPEN"); + return _("OPEN"); case NT_GNU_BUILD_ATTRIBUTE_FUNC: - return _("NT_GNU_BUILD_ATTRIBUTE_FUNC"); + return _("func"); default: break; } @@ -16716,9 +17079,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); @@ -16726,25 +17168,81 @@ 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; + default: + printf (_(""), bit); + break; } if (bitmask) printf (", "); @@ -16752,8 +17250,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); @@ -16762,26 +17266,65 @@ 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); @@ -16837,30 +17380,89 @@ 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 + { + 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 - decode_x86_feature (type, byte_get (ptr, 4)); + { + 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: @@ -17406,13 +18008,16 @@ print_ia64_vms_note (Elf_Internal_Note * pnote) return TRUE; } -/* Print the name of the symbol associated with a build attribute - that is attached to address OFFSET. */ +/* Find the symbol associated with a build attribute that is attached + to address OFFSET. If PNAME is non-NULL then store the name of + the symbol (if found) in the provided pointer, Returns NULL if a + symbol could not be found. */ -static bfd_boolean -print_symbol_for_build_attribute (Filedata * filedata, - unsigned long offset, - bfd_boolean is_open_attr) +static Elf_Internal_Sym * +get_symbol_for_build_attribute (Filedata * filedata, + unsigned long offset, + bfd_boolean is_open_attr, + const char ** pname) { static Filedata * saved_filedata = NULL; static char * strtab; @@ -17451,10 +18056,7 @@ print_symbol_for_build_attribute (Filedata * filedata, } if (symtab == NULL || strtab == NULL) - { - printf ("\n"); - return FALSE; - } + return NULL; /* Find a symbol whose value matches offset. */ for (sym = symtab; sym < symtab + nsyms; sym ++) @@ -17467,6 +18069,13 @@ print_symbol_for_build_attribute (Filedata * filedata, if (strtab[sym->st_name] == 0) continue; + /* The AArch64 and ARM architectures define mapping symbols + (eg $d, $x, $t) which we want to ignore. */ + if (strtab[sym->st_name] == '$' + && strtab[sym->st_name + 1] != 0 + && strtab[sym->st_name + 2] == 0) + continue; + if (is_open_attr) { /* For OPEN attributes we prefer GLOBAL over LOCAL symbols @@ -17474,14 +18083,15 @@ print_symbol_for_build_attribute (Filedata * filedata, FUNC symbols entirely. */ switch (ELF_ST_TYPE (sym->st_info)) { - case STT_FILE: - saved_sym = sym; - /* We can stop searching now. */ - sym = symtab + nsyms; - continue; - case STT_OBJECT: + case STT_FILE: saved_sym = sym; + if (sym->st_size) + { + /* If the symbol has a size associated + with it then we can stop searching. */ + sym = symtab + nsyms; + } continue; case STT_FUNC: @@ -17519,55 +18129,144 @@ print_symbol_for_build_attribute (Filedata * filedata, } } - printf (" (%s: %s)\n", - is_open_attr ? _("file") : _("func"), - saved_sym ? strtab + saved_sym->st_name : _(")")); - return TRUE; + if (saved_sym && pname) + * pname = strtab + saved_sym->st_name; + + 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) { - static unsigned long global_offset = 0; - unsigned long offset; - unsigned int desc_size = is_32bit_elf ? 4 : 8; - bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN; + static unsigned long global_offset = 0; + static unsigned long global_end = 0; + static unsigned long func_offset = 0; + static unsigned long func_end = 0; - if (pnote->descsz == 0) + Elf_Internal_Sym * sym; + const char * name; + unsigned long start; + unsigned long end; + bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN; + + switch (pnote->descsz) { + case 0: + /* A zero-length description means that the range of + the previous note of the same type should be used. */ if (is_open_attr) { - printf (_(" Applies from offset %#lx\n"), global_offset); - return TRUE; + if (global_end > global_offset) + printf (_(" Applies to region from %#lx to %#lx\n"), + global_offset, global_end); + else + printf (_(" Applies to region from %#lx\n"), global_offset); } else { - printf (_(" Applies to func at %#lx"), global_offset); - return print_symbol_for_build_attribute (filedata, global_offset, is_open_attr); + if (func_end > func_offset) + printf (_(" Applies to region from %#lx to %#lx\n"), func_offset, func_end); + else + printf (_(" Applies to region from %#lx\n"), func_offset); } - } + return TRUE; - if (pnote->descsz != desc_size) - { + case 4: + start = byte_get ((unsigned char *) pnote->descdata, 4); + end = 0; + break; + + case 8: + if (is_32bit_elf) + { + /* FIXME: We should check that version 3+ notes are being used here... */ + start = byte_get ((unsigned char *) pnote->descdata, 4); + end = byte_get ((unsigned char *) pnote->descdata + 4, 4); + } + else + { + start = byte_get ((unsigned char *) pnote->descdata, 8); + end = 0; + } + break; + + case 16: + start = byte_get ((unsigned char *) pnote->descdata, 8); + end = byte_get ((unsigned char *) pnote->descdata + 8, 8); + break; + + default: error (_(" \n"), pnote->descsz); printf (_(" ")); return FALSE; } - offset = byte_get ((unsigned char *) pnote->descdata, desc_size); + name = NULL; + sym = get_symbol_for_build_attribute (filedata, start, is_open_attr, & name); + /* As of version 5 of the annobin plugin, filename symbols are biased by 2 + in order to avoid them being confused with the start address of the + first function in the file... */ + if (sym == NULL && is_open_attr) + sym = get_symbol_for_build_attribute (filedata, start + 2, is_open_attr, + & name); + + if (end == 0 && sym != NULL && sym->st_size > 0) + end = start + sym->st_size; if (is_open_attr) { - printf (_(" Applies from offset %#lx"), offset); - global_offset = offset; + /* 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); + + printf (_(" Applies to region from %#lx"), start); + global_offset = start; + + if (end) + { + printf (_(" to %#lx"), end); + global_end = end; + } } else { - printf (_(" Applies to func at %#lx"), offset); + printf (_(" Applies to region from %#lx"), start); + func_offset = start; + + if (end) + { + printf (_(" to %#lx"), end); + func_end = end; + } } - return print_symbol_for_build_attribute (filedata, offset, is_open_attr); + if (sym && name) + printf (_(" (%s)"), name); + + printf ("\n"); + return TRUE; } static bfd_boolean @@ -17590,11 +18289,21 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) return FALSE; } - left = 20; + if (do_wide) + left = 28; + else + left = 20; /* Version 2 of the spec adds a "GA" prefix to the name field. */ if (name[0] == 'G' && name[1] == 'A') { + if (pnote->namesz < 4) + { + error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz); + print_symbol (-20, _(" ")); + return FALSE; + } + printf ("GA"); name += 2; left -= 2; @@ -17904,13 +18613,13 @@ static bfd_boolean process_notes_at (Filedata * filedata, Elf_Internal_Shdr * section, bfd_vma offset, - bfd_vma length) + bfd_vma length, + bfd_vma align) { Elf_External_Note * pnotes; Elf_External_Note * external; char * end; bfd_boolean res = TRUE; - size_t align; if (length <= 0) return FALSE; @@ -17923,21 +18632,11 @@ process_notes_at (Filedata * filedata, if (! apply_relocations (filedata, section, (unsigned char *) pnotes, length, NULL, NULL)) return FALSE; } - align = section->sh_addralign; } else - { - pnotes = (Elf_External_Note *) get_data (NULL, filedata, offset, 1, length, + pnotes = (Elf_External_Note *) get_data (NULL, filedata, offset, 1, length, _("notes")); - /* FIXME: Core notes seem to be produced with - 4-byte alignment even on 64-bit systems. */ - if (filedata->file_header.e_type == ET_CORE) - align = 4; - else - align = is_32bit_elf ? 4 : 4; - } - if (pnotes == NULL) return FALSE; @@ -17949,6 +18648,20 @@ process_notes_at (Filedata * filedata, printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"), (unsigned long) offset, (unsigned long) length); + /* NB: Some note sections may have alignment value of 0 or 1. gABI + specifies that notes should be aligned to 4 bytes in 32-bit + objects and to 8 bytes in 64-bit objects. As a Linux extension, + we also support 4 byte alignment in 64-bit objects. If section + alignment is less than 4, we treate alignment as 4 bytes. */ + if (align < 4) + align = 4; + else if (align != 4 && align != 8) + { + warn (_("Corrupt note: alignment %ld, expecting 4 or 8\n"), + (long) align); + return FALSE; + } + printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size")); end = (char *) pnotes + length; @@ -18037,7 +18750,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) { @@ -18087,7 +18800,8 @@ process_corefile_note_segments (Filedata * filedata) if (segment->p_type == PT_NOTE) if (! process_notes_at (filedata, NULL, (bfd_vma) segment->p_offset, - (bfd_vma) segment->p_filesz)) + (bfd_vma) segment->p_filesz, + (bfd_vma) segment->p_align)) res = FALSE; } @@ -18191,7 +18905,8 @@ process_note_sections (Filedata * filedata) { if (! process_notes_at (filedata, section, (bfd_vma) section->sh_offset, - (bfd_vma) section->sh_size)) + (bfd_vma) section->sh_size, + (bfd_vma) section->sh_addralign)) res = FALSE; n++; } @@ -18285,6 +19000,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); @@ -18566,7 +19286,10 @@ process_object (Filedata * filedata) if (! process_version_sections (filedata)) res = FALSE; - separates = load_separate_debug_file (filedata, filedata->file_name); + if (filedata->file_header.e_shstrndx != SHN_UNDEF) + separates = load_separate_debug_file (filedata, filedata->file_name); + else + separates = NULL; if (! process_section_contents (filedata)) res = FALSE; @@ -18738,7 +19461,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; @@ -18784,7 +19507,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); @@ -18792,7 +19515,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; } @@ -18812,7 +19538,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; } @@ -18821,7 +19547,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; } @@ -18867,7 +19593,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; }