X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=binutils%2Freadelf.c;h=e782e9561f2069d7ec2e7ac8b63ab73fb34d6183;hb=128e85e3ab36b8e30f6612fb50de3cbb4ede6824;hp=70a84e54e8efd7630ecfef37288868dac1028ccc;hpb=c6056a744af028824797e769ddb71927740be88a;p=deliverable%2Fbinutils-gdb.git diff --git a/binutils/readelf.c b/binutils/readelf.c index 70a84e54e8..e782e9561f 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-2015 Free Software Foundation, Inc. + Copyright (C) 1998-2016 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -124,6 +124,7 @@ #include "elf/metag.h" #include "elf/microblaze.h" #include "elf/mips.h" +#include "elf/riscv.h" #include "elf/mmix.h" #include "elf/mn10200.h" #include "elf/mn10300.h" @@ -346,8 +347,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, || (bfd_size_type) ((size_t) nmemb) != nmemb)) { if (reason) - error (_("Size truncation prevents reading 0x%llx elements of size 0x%llx for %s\n"), - (unsigned long long) nmemb, (unsigned long long) size, reason); + error (_("Size truncation prevents reading 0x%" BFD_VMA_FMT "x" + " elements of size 0x%" BFD_VMA_FMT "x for %s\n"), + nmemb, size, reason); return NULL; } @@ -355,8 +357,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, if (amt < nmemb) { if (reason) - error (_("Size overflow prevents reading 0x%llx elements of size 0x%llx for %s\n"), - (unsigned long long) nmemb, (unsigned long long) size, reason); + error (_("Size overflow prevents reading 0x%" BFD_VMA_FMT "x" + " elements of size 0x%" BFD_VMA_FMT "x for %s\n"), + nmemb, size, reason); return NULL; } @@ -366,8 +369,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, || offset + archive_file_offset + amt > current_file_size) { if (reason) - error (_("Reading 0x%llx bytes extends past end of file for %s\n"), - (unsigned long long) amt, reason); + error (_("Reading 0x%" BFD_VMA_FMT "x" + " bytes extends past end of file for %s\n"), + amt, reason); return NULL; } @@ -375,7 +379,7 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, { if (reason) error (_("Unable to seek to 0x%lx for %s\n"), - (unsigned long) archive_file_offset + offset, reason); + archive_file_offset + offset, reason); return NULL; } @@ -390,8 +394,9 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, if (mvar == NULL) { if (reason) - error (_("Out of memory allocating 0x%llx bytes for %s\n"), - (unsigned long long) amt, reason); + error (_("Out of memory allocating 0x%" BFD_VMA_FMT "x" + " bytes for %s\n"), + amt, reason); return NULL; } @@ -401,8 +406,8 @@ get_data (void * var, FILE * file, unsigned long offset, bfd_size_type size, if (fread (mvar, (size_t) size, (size_t) nmemb, file) != nmemb) { if (reason) - error (_("Unable to read in 0x%llx bytes of %s\n"), - (unsigned long long) amt, reason); + error (_("Unable to read in 0x%" BFD_VMA_FMT "x bytes of %s\n"), + amt, reason); if (mvar != var) free (mvar); return NULL; @@ -422,7 +427,7 @@ print_vma (bfd_vma vma, print_mode mode) { case FULL_HEX: nc = printf ("0x"); - /* Drop through. */ + /* Fall through. */ case LONG_HEX: #ifdef BFD64 @@ -435,11 +440,11 @@ print_vma (bfd_vma vma, print_mode mode) case DEC_5: if (vma <= 99999) return printf ("%5" BFD_VMA_FMT "d", vma); - /* Drop through. */ + /* Fall through. */ case PREFIX_HEX: nc = printf ("0x"); - /* Drop through. */ + /* Fall through. */ case HEX: return nc + printf ("%" BFD_VMA_FMT "x", vma); @@ -552,7 +557,7 @@ print_symbol (int width, const char *symbol) return num_printed; } -/* Returns a pointer to a static buffer containing a printable version of +/* Returns a pointer to a static buffer containing a printable version of the given section's name. Like print_symbol, except that it does not try to print multibyte characters, it just interprets them as hex values. */ @@ -771,6 +776,7 @@ guess_is_rela (unsigned int e_machine) case EM_OR1K: case EM_PPC64: case EM_PPC: + case EM_RISCV: case EM_RL78: case EM_RX: case EM_S390: @@ -1288,6 +1294,7 @@ dump_relocations (FILE * file, rtype = elf_msp430x_reloc_type (type); break; } + /* Fall through. */ case EM_MSP430_OLD: rtype = elf_msp430_reloc_type (type); break; @@ -1309,6 +1316,10 @@ dump_relocations (FILE * file, rtype = elf_mips_reloc_type (type); break; + case EM_RISCV: + rtype = elf_riscv_reloc_type (type); + break; + case EM_ALPHA: rtype = elf_alpha_reloc_type (type); break; @@ -1846,6 +1857,34 @@ get_ia64_dynamic_type (unsigned long type) } } +static const char * +get_solaris_section_type (unsigned long type) +{ + switch (type) + { + case 0x6fffffee: return "SUNW_ancillary"; + case 0x6fffffef: return "SUNW_capchain"; + case 0x6ffffff0: return "SUNW_capinfo"; + case 0x6ffffff1: return "SUNW_symsort"; + case 0x6ffffff2: return "SUNW_tlssort"; + case 0x6ffffff3: return "SUNW_LDYNSYM"; + case 0x6ffffff4: return "SUNW_dof"; + case 0x6ffffff5: return "SUNW_cap"; + case 0x6ffffff6: return "SUNW_SIGNATURE"; + case 0x6ffffff7: return "SUNW_ANNOTATE"; + case 0x6ffffff8: return "SUNW_DEBUGSTR"; + case 0x6ffffff9: return "SUNW_DEBUG"; + case 0x6ffffffa: return "SUNW_move"; + case 0x6ffffffb: return "SUNW_COMDAT"; + case 0x6ffffffc: return "SUNW_syminfo"; + case 0x6ffffffd: return "SUNW_verdef"; + case 0x6ffffffe: return "SUNW_verneed"; + case 0x6fffffff: return "SUNW_versym"; + case 0x70000000: return "SPARC_GOTDATA"; + default: return NULL; + } +} + static const char * get_alpha_dynamic_type (unsigned long type) { @@ -1900,6 +1939,43 @@ get_nios2_dynamic_type (unsigned long type) } } +static const char * +get_solaris_dynamic_type (unsigned long type) +{ + switch (type) + { + case 0x6000000d: return "SUNW_AUXILIARY"; + case 0x6000000e: return "SUNW_RTLDINF"; + case 0x6000000f: return "SUNW_FILTER"; + case 0x60000010: return "SUNW_CAP"; + case 0x60000011: return "SUNW_SYMTAB"; + case 0x60000012: return "SUNW_SYMSZ"; + case 0x60000013: return "SUNW_SORTENT"; + case 0x60000014: return "SUNW_SYMSORT"; + case 0x60000015: return "SUNW_SYMSORTSZ"; + case 0x60000016: return "SUNW_TLSSORT"; + case 0x60000017: return "SUNW_TLSSORTSZ"; + case 0x60000018: return "SUNW_CAPINFO"; + case 0x60000019: return "SUNW_STRPAD"; + case 0x6000001a: return "SUNW_CAPCHAIN"; + case 0x6000001b: return "SUNW_LDMACH"; + case 0x6000001d: return "SUNW_CAPCHAINENT"; + case 0x6000001f: return "SUNW_CAPCHAINSZ"; + case 0x60000021: return "SUNW_PARENT"; + case 0x60000023: return "SUNW_ASLR"; + case 0x60000025: return "SUNW_RELAX"; + case 0x60000029: return "SUNW_NXHEAP"; + case 0x6000002b: return "SUNW_NXSTACK"; + + case 0x70000001: return "SPARC_REGISTER"; + case 0x7ffffffd: return "AUXILIARY"; + case 0x7ffffffe: return "USED"; + case 0x7fffffff: return "FILTER"; + + default: return NULL; + } +} + static const char * get_dynamic_type (unsigned long type) { @@ -1941,6 +2017,7 @@ get_dynamic_type (unsigned long type) case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; + case DT_SYMTAB_SHNDX: return "SYMTAB_SHNDX"; case DT_CHECKSUM: return "CHECKSUM"; case DT_PLTPADSZ: return "PLTPADSZ"; @@ -2018,7 +2095,10 @@ get_dynamic_type (unsigned long type) result = get_nios2_dynamic_type (type); break; default: - result = NULL; + if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) + result = get_solaris_dynamic_type (type); + else + result = NULL; break; } @@ -2042,7 +2122,10 @@ get_dynamic_type (unsigned long type) result = get_ia64_dynamic_type (type); break; default: - result = NULL; + if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) + result = get_solaris_dynamic_type (type); + else + result = NULL; break; } @@ -2250,6 +2333,7 @@ get_machine_name (unsigned e_machine) case EM_CR16: case EM_MICROBLAZE: case EM_MICROBLAZE_OLD: return "Xilinx MicroBlaze"; + case EM_RISCV: return "RISC-V"; case EM_RL78: return "Renesas RL78"; case EM_RX: return "Renesas RX"; case EM_METAG: return "Imagination Technologies Meta processor architecture"; @@ -2264,12 +2348,101 @@ get_machine_name (unsigned e_machine) case EM_TILEGX: return "Tilera TILE-Gx multicore architecture family"; case EM_CUDA: return "NVIDIA CUDA architecture"; case EM_XGATE: return "Motorola XGATE embedded processor"; + case EM_CLOUDSHIELD: return "CloudShield architecture family"; + case EM_COREA_1ST: return "KIPO-KAIST Core-A 1st generation processor family"; + case EM_COREA_2ND: return "KIPO-KAIST Core-A 2nd generation processor family"; + case EM_OPEN8: return "Open8 8-bit RISC soft processor core"; + case EM_VIDEOCORE5: return "Broadcom VideoCore V processor"; + case EM_56800EX: return "Freescale 56800EX Digital Signal Controller (DSC)"; + case EM_BA1: return "Beyond BA1 CPU architecture"; + case EM_BA2: return "Beyond BA2 CPU architecture"; + case EM_XCORE: return "XMOS xCORE processor family"; + case EM_MCHP_PIC: return "Microchip 8-bit PIC(r) family"; + case EM_KM32: return "KM211 KM32 32-bit processor"; + case EM_KMX32: return "KM211 KMX32 32-bit processor"; + case EM_KMX16: return "KM211 KMX16 16-bit processor"; + case EM_KMX8: return "KM211 KMX8 8-bit processor"; + case EM_KVARC: return "KM211 KVARC processor"; + case EM_CDP: return "Paneve CDP architecture family"; + case EM_COGE: return "Cognitive Smart Memory Processor"; + case EM_COOL: return "Bluechip Systems CoolEngine"; + case EM_NORC: return "Nanoradio Optimized RISC"; + case EM_CSR_KALIMBA: return "CSR Kalimba architecture family"; + case EM_Z80: return "Zilog Z80"; + case EM_AMDGPU: return "AMD GPU architecture"; default: snprintf (buff, sizeof (buff), _(": 0x%x"), e_machine); return buff; } } +static void +decode_ARC_machine_flags (unsigned e_flags, unsigned e_machine, char buf[]) +{ + /* ARC has two machine types EM_ARC_COMPACT and EM_ARC_COMPACT2. Some + other compilers don't a specific architecture type in the e_flags, and + instead use EM_ARC_COMPACT for old ARC600, ARC601, and ARC700 + architectures, and switch to EM_ARC_COMPACT2 for newer ARCEM and ARCHS + architectures. + + Th GNU tools follows this use of EM_ARC_COMPACT and EM_ARC_COMPACT2, + but also sets a specific architecture type in the e_flags field. + + However, when decoding the flags we don't worry if we see an + unexpected pairing, for example EM_ARC_COMPACT machine type, with + ARCEM architecture type. */ + + switch (e_flags & EF_ARC_MACH_MSK) + { + /* We only expect these to occur for EM_ARC_COMPACT2. */ + case EF_ARC_CPU_ARCV2EM: + strcat (buf, ", ARC EM"); + break; + case EF_ARC_CPU_ARCV2HS: + strcat (buf, ", ARC HS"); + break; + + /* We only expect these to occur for EM_ARC_COMPACT. */ + case E_ARC_MACH_ARC600: + strcat (buf, ", ARC600"); + break; + case E_ARC_MACH_ARC601: + strcat (buf, ", ARC601"); + break; + case E_ARC_MACH_ARC700: + strcat (buf, ", ARC700"); + break; + + /* The only times we should end up here are (a) A corrupt ELF, (b) A + new ELF with new architecture being read by an old version of + readelf, or (c) An ELF built with non-GNU compiler that does not + set the architecture in the e_flags. */ + default: + if (e_machine == EM_ARC_COMPACT) + strcat (buf, ", Unknown ARCompact"); + else + strcat (buf, ", Unknown ARC"); + break; + } + + switch (e_flags & EF_ARC_OSABI_MSK) + { + case E_ARC_OSABI_ORIG: + strcat (buf, ", (ABI:legacy)"); + break; + case E_ARC_OSABI_V2: + strcat (buf, ", (ABI:v2)"); + break; + /* Only upstream 3.9+ kernels will support ARCv2 ISA. */ + case E_ARC_OSABI_V3: + strcat (buf, ", v3 no-legacy-syscalls ABI"); + break; + default: + strcat (buf, ", unrecognised ARC OSABI flag"); + break; + } +} + static void decode_ARM_machine_flags (unsigned e_flags, char buf[]) { @@ -2768,61 +2941,9 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) break; case EM_ARC_COMPACT2: - switch (e_flags & EF_ARC_MACH_MSK) - { - case EF_ARC_CPU_ARCV2EM: - strcat (buf, ", ARC EM"); - break; - case EF_ARC_CPU_ARCV2HS: - strcat (buf, ", ARC HS"); - break; - default: - strcat (buf, ", unrecognized flag for ARCv2"); - break; - } - switch (e_flags & EF_ARC_OSABI_MSK) - { - /* Only upstream 3.9+ kernels will support ARCv2 - ISA. */ - case E_ARC_OSABI_V3: - strcat (buf, ", v3 no-legacy-syscalls ABI"); - break; - } - break; - case EM_ARC_COMPACT: - switch (e_flags & EF_ARC_MACH_MSK) - { - case E_ARC_MACH_ARC600: - strcat (buf, ", ARC 600"); - break; - case E_ARC_MACH_ARC601: - strcat (buf, ", ARC 601"); - break; - case E_ARC_MACH_ARC700: - strcat (buf, ", ARC 700"); - break; - default: - strcat (buf, ", Generic ARCompact"); - break; - } - switch (e_flags & EF_ARC_OSABI_MSK) - { - case E_ARC_OSABI_ORIG: - strcat (buf, ", legacy syscall ABI"); - break; - case E_ARC_OSABI_V2: - /* For 3.2+ Linux kernels which use asm-generic - hdrs. */ - strcat (buf, ", v2 syscall ABI"); - break; - case E_ARC_OSABI_V3: - /* Upstream 3.9+ kernels which don't use any legacy - syscalls. */ - strcat (buf, ", v3 no-legacy-syscalls ABI"); - break; - } - break; + decode_ARC_machine_flags (e_flags, e_machine, buf); + break; case EM_ARM: decode_ARM_machine_flags (e_flags, buf); @@ -3193,6 +3314,13 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) decode_NDS32_machine_flags (e_flags, buf, sizeof buf); break; + case EM_RISCV: + if (e_flags & EF_RISCV_RVC) + strcat (buf, ", RVC"); + if (e_flags & EF_RISCV_SOFT_FLOAT) + strcat (buf, ", soft-float ABI"); + break; + case EM_SH: switch ((e_flags & EF_SH_MACH_MASK)) { @@ -3376,6 +3504,8 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) if (e_flags & E_FLAG_RX_SINSNS_SET) strcat (buf, e_flags & E_FLAG_RX_SINSNS_YES ? ", uses String instructions" : ", bans String instructions"); + if (e_flags & E_FLAG_RX_V2) + strcat (buf, ", V2"); break; case EM_S390: @@ -3441,6 +3571,8 @@ get_osabi_name (unsigned int osabi) case ELFOSABI_NSK: return "HP - Non-Stop Kernel"; case ELFOSABI_AROS: return "AROS"; case ELFOSABI_FENIXOS: return "FenixOS"; + case ELFOSABI_CLOUDABI: return "Nuxi CloudABI"; + case ELFOSABI_OPENVOS: return "Stratus Technologies OpenVOS"; default: if (osabi >= 64) switch (elf_header.e_machine) @@ -3593,6 +3725,23 @@ get_tic6x_segment_type (unsigned long type) return NULL; } +static const char * +get_solaris_segment_type (unsigned long type) +{ + switch (type) + { + case 0x6464e550: return "PT_SUNW_UNWIND"; + case 0x6474e550: return "PT_SUNW_EH_FRAME"; + case 0x6ffffff7: return "PT_LOSUNW"; + case 0x6ffffffa: return "PT_SUNWBSS"; + case 0x6ffffffb: return "PT_SUNWSTACK"; + case 0x6ffffffc: return "PT_SUNWDTRACE"; + case 0x6ffffffd: return "PT_SUNWCAP"; + case 0x6fffffff: return "PT_HISUNW"; + default: return NULL; + } +} + static const char * get_segment_type (unsigned long p_type) { @@ -3663,7 +3812,10 @@ get_segment_type (unsigned long p_type) result = get_ia64_segment_type (p_type); break; default: - result = NULL; + if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) + result = get_solaris_segment_type (p_type); + else + result = NULL; break; } @@ -3871,6 +4023,7 @@ static const char * get_section_type_name (unsigned int sh_type) { static char buff[32]; + const char * result; switch (sh_type) { @@ -3904,8 +4057,6 @@ get_section_type_name (unsigned int sh_type) default: if ((sh_type >= SHT_LOPROC) && (sh_type <= SHT_HIPROC)) { - const char * result; - switch (elf_header.e_machine) { case EM_MIPS: @@ -3948,26 +4099,27 @@ get_section_type_name (unsigned int sh_type) if (result != NULL) return result; - sprintf (buff, "LOPROC+%x", sh_type - SHT_LOPROC); + sprintf (buff, "LOPROC+%#x", sh_type - SHT_LOPROC); } else if ((sh_type >= SHT_LOOS) && (sh_type <= SHT_HIOS)) { - const char * result; - switch (elf_header.e_machine) { case EM_IA_64: result = get_ia64_section_type_name (sh_type); break; default: - result = NULL; + if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) + result = get_solaris_section_type (sh_type); + else + result = NULL; break; } if (result != NULL) return result; - sprintf (buff, "LOOS+%x", sh_type - SHT_LOOS); + sprintf (buff, "LOOS+%#x", sh_type - SHT_LOOS); } else if ((sh_type >= SHT_LOUSER) && (sh_type <= SHT_HIUSER)) { @@ -3976,12 +4128,17 @@ get_section_type_name (unsigned int sh_type) case EM_V800: case EM_V850: case EM_CYGNUS_V850: - return get_v850_section_type_name (sh_type); + result = get_v850_section_type_name (sh_type); + break; default: + result = NULL; break; } - sprintf (buff, "LOUSER+%x", sh_type - SHT_LOUSER); + if (result != NULL) + return result; + + sprintf (buff, "LOUSER+%#x", sh_type - SHT_LOUSER); } else /* This message is probably going to be displayed in a 15 @@ -4121,10 +4278,13 @@ request_dump_bynumber (unsigned int section, dump_type type) error (_("Out of memory allocating dump request table.\n")); else { - /* Copy current flag settings. */ - memcpy (new_dump_sects, dump_sects, num_dump_sects * sizeof (* dump_sects)); + if (dump_sects) + { + /* Copy current flag settings. */ + memcpy (new_dump_sects, dump_sects, num_dump_sects * sizeof (* dump_sects)); - free (dump_sects); + free (dump_sects); + } dump_sects = new_dump_sects; num_dump_sects = section + 1; @@ -4330,7 +4490,7 @@ parse_args (int argc, char ** argv) default: /* xgettext:c-format */ error (_("Invalid option '-%c'\n"), c); - /* Drop through. */ + /* Fall through. */ case '?': usage (stderr); } @@ -4939,6 +5099,10 @@ get_32bit_section_headers (FILE * file, bfd_boolean probe) internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); internal->sh_entsize = BYTE_GET (shdrs[i].sh_entsize); + if (!probe && internal->sh_link > num) + warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link); + if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num) + warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info); } free (shdrs); @@ -4997,6 +5161,10 @@ get_64bit_section_headers (FILE * file, bfd_boolean probe) internal->sh_info = BYTE_GET (shdrs[i].sh_info); internal->sh_offset = BYTE_GET (shdrs[i].sh_offset); internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign); + if (!probe && internal->sh_link > num) + warn (_("Section %u has an out of range sh_link value of %u\n"), i, internal->sh_link); + if (!probe && internal->sh_flags & SHF_INFO_LINK && internal->sh_info > num) + warn (_("Section %u has an out of range sh_info value of %u\n"), i, internal->sh_info); } free (shdrs); @@ -5271,7 +5439,11 @@ get_elf_section_flags (bfd_vma sh_flags) /* 18 */ { STRING_COMMA_LEN ("EXCLUDE") }, /* SPARC specific. */ /* 19 */ { STRING_COMMA_LEN ("ORDERED") }, - /* 20 */ { STRING_COMMA_LEN ("COMPRESSED") } + /* 20 */ { STRING_COMMA_LEN ("COMPRESSED") }, + /* ARM specific. */ + /* 21 */ { STRING_COMMA_LEN ("ENTRYSECT") }, + /* 22 */ { STRING_COMMA_LEN ("ARM_PURECODE") }, + /* 23 */ { STRING_COMMA_LEN ("COMDEF") } }; if (do_section_details) @@ -5341,6 +5513,17 @@ get_elf_section_flags (bfd_vma sh_flags) if (flag == SHF_ORDERED) sindex = 19; break; + + case EM_ARM: + switch (flag) + { + case SHF_ENTRYSECT: sindex = 21; break; + case SHF_ARM_PURECODE: sindex = 22; break; + case SHF_COMDEF: sindex = 23; break; + default: break; + } + break; + default: break; } @@ -5393,6 +5576,9 @@ get_elf_section_flags (bfd_vma sh_flags) || elf_header.e_machine == EM_K1OM) && flag == SHF_X86_64_LARGE) *p = 'l'; + else if (elf_header.e_machine == EM_ARM + && flag == SHF_ARM_PURECODE) + *p = 'y'; else if (flag & SHF_MASKOS) { *p = 'o'; @@ -5479,6 +5665,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf) if (is_32bit_elf) { Elf32_External_Chdr *echdr = (Elf32_External_Chdr *) buf; + chdr->ch_type = BYTE_GET (echdr->ch_type); chdr->ch_size = BYTE_GET (echdr->ch_size); chdr->ch_addralign = BYTE_GET (echdr->ch_addralign); @@ -5487,6 +5674,7 @@ get_compression_header (Elf_Internal_Chdr *chdr, unsigned char *buf) else { Elf64_External_Chdr *echdr = (Elf64_External_Chdr *) buf; + chdr->ch_type = BYTE_GET (echdr->ch_type); chdr->ch_size = BYTE_GET (echdr->ch_size); chdr->ch_addralign = BYTE_GET (echdr->ch_addralign); @@ -5777,6 +5965,122 @@ process_section_headers (FILE * file) i < elf_header.e_shnum; i++, section++) { + /* Run some sanity checks on the section header. */ + + /* Check the sh_link field. */ + switch (section->sh_type) + { + 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 + || section->sh_link >= elf_header.e_shnum + || (section_headers[section->sh_link].sh_type != SHT_SYMTAB + && section_headers[section->sh_link].sh_type != SHT_DYNSYM)) + warn (_("[%2u]: Link field (%u) should index a symtab section.\n"), + i, section->sh_link); + break; + + case SHT_DYNAMIC: + case SHT_SYMTAB: + case SHT_DYNSYM: + case SHT_GNU_verneed: + case SHT_GNU_verdef: + case SHT_GNU_LIBLIST: + if (section->sh_link < 1 + || section->sh_link >= elf_header.e_shnum + || section_headers[section->sh_link].sh_type != SHT_STRTAB) + warn (_("[%2u]: Link field (%u) should index a string section.\n"), + i, section->sh_link); + break; + + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + case SHT_PREINIT_ARRAY: + if (section->sh_type < SHT_LOOS && section->sh_link != 0) + warn (_("[%2u]: Unexpected value (%u) in link field.\n"), + i, section->sh_link); + break; + + default: + /* FIXME: Add support for target specific section types. */ +#if 0 /* Currently we do not check other section types as there are too + many special cases. Stab sections for example have a type + of SHT_PROGBITS but an sh_link field that links to the .stabstr + section. */ + if (section->sh_type < SHT_LOOS && section->sh_link != 0) + warn (_("[%2u]: Unexpected value (%u) in link field.\n"), + i, section->sh_link); +#endif + break; + } + + /* Check the sh_info field. */ + switch (section->sh_type) + { + case SHT_REL: + case SHT_RELA: + if (section->sh_info < 1 + || section->sh_info >= elf_header.e_shnum + || (section_headers[section->sh_info].sh_type != SHT_PROGBITS + && section_headers[section->sh_info].sh_type != SHT_NOBITS + && section_headers[section->sh_info].sh_type != SHT_NOTE + && section_headers[section->sh_info].sh_type != SHT_INIT_ARRAY + /* FIXME: Are other section types valid ? */ + && 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. No idea why. I would have expected the index + of the .plt section. */ + ; + else + warn (_("[%2u]: Info field (%u) should index a relocatable section.\n"), + i, section->sh_info); + } + break; + + case SHT_DYNAMIC: + case SHT_HASH: + case SHT_SYMTAB_SHNDX: + case SHT_INIT_ARRAY: + case SHT_FINI_ARRAY: + case SHT_PREINIT_ARRAY: + if (section->sh_info != 0) + warn (_("[%2u]: Unexpected value (%u) in info field.\n"), + i, section->sh_info); + break; + + case SHT_GROUP: + case SHT_SYMTAB: + case SHT_DYNSYM: + /* A symbol index - we assume that it is valid. */ + break; + + default: + /* FIXME: Add support for target specific section types. */ + if (section->sh_type == SHT_NOBITS) + /* NOBITS section headers with non-zero sh_info fields can be + created when a binary is stripped of everything but its debug + information. The stripped sections have their headers preserved but their types set to SHT_NOBITS. so do not check this type of section. */ + ; + else if (section->sh_flags & SHF_INFO_LINK) + { + if (section->sh_info < 1 || section->sh_info >= elf_header.e_shnum) + warn (_("[%2u]: Expected link to another section in info field"), i); + } + else if (section->sh_type < SHT_LOOS && section->sh_info != 0) + warn (_("[%2u]: Unexpected value (%u) in info field.\n"), + i, section->sh_info); + break; + } + printf (" [%2u] ", i); if (do_section_details) printf ("%s\n ", printable_section_name (section)); @@ -5943,12 +6247,15 @@ process_section_headers (FILE * file) /* Minimum section size is 12 bytes for 32-bit compression header + 12 bytes for compressed data header. */ unsigned char buf[24]; + assert (sizeof (buf) >= sizeof (Elf64_External_Chdr)); if (get_data (&buf, (FILE *) file, section->sh_offset, 1, sizeof (buf), _("compression header"))) { Elf_Internal_Chdr chdr; - get_compression_header (&chdr, buf); + + (void) get_compression_header (&chdr, buf); + if (chdr.ch_type == ELFCOMPRESS_ZLIB) printf (" ZLIB, "); else @@ -5963,18 +6270,20 @@ process_section_headers (FILE * file) if (!do_section_details) { + /* The ordering of the letters shown here matches the ordering of the + corresponding SHF_xxx values, and hence the order in which these + letters will be displayed to the user. */ + printf (_("Key to Flags:\n\ + W (write), A (alloc), X (execute), M (merge), S (strings), I (info),\n\ + L (link order), O (extra OS processing required), G (group), T (TLS),\n\ + C (compressed), x (unknown), o (OS specific), E (exclude),\n ")); if (elf_header.e_machine == EM_X86_64 || elf_header.e_machine == EM_L1OM || elf_header.e_machine == EM_K1OM) - printf (_("Key to Flags:\n\ - W (write), A (alloc), X (execute), M (merge), S (strings), l (large)\n\ - I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\n\ - O (extra OS processing required) o (OS specific), p (processor specific)\n")); - else - printf (_("Key to Flags:\n\ - W (write), A (alloc), X (execute), M (merge), S (strings)\n\ - I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\n\ - O (extra OS processing required) o (OS specific), p (processor specific)\n")); + printf (_("l (large), ")); + else if (elf_header.e_machine == EM_ARM) + printf (_("y (purecode), ")); + printf ("p (processor specific)\n"); } return 1; @@ -5983,19 +6292,32 @@ process_section_headers (FILE * file) static const char * get_group_flags (unsigned int flags) { - static char buff[32]; - switch (flags) - { - case 0: - return ""; + static char buff[128]; - case GRP_COMDAT: - return "COMDAT "; + if (flags == 0) + return ""; + else if (flags == GRP_COMDAT) + return "COMDAT "; - default: - snprintf (buff, sizeof (buff), _("[: 0x%x] "), flags); - break; + snprintf (buff, 14, _("[0x%x: "), flags); + + flags &= ~ GRP_COMDAT; + if (flags & GRP_MASKOS) + { + strcat (buff, ""); + flags &= ~ GRP_MASKOS; + } + + if (flags & GRP_MASKPROC) + { + strcat (buff, ""); + flags &= ~ GRP_MASKPROC; } + + if (flags) + strcat (buff, ""); + + strcat (buff, "]"); return buff; } @@ -8566,7 +8888,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry) case DT_MIPS_TIME_STAMP: { - char timebuf[20]; + char timebuf[128]; struct tm * tmp; time_t atime = entry->d_un.d_val; @@ -8595,7 +8917,7 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry) case DT_MIPS_DELTA_SYM_NO: case DT_MIPS_DELTA_CLASSSYM_NO: case DT_MIPS_COMPACT_SIZE: - print_vma (entry->d_un.d_ptr, DEC); + print_vma (entry->d_un.d_val, DEC); break; default: @@ -9410,6 +9732,7 @@ process_dynamic_section (FILE * file) case DT_SYMENT : case DT_RELENT : dynamic_info[entry->d_tag] = entry->d_un.d_val; + /* Fall through. */ case DT_PLTPADSZ: case DT_MOVEENT : case DT_MOVESZ : @@ -9889,8 +10212,8 @@ process_version_sections (FILE * file) for (cnt = 0; cnt < total; cnt += 4) { int j, nn; - int check_def, check_need; - char * name; + char *name; + char *invalid = _("*invalid*"); printf (" %03x:", cnt); @@ -9917,20 +10240,8 @@ process_version_sections (FILE * file) break; } - check_def = 1; - check_need = 1; - if (symbols[cnt + j].st_shndx >= elf_header.e_shnum - || section_headers[symbols[cnt + j].st_shndx].sh_type - != SHT_NOBITS) - { - if (symbols[cnt + j].st_shndx == SHN_UNDEF) - check_def = 0; - else - check_need = 0; - } - - if (check_need - && version_info[DT_VERSIONTAGIDX (DT_VERNEED)]) + name = NULL; + if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]) { Elf_Internal_Verneed ivn; unsigned long offset; @@ -9979,14 +10290,9 @@ process_version_sections (FILE * file) ivna.vna_name = BYTE_GET (evna.vna_name); if (ivna.vna_name >= string_sec->sh_size) - name = _("*invalid*"); + name = invalid; else name = strtab + ivna.vna_name; - nn += printf ("(%s%-*s", - name, - 12 - (int) strlen (name), - ")"); - check_def = 0; break; } @@ -9995,7 +10301,7 @@ process_version_sections (FILE * file) while (ivn.vn_next); } - if (check_def && data[cnt + j] != 0x8001 + if (data[cnt + j] != 0x8001 && version_info[DT_VERSIONTAGIDX (DT_VERDEF)]) { Elf_Internal_Verdef ivd; @@ -10043,15 +10349,18 @@ process_version_sections (FILE * file) ivda.vda_name = BYTE_GET (evda.vda_name); if (ivda.vda_name >= string_sec->sh_size) - name = _("*invalid*"); + name = invalid; + else if (name != NULL && name != invalid) + name = _("*both*"); else name = strtab + ivda.vda_name; - nn += printf ("(%s%-*s", - name, - 12 - (int) strlen (name), - ")"); } } + if (name != NULL) + nn += printf ("(%s%-*s", + name, + 12 - (int) strlen (name), + ")"); if (nn < 18) printf ("%*c", 18 - nn, ' '); @@ -10176,6 +10485,18 @@ get_symbol_visibility (unsigned int visibility) } } +static const char * +get_solaris_symbol_visibility (unsigned int visibility) +{ + switch (visibility) + { + case 4: return "EXPORTED"; + case 5: return "SINGLETON"; + case 6: return "ELIMINATE"; + default: return get_symbol_visibility (visibility); + } +} + static const char * get_mips_symbol_other (unsigned int other) { @@ -10299,6 +10620,7 @@ get_symbol_other (unsigned int other) result = get_ppc64_symbol_other (other); break; default: + result = NULL; break; } @@ -10365,8 +10687,9 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size) if (sizeof (size_t) < sizeof (bfd_size_type) && (bfd_size_type) ((size_t) number) != number) { - error (_("Size truncation prevents reading %llu elements of size %u\n"), - (unsigned long long) number, ent_size); + error (_("Size truncation prevents reading %" BFD_VMA_FMT "u" + " elements of size %u\n"), + number, ent_size); return NULL; } @@ -10374,23 +10697,23 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size) attempting to allocate memory when the read is bound to fail. */ if (ent_size * number > current_file_size) { - error (_("Invalid number of dynamic entries: %llu\n"), - (unsigned long long) number); + error (_("Invalid number of dynamic entries: %" BFD_VMA_FMT "u\n"), + number); return NULL; } e_data = (unsigned char *) cmalloc ((size_t) number, ent_size); if (e_data == NULL) { - error (_("Out of memory reading %llu dynamic entries\n"), - (unsigned long long) number); + error (_("Out of memory reading %" BFD_VMA_FMT "u dynamic entries\n"), + number); return NULL; } if (fread (e_data, ent_size, (size_t) number, file) != number) { - error (_("Unable to read in %llu bytes of dynamic data\n"), - (unsigned long long) (number * ent_size)); + error (_("Unable to read in %" BFD_VMA_FMT "u bytes of dynamic data\n"), + number * ent_size); free (e_data); return NULL; } @@ -10398,8 +10721,9 @@ get_dynamic_data (FILE * file, bfd_size_type number, unsigned int ent_size) i_data = (bfd_vma *) cmalloc ((size_t) number, sizeof (*i_data)); if (i_data == NULL) { - error (_("Out of memory allocating space for %llu dynamic entries\n"), - (unsigned long long) number); + error (_("Out of memory allocating space for %" BFD_VMA_FMT "u" + " dynamic entries\n"), + number); free (e_data); return NULL; } @@ -10437,13 +10761,22 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn) printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); - printf (" %-7s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); - /* Check to see if any other bits in the st_other field are set. - Note - displaying this information disrupts the layout of the - table being generated, but for the moment this case is very - rare. */ - if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)) - printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))); + + if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) + printf (" %-7s", get_solaris_symbol_visibility (psym->st_other)); + else + { + unsigned int vis = ELF_ST_VISIBILITY (psym->st_other); + + printf (" %-7s", get_symbol_visibility (vis)); + /* Check to see if any other bits in the st_other field are set. + Note - displaying this information disrupts the layout of the + table being generated, but for the moment this case is very + rare. */ + if (psym->st_other ^ vis) + printf (" [%s] ", get_symbol_other (psym->st_other ^ vis)); + } + printf (" %3.3s ", get_symbol_index_type (psym->st_shndx)); if (VALID_DYNAMIC_NAME (psym->st_name)) print_symbol (25, GET_DYNAMIC_NAME (psym->st_name)); @@ -10453,179 +10786,165 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn) } static const char * -get_symbol_version_string (FILE *file, int is_dynsym, - const char *strtab, - unsigned long int strtab_size, - unsigned int si, Elf_Internal_Sym *psym, - enum versioned_symbol_info *sym_info, - unsigned short *vna_other) +get_symbol_version_string (FILE * file, + bfd_boolean is_dynsym, + const char * strtab, + unsigned long int strtab_size, + unsigned int si, + Elf_Internal_Sym * psym, + enum versioned_symbol_info * sym_info, + unsigned short * vna_other) { - const char *version_string = NULL; + unsigned char data[2]; + unsigned short vers_data; + unsigned long offset; - if (is_dynsym - && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0) - { - unsigned char data[2]; - unsigned short vers_data; - unsigned long offset; - int is_nobits; - int check_def; + if (!is_dynsym + || version_info[DT_VERSIONTAGIDX (DT_VERSYM)] == 0) + return NULL; - offset = offset_from_vma - (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)], - sizeof data + si * sizeof (vers_data)); + offset = offset_from_vma (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)], + sizeof data + si * sizeof (vers_data)); - if (get_data (&data, file, offset + si * sizeof (vers_data), - sizeof (data), 1, _("version data")) == NULL) - return NULL; + if (get_data (&data, file, offset + si * sizeof (vers_data), + sizeof (data), 1, _("version data")) == NULL) + return NULL; - vers_data = byte_get (data, 2); + vers_data = byte_get (data, 2); - is_nobits = (section_headers != NULL - && psym->st_shndx < elf_header.e_shnum - && section_headers[psym->st_shndx].sh_type - == SHT_NOBITS); + if ((vers_data & VERSYM_HIDDEN) == 0 && vers_data <= 1) + return NULL; - check_def = (psym->st_shndx != SHN_UNDEF); + /* 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 + avoid text relocations are defined yet have verneed. We could + use a heuristic to detect the special case, for example, check + for verneed first on symbols defined in SHT_NOBITS sections, but + it is simpler and more reliable to just look for both verdef and + verneed. .dynbss might not be mapped to a SHT_NOBITS section. */ - if ((vers_data & VERSYM_HIDDEN) || vers_data > 1) + if (psym->st_shndx != SHN_UNDEF + && vers_data != 0x8001 + && version_info[DT_VERSIONTAGIDX (DT_VERDEF)]) + { + Elf_Internal_Verdef ivd; + Elf_Internal_Verdaux ivda; + Elf_External_Verdaux evda; + unsigned long off; + + off = offset_from_vma (file, + version_info[DT_VERSIONTAGIDX (DT_VERDEF)], + sizeof (Elf_External_Verdef)); + + do { - if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)] - && (is_nobits || ! check_def)) + Elf_External_Verdef evd; + + if (get_data (&evd, file, off, sizeof (evd), 1, + _("version def")) == NULL) + { + ivd.vd_ndx = 0; + ivd.vd_aux = 0; + ivd.vd_next = 0; + } + else { - Elf_External_Verneed evn; - Elf_Internal_Verneed ivn; - Elf_Internal_Vernaux ivna; + ivd.vd_ndx = BYTE_GET (evd.vd_ndx); + ivd.vd_aux = BYTE_GET (evd.vd_aux); + ivd.vd_next = BYTE_GET (evd.vd_next); + } - /* We must test both. */ - offset = offset_from_vma - (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)], - sizeof evn); + off += ivd.vd_next; + } + while (ivd.vd_ndx != (vers_data & VERSYM_VERSION) && ivd.vd_next != 0); - do - { - unsigned long vna_off; + if (ivd.vd_ndx == (vers_data & VERSYM_VERSION)) + { + off -= ivd.vd_next; + off += ivd.vd_aux; - if (get_data (&evn, file, offset, sizeof (evn), 1, - _("version need")) == NULL) - { - ivna.vna_next = 0; - ivna.vna_other = 0; - ivna.vna_name = 0; - break; - } + if (get_data (&evda, file, off, sizeof (evda), 1, + _("version def aux")) != NULL) + { + ivda.vda_name = BYTE_GET (evda.vda_name); - ivn.vn_aux = BYTE_GET (evn.vn_aux); - ivn.vn_next = BYTE_GET (evn.vn_next); + if (psym->st_name != ivda.vda_name) + { + *sym_info = ((vers_data & VERSYM_HIDDEN) != 0 + ? symbol_hidden : symbol_public); + return (ivda.vda_name < strtab_size + ? strtab + ivda.vda_name : _("")); + } + } + } + } - vna_off = offset + ivn.vn_aux; + if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]) + { + Elf_External_Verneed evn; + Elf_Internal_Verneed ivn; + Elf_Internal_Vernaux ivna; - do - { - Elf_External_Vernaux evna; + offset = offset_from_vma (file, + version_info[DT_VERSIONTAGIDX (DT_VERNEED)], + sizeof evn); + do + { + unsigned long vna_off; - if (get_data (&evna, file, vna_off, - sizeof (evna), 1, - _("version need aux (3)")) == NULL) - { - ivna.vna_next = 0; - ivna.vna_other = 0; - ivna.vna_name = 0; - } - else - { - ivna.vna_other = BYTE_GET (evna.vna_other); - ivna.vna_next = BYTE_GET (evna.vna_next); - ivna.vna_name = BYTE_GET (evna.vna_name); - } + if (get_data (&evn, file, offset, sizeof (evn), 1, + _("version need")) == NULL) + { + ivna.vna_next = 0; + ivna.vna_other = 0; + ivna.vna_name = 0; + break; + } - vna_off += ivna.vna_next; - } - while (ivna.vna_other != vers_data - && ivna.vna_next != 0); + ivn.vn_aux = BYTE_GET (evn.vn_aux); + ivn.vn_next = BYTE_GET (evn.vn_next); - if (ivna.vna_other == vers_data) - break; + vna_off = offset + ivn.vn_aux; - offset += ivn.vn_next; - } - while (ivn.vn_next != 0); + do + { + Elf_External_Vernaux evna; - if (ivna.vna_other == vers_data) + if (get_data (&evna, file, vna_off, sizeof (evna), 1, + _("version need aux (3)")) == NULL) { - *sym_info = symbol_undefined; - *vna_other = ivna.vna_other; - version_string = (ivna.vna_name < strtab_size - ? strtab + ivna.vna_name - : _("")); - check_def = 0; + ivna.vna_next = 0; + ivna.vna_other = 0; + ivna.vna_name = 0; } - else if (! is_nobits) - error (_("bad dynamic symbol\n")); else - check_def = 1; - } - - if (check_def) - { - if (vers_data != 0x8001 - && version_info[DT_VERSIONTAGIDX (DT_VERDEF)]) { - Elf_Internal_Verdef ivd; - Elf_Internal_Verdaux ivda; - Elf_External_Verdaux evda; - unsigned long off; - - off = offset_from_vma - (file, - version_info[DT_VERSIONTAGIDX (DT_VERDEF)], - sizeof (Elf_External_Verdef)); - - do - { - Elf_External_Verdef evd; - - if (get_data (&evd, file, off, sizeof (evd), - 1, _("version def")) == NULL) - { - ivd.vd_ndx = 0; - ivd.vd_aux = 0; - ivd.vd_next = 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); - } - - off += ivd.vd_next; - } - while (ivd.vd_ndx != (vers_data & VERSYM_VERSION) - && ivd.vd_next != 0); + ivna.vna_other = BYTE_GET (evna.vna_other); + ivna.vna_next = BYTE_GET (evna.vna_next); + ivna.vna_name = BYTE_GET (evna.vna_name); + } - off -= ivd.vd_next; - off += ivd.vd_aux; + vna_off += ivna.vna_next; + } + while (ivna.vna_other != vers_data && ivna.vna_next != 0); - if (get_data (&evda, file, off, sizeof (evda), - 1, _("version def aux")) == NULL) - return version_string; + if (ivna.vna_other == vers_data) + break; - ivda.vda_name = BYTE_GET (evda.vda_name); + offset += ivn.vn_next; + } + while (ivn.vn_next != 0); - if (psym->st_name != ivda.vda_name) - { - *sym_info = ((vers_data & VERSYM_HIDDEN) != 0 - ? symbol_hidden : symbol_public); - version_string = (ivda.vda_name < strtab_size - ? strtab + ivda.vda_name - : _("")); - } - } - } + if (ivna.vna_other == vers_data) + { + *sym_info = symbol_undefined; + *vna_other = ivna.vna_other; + return (ivna.vna_name < strtab_size + ? strtab + ivna.vna_name : _("")); } } - return version_string; + return NULL; } /* Dump the symbol table. */ @@ -10938,12 +11257,19 @@ process_symbol_table (FILE * file) print_vma (psym->st_size, DEC_5); printf (" %-7s", get_symbol_type (ELF_ST_TYPE (psym->st_info))); printf (" %-6s", get_symbol_binding (ELF_ST_BIND (psym->st_info))); - printf (" %-7s", get_symbol_visibility (ELF_ST_VISIBILITY (psym->st_other))); - /* Check to see if any other bits in the st_other field are set. - Note - displaying this information disrupts the layout of the - table being generated, but for the moment this case is very rare. */ - if (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other)) - printf (" [%s] ", get_symbol_other (psym->st_other ^ ELF_ST_VISIBILITY (psym->st_other))); + if (elf_header.e_ident[EI_OSABI] == ELFOSABI_SOLARIS) + printf (" %-7s", get_solaris_symbol_visibility (psym->st_other)); + else + { + unsigned int vis = ELF_ST_VISIBILITY (psym->st_other); + + printf (" %-7s", get_symbol_visibility (vis)); + /* Check to see if any other bits in the st_other field are set. + Note - displaying this information disrupts the layout of the + table being generated, but for the moment this case is very rare. */ + if (psym->st_other ^ vis) + printf (" [%s] ", get_symbol_other (psym->st_other ^ vis)); + } printf (" %4s ", get_symbol_index_type (psym->st_shndx)); print_symbol (25, psym->st_name < strtab_size ? strtab + psym->st_name : _("")); @@ -10963,6 +11289,16 @@ process_symbol_table (FILE * file) } putchar ('\n'); + + if (ELF_ST_BIND (psym->st_info) == STB_LOCAL + && si >= section->sh_info + /* Irix 5 and 6 MIPS binaries are known to ignore this requirement. */ + && elf_header.e_machine != EM_MIPS + /* Solaris binaries have been found to violate this requirement as + well. Not sure if this is a bug or an ABI requirement. */ + && elf_header.e_ident[EI_OSABI] != ELFOSABI_SOLARIS) + warn (_("local symbol %u found at index >= %s's sh_info value of %u\n"), + si, printable_section_name (section), section->sh_info); } free (symtab); @@ -11214,6 +11550,7 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, case 10: /* R_MSP430_SYM_DIFF */ if (uses_msp430x_relocs ()) break; + /* Fall through. */ case 21: /* R_MSP430X_SYM_DIFF */ saved_sym = symtab + get_reloc_symindex (reloc->r_info); return TRUE; @@ -11348,6 +11685,7 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, static bfd_boolean is_32bit_abs_reloc (unsigned int reloc_type) { + /* Please keep this table alpha-sorted for ease of visual lookup. */ switch (elf_header.e_machine) { case EM_386: @@ -11361,6 +11699,8 @@ is_32bit_abs_reloc (unsigned int reloc_type) return reloc_type == 2; /* R_960_32. */ case EM_AARCH64: return reloc_type == 258; /* R_AARCH64_ABS32 */ + case EM_ADAPTEVA_EPIPHANY: + return reloc_type == 3; case EM_ALPHA: return reloc_type == 1; /* R_ALPHA_REFLONG. */ case EM_ARC: @@ -11373,8 +11713,6 @@ is_32bit_abs_reloc (unsigned int reloc_type) case EM_AVR_OLD: case EM_AVR: return reloc_type == 1; - case EM_ADAPTEVA_EPIPHANY: - return reloc_type == 3; case EM_BLACKFIN: return reloc_type == 0x12; /* R_byte4_data. */ case EM_CRIS: @@ -11417,6 +11755,9 @@ is_32bit_abs_reloc (unsigned int reloc_type) return reloc_type == 3; /* R_M32C_32. */ case EM_M32R: return reloc_type == 34; /* R_M32R_32_RELA. */ + case EM_68HC11: + case EM_68HC12: + return reloc_type == 6; /* R_M68HC11_32. */ case EM_MCORE: return reloc_type == 1; /* R_MCORE_ADDR32. */ case EM_CYGNUS_MEP: @@ -11460,6 +11801,8 @@ is_32bit_abs_reloc (unsigned int reloc_type) return reloc_type == 1; /* R_PPC64_ADDR32. */ case EM_PPC: return reloc_type == 1; /* R_PPC_ADDR32. */ + case EM_RISCV: + return reloc_type == 1; /* R_RISCV_32. */ case EM_RL78: return reloc_type == 1; /* R_RL78_DIR32. */ case EM_RX: @@ -11530,6 +11873,7 @@ static bfd_boolean is_32bit_pcrel_reloc (unsigned int reloc_type) { switch (elf_header.e_machine) + /* Please keep this table alpha-sorted for ease of visual lookup. */ { case EM_386: case EM_IAMCU: @@ -11542,8 +11886,14 @@ is_32bit_pcrel_reloc (unsigned int reloc_type) return reloc_type == 6; case EM_ALPHA: return reloc_type == 10; /* R_ALPHA_SREL32. */ + case EM_ARC_COMPACT: + case EM_ARC_COMPACT2: + return reloc_type == 49; /* R_ARC_32_PCREL. */ case EM_ARM: return reloc_type == 3; /* R_ARM_REL32 */ + case EM_AVR_OLD: + case EM_AVR: + return reloc_type == 36; /* R_AVR_32_PCREL. */ case EM_MICROBLAZE: return reloc_type == 2; /* R_MICROBLAZE_32_PCREL. */ case EM_OR1K: @@ -11606,6 +11956,8 @@ is_64bit_abs_reloc (unsigned int reloc_type) return reloc_type == 80; /* R_PARISC_DIR64. */ case EM_PPC64: return reloc_type == 38; /* R_PPC64_ADDR64. */ + case EM_RISCV: + return reloc_type == 2; /* R_RISCV_64. */ case EM_SPARC32PLUS: case EM_SPARCV9: case EM_SPARC: @@ -11673,6 +12025,8 @@ is_24bit_abs_reloc (unsigned int reloc_type) case EM_CYGNUS_MN10200: case EM_MN10200: return reloc_type == 4; /* R_MN10200_24. */ + case EM_FT32: + return reloc_type == 5; /* R_FT32_20. */ default: return FALSE; } @@ -11684,17 +12038,18 @@ is_24bit_abs_reloc (unsigned int reloc_type) static bfd_boolean is_16bit_abs_reloc (unsigned int reloc_type) { + /* Please keep this table alpha-sorted for ease of visual lookup. */ switch (elf_header.e_machine) { case EM_ARC: case EM_ARC_COMPACT: case EM_ARC_COMPACT2: return reloc_type == 2; /* R_ARC_16. */ + case EM_ADAPTEVA_EPIPHANY: + return reloc_type == 5; case EM_AVR_OLD: case EM_AVR: return reloc_type == 4; /* R_AVR_16. */ - case EM_ADAPTEVA_EPIPHANY: - return reloc_type == 5; case EM_CYGNUS_D10V: case EM_D10V: return reloc_type == 3; /* R_D10V_16. */ @@ -11708,9 +12063,16 @@ is_16bit_abs_reloc (unsigned int reloc_type) case EM_M32C_OLD: case EM_M32C: return reloc_type == 1; /* R_M32C_16 */ + case EM_CYGNUS_MN10200: + case EM_MN10200: + return reloc_type == 2; /* R_MN10200_16. */ + case EM_CYGNUS_MN10300: + case EM_MN10300: + return reloc_type == 2; /* R_MN10300_16. */ case EM_MSP430: if (uses_msp430x_relocs ()) return reloc_type == 2; /* R_MSP430_ABS16. */ + /* Fall through. */ case EM_MSP430_OLD: return reloc_type == 5; /* R_MSP430_16_BYTE. */ case EM_NDS32: @@ -11723,17 +12085,11 @@ is_16bit_abs_reloc (unsigned int reloc_type) return reloc_type == 2; /* R_OR1K_16. */ case EM_TI_C6000: return reloc_type == 2; /* R_C6000_ABS16. */ + case EM_VISIUM: + return reloc_type == 2; /* R_VISIUM_16. */ case EM_XC16X: case EM_C166: return reloc_type == 2; /* R_XC16C_ABS_16. */ - case EM_CYGNUS_MN10200: - case EM_MN10200: - return reloc_type == 2; /* R_MN10200_16. */ - case EM_CYGNUS_MN10300: - case EM_MN10300: - return reloc_type == 2; /* R_MN10300_16. */ - case EM_VISIUM: - return reloc_type == 2; /* R_VISIUM_16. */ case EM_XGATE: return reloc_type == 3; /* R_XGATE_16. */ default: @@ -11749,44 +12105,54 @@ is_none_reloc (unsigned int reloc_type) { switch (elf_header.e_machine) { - case EM_68K: /* R_68K_NONE. */ case EM_386: /* R_386_NONE. */ - case EM_SPARC32PLUS: - case EM_SPARCV9: - case EM_SPARC: /* R_SPARC_NONE. */ - case EM_MIPS: /* R_MIPS_NONE. */ - case EM_PARISC: /* R_PARISC_NONE. */ - case EM_ALPHA: /* R_ALPHA_NONE. */ + case EM_68K: /* R_68K_NONE. */ case EM_ADAPTEVA_EPIPHANY: - case EM_PPC: /* R_PPC_NONE. */ - case EM_PPC64: /* R_PPC64_NONE. */ + case EM_ALPHA: /* R_ALPHA_NONE. */ + case EM_ALTERA_NIOS2: /* R_NIOS2_NONE. */ case EM_ARC: /* R_ARC_NONE. */ - case EM_ARC_COMPACT: /* R_ARC_NONE. */ case EM_ARC_COMPACT2: /* R_ARC_NONE. */ + case EM_ARC_COMPACT: /* R_ARC_NONE. */ case EM_ARM: /* R_ARM_NONE. */ - case EM_IA_64: /* R_IA64_NONE. */ - case EM_SH: /* R_SH_NONE. */ - case EM_S390_OLD: - case EM_S390: /* R_390_NONE. */ + case EM_C166: /* R_XC16X_NONE. */ case EM_CRIS: /* R_CRIS_NONE. */ - case EM_X86_64: /* R_X86_64_NONE. */ - case EM_L1OM: /* R_X86_64_NONE. */ + case EM_FT32: /* R_FT32_NONE. */ + case EM_IA_64: /* R_IA64_NONE. */ case EM_K1OM: /* R_X86_64_NONE. */ + case EM_L1OM: /* R_X86_64_NONE. */ + case EM_M32R: /* R_M32R_NONE. */ + case EM_MIPS: /* R_MIPS_NONE. */ case EM_MN10300: /* R_MN10300_NONE. */ - case EM_FT32: /* R_FT32_NONE. */ case EM_MOXIE: /* R_MOXIE_NONE. */ - case EM_M32R: /* R_M32R_NONE. */ - case EM_TI_C6000:/* R_C6000_NONE. */ + case EM_NIOS32: /* R_NIOS_NONE. */ + case EM_OR1K: /* R_OR1K_NONE. */ + case EM_PARISC: /* R_PARISC_NONE. */ + case EM_PPC64: /* R_PPC64_NONE. */ + case EM_PPC: /* R_PPC_NONE. */ + case EM_RISCV: /* R_RISCV_NONE. */ + case EM_S390: /* R_390_NONE. */ + case EM_S390_OLD: + case EM_SH: /* R_SH_NONE. */ + case EM_SPARC32PLUS: + case EM_SPARC: /* R_SPARC_NONE. */ + case EM_SPARCV9: case EM_TILEGX: /* R_TILEGX_NONE. */ case EM_TILEPRO: /* R_TILEPRO_NONE. */ + case EM_TI_C6000:/* R_C6000_NONE. */ + case EM_X86_64: /* R_X86_64_NONE. */ case EM_XC16X: - case EM_C166: /* R_XC16X_NONE. */ - case EM_ALTERA_NIOS2: /* R_NIOS2_NONE. */ - case EM_NIOS32: /* R_NIOS_NONE. */ - case EM_OR1K: /* R_OR1K_NONE. */ return reloc_type == 0; + case EM_AARCH64: return reloc_type == 0 || reloc_type == 256; + case EM_AVR_OLD: + case EM_AVR: + return (reloc_type == 0 /* R_AVR_NONE. */ + || reloc_type == 30 /* R_AVR_DIFF8. */ + || reloc_type == 31 /* R_AVR_DIFF16. */ + || reloc_type == 32 /* R_AVR_DIFF32. */); + case EM_METAG: + return reloc_type == 3; /* R_METAG_NONE. */ case EM_NDS32: return (reloc_type == 0 /* R_XTENSA_NONE. */ || reloc_type == 204 /* R_NDS32_DIFF8. */ @@ -11799,8 +12165,6 @@ is_none_reloc (unsigned int reloc_type) || reloc_type == 17 /* R_XTENSA_DIFF8. */ || reloc_type == 18 /* R_XTENSA_DIFF16. */ || reloc_type == 19 /* R_XTENSA_DIFF32. */); - case EM_METAG: - return reloc_type == 3; /* R_METAG_NONE. */ } return FALSE; } @@ -11838,7 +12202,7 @@ apply_relocations (void * file, const Elf_Internal_Shdr * section, unsigned char * start, bfd_size_type size, - void ** relocs_return, + void ** relocs_return, unsigned long * num_relocs_return) { Elf_Internal_Shdr * relsec; @@ -11894,6 +12258,9 @@ apply_relocations (void * file, is_rela = FALSE; symsec = section_headers + relsec->sh_link; + if (symsec->sh_type != SHT_SYMTAB + && symsec->sh_type != SHT_DYNSYM) + return; symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec, & num_syms); for (rp = relocs; rp < relocs + num_relocs; ++rp) @@ -11962,6 +12329,7 @@ apply_relocations (void * file, referencing a global array. For an example of this see the _clz.o binary in libgcc.a. */ if (sym != symtab + && ELF_ST_TYPE (sym->st_info) != STT_COMMON && ELF_ST_TYPE (sym->st_info) > STT_SECTION) { warn (_("skipping unexpected symbol type %s in %ld'th relocation in section %s\n"), @@ -12405,8 +12773,19 @@ load_specific_debug_section (enum dwarf_section_display_enum debug, if ((sec->sh_flags & SHF_COMPRESSED) != 0) { Elf_Internal_Chdr chdr; - unsigned int compression_header_size - = get_compression_header (&chdr, start); + unsigned int compression_header_size; + + if (size < (is_32bit_elf + ? sizeof (Elf32_External_Chdr) + : sizeof (Elf64_External_Chdr))) + { + warn (_("compressed section %s is too small to contain a compression header"), + section->name); + return 0; + } + + compression_header_size = get_compression_header (&chdr, start); + if (chdr.ch_type != ELFCOMPRESS_ZLIB) { warn (_("section '%s' has unsupported compress type: %d\n"), @@ -12744,16 +13123,18 @@ 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"}; + "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8", "", "v8-M.baseline", + "v8-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"}; + {"No", "Thumb-1", "Thumb-2", "Yes"}; static const char * arm_attr_tag_FP_arch[] = {"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", "VFPv4-D16", "FP for ARMv8", "FPv5/FP-D16 for ARMv8"}; static const char * arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1", "WMMXv2"}; static const char * arm_attr_tag_Advanced_SIMD_arch[] = - {"No", "NEONv1", "NEONv1 with Fused-MAC", "NEON for ARMv8"}; + {"No", "NEONv1", "NEONv1 with Fused-MAC", "NEON for ARMv8", + "NEON for ARMv8.1"}; static const char * arm_attr_tag_PCS_config[] = {"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004", "PalmOS (reserved)", "SymbianOS 2004", "SymbianOS (reserved)"}; @@ -12793,6 +13174,8 @@ static const char * arm_attr_tag_FP_HP_extension[] = {"Not Allowed", "Allowed"}; static const char * arm_attr_tag_ABI_FP_16bit_format[] = {"None", "IEEE 754", "Alternative Format"}; +static const char * arm_attr_tag_DSP_extension[] = + {"Follow architecture", "Allowed"}; static const char * arm_attr_tag_MPextension_use[] = {"Not Allowed", "Allowed"}; static const char * arm_attr_tag_DIV_use[] = @@ -12843,6 +13226,7 @@ static arm_attr_public_tag arm_attr_public_tags[] = LOOKUP(38, ABI_FP_16bit_format), LOOKUP(42, MPextension_use), LOOKUP(44, DIV_use), + LOOKUP(46, DSP_extension), {64, "nodefaults", 0, NULL}, {65, "also_compatible_with", 0, NULL}, LOOKUP(66, T2EE_use), @@ -13064,47 +13448,77 @@ display_power_gnu_attribute (unsigned char * p, const unsigned char * const end) { unsigned int len; - int val; + unsigned int val; if (tag == Tag_GNU_Power_ABI_FP) { val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Power_ABI_FP: "); + if (len == 0) + { + printf (_("\n")); + return p; + } - switch (val) + if (val > 15) + printf ("(%#x), ", val); + + switch (val & 3) { case 0: - printf (_("Hard or soft float\n")); + printf (_("unspecified hard/soft float, ")); break; case 1: - printf (_("Hard float\n")); + printf (_("hard float, ")); break; case 2: - printf (_("Soft float\n")); + printf (_("soft float, ")); break; case 3: - printf (_("Single-precision hard float\n")); + printf (_("single-precision hard float, ")); break; - default: - printf ("??? (%d)\n", val); + } + + switch (val & 0xC) + { + case 0: + printf (_("unspecified long double\n")); + break; + case 4: + printf (_("128-bit IBM long double\n")); + break; + case 8: + printf (_("64-bit long double\n")); + break; + case 12: + printf (_("128-bit IEEE long double\n")); break; } return p; - } + } if (tag == Tag_GNU_Power_ABI_Vector) { val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Power_ABI_Vector: "); - switch (val) + if (len == 0) + { + printf (_("\n")); + return p; + } + + if (val > 3) + printf ("(%#x), ", val); + + switch (val & 3) { case 0: - printf (_("Any\n")); + printf (_("unspecified\n")); break; case 1: - printf (_("Generic\n")); + printf (_("generic\n")); break; case 2: printf ("AltiVec\n"); @@ -13112,39 +13526,39 @@ display_power_gnu_attribute (unsigned char * p, case 3: printf ("SPE\n"); break; - default: - printf ("??? (%d)\n", val); - break; } return p; - } + } if (tag == Tag_GNU_Power_ABI_Struct_Return) { - if (p == end) + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_GNU_Power_ABI_Struct_Return: "); + if (len == 0) { - warn (_("corrupt Tag_GNU_Power_ABI_Struct_Return\n")); + printf (_("\n")); return p; } - val = read_uleb128 (p, &len, end); - p += len; - printf (" Tag_GNU_Power_ABI_Struct_Return: "); - switch (val) - { - case 0: - printf (_("Any\n")); - break; - case 1: - printf ("r3/r4\n"); - break; - case 2: - printf (_("Memory\n")); - break; - default: - printf ("??? (%d)\n", val); - break; - } + if (val > 2) + printf ("(%#x), ", val); + + switch (val & 3) + { + case 0: + printf (_("unspecified\n")); + break; + case 1: + printf ("r3/r4\n"); + break; + case 2: + printf (_("memory\n")); + break; + case 3: + printf ("???\n"); + break; + } return p; } @@ -13893,6 +14307,7 @@ process_attributes (FILE * file, goto do_numlist; case 3: printf (_("Symbol Attributes:")); + /* Fall through. */ do_numlist: for (;;) { @@ -14055,6 +14470,8 @@ print_mips_ases (unsigned int mask) fputs ("\n\tDSP ASE", stdout); if (mask & AFL_ASE_DSPR2) fputs ("\n\tDSP R2 ASE", stdout); + if (mask & AFL_ASE_DSPR3) + fputs ("\n\tDSP R3 ASE", stdout); if (mask & AFL_ASE_EVA) fputs ("\n\tEnhanced VA Scheme", stdout); if (mask & AFL_ASE_MCU) @@ -14314,7 +14731,7 @@ process_mips_specific (FILE * file) { Elf32_Lib liblist; time_t atime; - char timebuf[20]; + char timebuf[128]; struct tm * tmp; liblist.l_name = BYTE_GET (elib[cnt].l_name); @@ -14401,7 +14818,7 @@ process_mips_specific (FILE * file) cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (* iopt)); if (iopt == NULL) { - error (_("Out of memory allocatinf space for MIPS options\n")); + error (_("Out of memory allocating space for MIPS options\n")); return 0; } @@ -14968,7 +15385,7 @@ process_gnu_liblist (FILE * file) { Elf32_Lib liblist; time_t atime; - char timebuf[20]; + char timebuf[128]; struct tm * tmp; liblist.l_name = BYTE_GET (elib[cnt].l_name); @@ -15185,8 +15602,7 @@ print_core_note (Elf_Internal_Note *pnote) static const char * get_gnu_elf_note_type (unsigned e_type) { - static char buff[64]; - + /* NB/ Keep this switch statement in sync with print_gnu_note (). */ switch (e_type) { case NT_GNU_ABI_TAG: @@ -15198,16 +15614,19 @@ get_gnu_elf_note_type (unsigned e_type) case NT_GNU_GOLD_VERSION: return _("NT_GNU_GOLD_VERSION (gold version)"); default: - break; - } + { + static char buff[64]; - snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); - return buff; + snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type); + return buff; + } + } } static int print_gnu_note (Elf_Internal_Note *pnote) { + /* NB/ Keep this switch statement in sync with get_gnu_elf_note_type (). */ switch (pnote->type) { case NT_GNU_BUILD_ID: @@ -15281,6 +15700,42 @@ print_gnu_note (Elf_Internal_Note *pnote) printf ("\n"); } break; + + case NT_GNU_HWCAP: + { + unsigned long num_entries, mask; + + /* Hardware capabilities information. Word 0 is the number of entries. + Word 1 is a bitmask of enabled entries. The rest of the descriptor + is a series of entries, where each entry is a single byte followed + by a nul terminated string. The byte gives the bit number to test + if enabled in the bitmask. */ + printf (_(" Hardware Capabilities: ")); + if (pnote->descsz < 8) + { + printf (_("\n")); + break; + } + num_entries = byte_get ((unsigned char *) pnote->descdata, 4); + mask = byte_get ((unsigned char *) pnote->descdata + 4, 4); + printf (_("num entries: %ld, enabled mask: %lx\n"), num_entries, mask); + /* FIXME: Add code to display the entries... */ + } + 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 + display the data. */ + { + unsigned long i; + + printf (_(" Description data: ")); + for (i = 0; i < pnote->descsz; ++i) + printf ("%02x ", pnote->descdata[i] & 0xff); + printf ("\n"); + } + break; } return 1; @@ -15365,7 +15820,7 @@ print_v850_note (Elf_Internal_Note * pnote) return 0; } -static int +static int process_netbsd_elf_note (Elf_Internal_Note * pnote) { unsigned int version; @@ -15378,11 +15833,11 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote) printf (" NetBSD\t\t0x%08lx\tIDENT %u (%u.%u%s%c)\n", pnote->descsz, version, version / 100000000, (version / 1000000) % 100, (version / 10000) % 100 > 26 ? "Z" : "", - 'A' + (version / 10000) % 26); + 'A' + (version / 10000) % 26); else printf (" NetBSD\t\t0x%08lx\tIDENT %u (%u.%u.%u)\n", pnote->descsz, version, version / 100000000, (version / 1000000) % 100, - (version / 100) % 100); + (version / 100) % 100); return 1; case NT_NETBSD_MARCH: @@ -15399,6 +15854,35 @@ process_netbsd_elf_note (Elf_Internal_Note * pnote) return 1; } +static const char * +get_freebsd_elfcore_note_type (unsigned e_type) +{ + switch (e_type) + { + case NT_FREEBSD_THRMISC: + return _("NT_THRMISC (thrmisc structure)"); + case NT_FREEBSD_PROCSTAT_PROC: + return _("NT_PROCSTAT_PROC (proc data)"); + case NT_FREEBSD_PROCSTAT_FILES: + return _("NT_PROCSTAT_FILES (files data)"); + case NT_FREEBSD_PROCSTAT_VMMAP: + return _("NT_PROCSTAT_VMMAP (vmmap data)"); + case NT_FREEBSD_PROCSTAT_GROUPS: + return _("NT_PROCSTAT_GROUPS (groups data)"); + case NT_FREEBSD_PROCSTAT_UMASK: + return _("NT_PROCSTAT_UMASK (umask data)"); + case NT_FREEBSD_PROCSTAT_RLIMIT: + return _("NT_PROCSTAT_RLIMIT (rlimit data)"); + case NT_FREEBSD_PROCSTAT_OSREL: + return _("NT_PROCSTAT_OSREL (osreldate data)"); + case NT_FREEBSD_PROCSTAT_PSSTRINGS: + return _("NT_PROCSTAT_PSSTRINGS (ps_strings data)"); + case NT_FREEBSD_PROCSTAT_AUXV: + return _("NT_PROCSTAT_AUXV (auxv data)"); + } + return get_note_type (e_type); +} + static const char * get_netbsd_elfcore_note_type (unsigned e_type) { @@ -15634,7 +16118,9 @@ print_ia64_vms_note (Elf_Internal_Note * pnote) If the value of namesz is zero, there is no name present. */ static int -process_note (Elf_Internal_Note * pnote) +process_note (Elf_Internal_Note * pnote, + FILE * file ATTRIBUTE_UNUSED, + Elf_Internal_Shdr * section ATTRIBUTE_UNUSED) { const char * name = pnote->namesz ? pnote->namedata : "(NONE)"; const char * nt; @@ -15648,6 +16134,10 @@ process_note (Elf_Internal_Note * pnote) /* GNU-specific object file notes. */ nt = get_gnu_elf_note_type (pnote->type); + else if (const_strneq (pnote->namedata, "FreeBSD")) + /* FreeBSD-specific core file notes. */ + nt = get_freebsd_elfcore_note_type (pnote->type); + else if (const_strneq (pnote->namedata, "NetBSD-CORE")) /* NetBSD-specific core file notes. */ nt = get_netbsd_elfcore_note_type (pnote->type); @@ -15675,7 +16165,9 @@ process_note (Elf_Internal_Note * pnote) note type strings. */ nt = get_note_type (pnote->type); - printf (" %-20s 0x%08lx\t%s\n", name, pnote->descsz, nt); + printf (" "); + print_symbol (-20, name); + printf (" 0x%08lx\t%s\n", pnote->descsz, nt); if (const_strneq (pnote->namedata, "IPF/VMS")) return print_ia64_vms_note (pnote); @@ -15685,13 +16177,25 @@ process_note (Elf_Internal_Note * pnote) return print_stapsdt_note (pnote); else if (const_strneq (pnote->namedata, "CORE")) return print_core_note (pnote); - else - return 1; -} + else if (pnote->descsz) + { + unsigned long i; + + printf (_(" description data: ")); + for (i = 0; i < pnote->descsz; i++) + printf ("%02x ", pnote->descdata[i]); + printf ("\n"); + } + + return 1; +} static int -process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length) +process_notes_at (FILE * file, + Elf_Internal_Shdr * section, + bfd_vma offset, + bfd_vma length) { Elf_External_Note * pnotes; Elf_External_Note * external; @@ -15701,15 +16205,26 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length) if (length <= 0) return 0; - pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length, - _("notes")); + if (section) + { + pnotes = (Elf_External_Note *) get_section_contents (section, file); + if (pnotes) + apply_relocations (file, section, (unsigned char *) pnotes, length, NULL, NULL); + } + else + pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length, + _("notes")); if (pnotes == NULL) return 0; external = pnotes; - printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"), - (unsigned long) offset, (unsigned long) length); + if (section) + printf (_("\nDisplaying notes found in: %s\n"), printable_section_name (section)); + else + printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"), + (unsigned long) offset, (unsigned long) length); + printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size")); end = (char *) pnotes + length; @@ -15809,7 +16324,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length) inote.namedata = temp; } - res &= process_note (& inote); + res &= process_note (& inote, file, section); if (temp != NULL) { @@ -15838,9 +16353,9 @@ process_corefile_note_segments (FILE * file) i++, segment++) { if (segment->p_type == PT_NOTE) - res &= process_corefile_note_segment (file, - (bfd_vma) segment->p_offset, - (bfd_vma) segment->p_filesz); + res &= process_notes_at (file, NULL, + (bfd_vma) segment->p_offset, + (bfd_vma) segment->p_filesz); } return res; @@ -15941,9 +16456,9 @@ process_note_sections (FILE * file) { if (section->sh_type == SHT_NOTE) { - res &= process_corefile_note_segment (file, - (bfd_vma) section->sh_offset, - (bfd_vma) section->sh_size); + res &= process_notes_at (file, section, + (bfd_vma) section->sh_offset, + (bfd_vma) section->sh_size); n++; } @@ -16002,6 +16517,7 @@ process_arch_specific (FILE * file) return process_nds32_specific (file); break; case EM_PPC: + case EM_PPC64: return process_power_specific (file); break; case EM_S390: @@ -16034,8 +16550,8 @@ get_file_header (FILE * file) /* Determine how to read the rest of the header. */ switch (elf_header.e_ident[EI_DATA]) { - default: /* fall through */ - case ELFDATANONE: /* fall through */ + default: + case ELFDATANONE: case ELFDATA2LSB: byte_get = byte_get_little_endian; byte_put = byte_put_little_endian;