From 5e8c1cf25beccac1d22d10dc866912394f42771b Mon Sep 17 00:00:00 2001 From: Andrew Hsieh Date: Tue, 9 Dec 2014 17:57:18 +0800 Subject: [2.25] sync to a30720e3e633f275250e26f85ccae5dbdddfb6c6 local patches will be re-applied later commit a30720e3e633f275250e26f85ccae5dbdddfb6c6 Author: Alan Modra Date: Wed Nov 19 10:30:16 2014 +1030 daily update Change-Id: Ieb2a3f4dd2ecb289ac5305ff08d428b2847494ab --- binutils-2.25/binutils/readelf.c | 1744 ++++++++++++++++++++++++++++++-------- 1 file changed, 1384 insertions(+), 360 deletions(-) (limited to 'binutils-2.25/binutils/readelf.c') diff --git a/binutils-2.25/binutils/readelf.c b/binutils-2.25/binutils/readelf.c index 79201006..0c00b2f9 100644 --- a/binutils-2.25/binutils/readelf.c +++ b/binutils-2.25/binutils/readelf.c @@ -1,5 +1,5 @@ /* readelf.c -- display contents of an ELF format file - Copyright 1998-2013 Free Software Foundation, Inc. + Copyright (C) 1998-2014 Free Software Foundation, Inc. Originally developed by Eric Youngdale Modifications by Nick Clifton @@ -131,8 +131,9 @@ #include "elf/moxie.h" #include "elf/mt.h" #include "elf/msp430.h" +#include "elf/nds32.h" #include "elf/nios2.h" -#include "elf/or32.h" +#include "elf/or1k.h" #include "elf/pj.h" #include "elf/ppc.h" #include "elf/ppc64.h" @@ -166,9 +167,10 @@ char * program_name = "readelf"; static long archive_file_offset; static unsigned long archive_file_size; +static bfd_size_type current_file_size; static unsigned long dynamic_addr; static bfd_size_type dynamic_size; -static unsigned int dynamic_nent; +static size_t dynamic_nent; static char * dynamic_strings; static unsigned long dynamic_strings_length; static char * string_table; @@ -314,8 +316,19 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb, if (fseek (file, archive_file_offset + offset, SEEK_SET)) { - error (_("Unable to seek to 0x%lx for %s\n"), - (unsigned long) archive_file_offset + offset, reason); + if (reason) + error (_("Unable to seek to 0x%lx for %s\n"), + (unsigned long) archive_file_offset + offset, reason); + return NULL; + } + + /* Be kind to memory chekers (eg valgrind, address sanitizer) by not + attempting to allocate memory when the read is bound to fail. */ + if (offset + archive_file_offset + size * nmemb > current_file_size) + { + if (reason) + error (_("Reading 0x%lx bytes extends past end of file for %s\n"), + (unsigned long) (size * nmemb), reason); return NULL; } @@ -329,8 +342,9 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb, if (mvar == NULL) { - error (_("Out of memory allocating 0x%lx bytes for %s\n"), - (unsigned long)(size * nmemb), reason); + if (reason) + error (_("Out of memory allocating 0x%lx bytes for %s\n"), + (unsigned long)(size * nmemb), reason); return NULL; } @@ -339,8 +353,9 @@ get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb, if (fread (mvar, size, nmemb, file) != nmemb) { - error (_("Unable to read in 0x%lx bytes of %s\n"), - (unsigned long)(size * nmemb), reason); + if (reason) + error (_("Unable to read in 0x%lx bytes of %s\n"), + (unsigned long)(size * nmemb), reason); if (mvar != var) free (mvar); return NULL; @@ -417,6 +432,7 @@ print_symbol (int width, const char *symbol) width = - width; extra_padding = TRUE; } + assert (width != 0); if (do_wide) /* Set the remaining width to a very large value. @@ -489,6 +505,66 @@ print_symbol (int width, const char *symbol) return num_printed; } +/* 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. */ + +static const char * +printable_section_name (Elf_Internal_Shdr * sec) +{ +#define MAX_PRINT_SEC_NAME_LEN 128 + static char sec_name_buf [MAX_PRINT_SEC_NAME_LEN + 1]; + const char * name = SECTION_NAME (sec); + char * buf = sec_name_buf; + char c; + unsigned int remaining = MAX_PRINT_SEC_NAME_LEN; + + while ((c = * name ++) != 0) + { + if (ISCNTRL (c)) + { + if (remaining < 2) + break; + + * buf ++ = '^'; + * buf ++ = c + 0x40; + remaining -= 2; + } + else if (ISPRINT (c)) + { + * buf ++ = c; + remaining -= 1; + } + else + { + static char hex[17] = "0123456789ABCDEF"; + + if (remaining < 4) + break; + * buf ++ = '<'; + * buf ++ = hex[(c & 0xf0) >> 4]; + * buf ++ = hex[c & 0x0f]; + * buf ++ = '>'; + remaining -= 4; + } + + if (remaining == 0) + break; + } + + * buf = 0; + return sec_name_buf; +} + +static const char * +printable_section_name_from_index (unsigned long ndx) +{ + if (ndx >= elf_header.e_shnum) + return _(""); + + return printable_section_name (section_headers + ndx); +} + /* Return a pointer to section NAME, or NULL if no such section exists. */ static Elf_Internal_Shdr * @@ -521,6 +597,21 @@ find_section_by_address (bfd_vma addr) return NULL; } +static Elf_Internal_Shdr * +find_section_by_type (unsigned int type) +{ + unsigned int i; + + for (i = 0; i < elf_header.e_shnum; i++) + { + Elf_Internal_Shdr *sec = section_headers + i; + if (sec->sh_type == type) + return sec; + } + + return NULL; +} + /* Return a pointer to section NAME, or NULL if no such section exists, restricted to the list of sections given in SET. */ @@ -579,8 +670,6 @@ guess_is_rela (unsigned int e_machine) case EM_MIPS: case EM_MIPS_RS3_LE: case EM_CYGNUS_M32R: - case EM_OPENRISC: - case EM_OR32: case EM_SCORE: case EM_XGATE: return FALSE; @@ -626,7 +715,9 @@ guess_is_rela (unsigned int e_machine) case EM_MSP430: case EM_MSP430_OLD: case EM_MT: + case EM_NDS32: case EM_NIOS32: + case EM_OR1K: case EM_PPC64: case EM_PPC: case EM_RL78: @@ -686,7 +777,7 @@ slurp_rela_relocs (FILE * file, unsigned long * nrelasp) { Elf_Internal_Rela * relas; - unsigned long nrelas; + size_t nrelas; unsigned int i; if (is_32bit_elf) @@ -784,7 +875,7 @@ slurp_rel_relocs (FILE * file, unsigned long * nrelsp) { Elf_Internal_Rela * rels; - unsigned long nrels; + size_t nrels; unsigned int i; if (is_32bit_elf) @@ -1144,6 +1235,10 @@ dump_relocations (FILE * file, rtype = elf_msp430_reloc_type (type); break; + case EM_NDS32: + rtype = elf_nds32_reloc_type (type); + break; + case EM_PPC: rtype = elf_ppc_reloc_type (type); break; @@ -1179,9 +1274,8 @@ dump_relocations (FILE * file, rtype = elf_h8_reloc_type (type); break; - case EM_OPENRISC: - case EM_OR32: - rtype = elf_or32_reloc_type (type); + case EM_OR1K: + rtype = elf_or1k_reloc_type (type); break; case EM_PJ: @@ -1400,8 +1494,7 @@ dump_relocations (FILE * file, if (ELF_ST_TYPE (psym->st_info) == STT_SECTION) { if (psym->st_shndx < elf_header.e_shnum) - sec_name - = SECTION_NAME (section_headers + psym->st_shndx); + sec_name = SECTION_NAME (section_headers + psym->st_shndx); else if (psym->st_shndx == SHN_ABS) sec_name = "ABS"; else if (psym->st_shndx == SHN_COMMON) @@ -1575,7 +1668,7 @@ get_ppc_dynamic_type (unsigned long type) switch (type) { case DT_PPC_GOT: return "PPC_GOT"; - case DT_PPC_TLSOPT: return "PPC_TLSOPT"; + case DT_PPC_OPT: return "PPC_OPT"; default: return NULL; } @@ -1589,7 +1682,7 @@ get_ppc64_dynamic_type (unsigned long type) case DT_PPC64_GLINK: return "PPC64_GLINK"; case DT_PPC64_OPD: return "PPC64_OPD"; case DT_PPC64_OPDSZ: return "PPC64_OPDSZ"; - case DT_PPC64_TLSOPT: return "PPC64_TLSOPT"; + case DT_PPC64_OPT: return "PPC64_OPT"; default: return NULL; } @@ -2008,8 +2101,7 @@ get_machine_name (unsigned e_machine) case EM_S390: return "IBM S/390"; case EM_SCORE: return "SUNPLUS S+Core"; case EM_XSTORMY16: return "Sanyo XStormy16 CPU core"; - case EM_OPENRISC: - case EM_OR32: return "OpenRISC"; + case EM_OR1K: return "OpenRISC 1000"; case EM_ARC_A5: return "ARC International ARCompact processor"; case EM_CRX: return "National Semiconductor CRX microprocessor"; case EM_ADAPTEVA_EPIPHANY: return "Adapteva EPIPHANY"; @@ -2307,6 +2399,209 @@ decode_ARM_machine_flags (unsigned e_flags, char buf[]) strcat (buf,_(", ")); } +static void +decode_NDS32_machine_flags (unsigned e_flags, char buf[], size_t size) +{ + unsigned abi; + unsigned arch; + unsigned config; + unsigned version; + int has_fpu = 0; + int r = 0; + + static const char *ABI_STRINGS[] = + { + "ABI v0", /* use r5 as return register; only used in N1213HC */ + "ABI v1", /* use r0 as return register */ + "ABI v2", /* use r0 as return register and don't reserve 24 bytes for arguments */ + "ABI v2fp", /* for FPU */ + "AABI", + "ABI2 FP+" + }; + static const char *VER_STRINGS[] = + { + "Andes ELF V1.3 or older", + "Andes ELF V1.3.1", + "Andes ELF V1.4" + }; + static const char *ARCH_STRINGS[] = + { + "", + "Andes Star v1.0", + "Andes Star v2.0", + "Andes Star v3.0", + "Andes Star v3.0m" + }; + + abi = EF_NDS_ABI & e_flags; + arch = EF_NDS_ARCH & e_flags; + config = EF_NDS_INST & e_flags; + version = EF_NDS32_ELF_VERSION & e_flags; + + memset (buf, 0, size); + + switch (abi) + { + case E_NDS_ABI_V0: + case E_NDS_ABI_V1: + case E_NDS_ABI_V2: + case E_NDS_ABI_V2FP: + case E_NDS_ABI_AABI: + case E_NDS_ABI_V2FP_PLUS: + /* In case there are holes in the array. */ + r += snprintf (buf + r, size - r, ", %s", ABI_STRINGS[abi >> EF_NDS_ABI_SHIFT]); + break; + + default: + r += snprintf (buf + r, size - r, ", "); + break; + } + + switch (version) + { + case E_NDS32_ELF_VER_1_2: + case E_NDS32_ELF_VER_1_3: + case E_NDS32_ELF_VER_1_4: + r += snprintf (buf + r, size - r, ", %s", VER_STRINGS[version >> EF_NDS32_ELF_VERSION_SHIFT]); + break; + + default: + r += snprintf (buf + r, size - r, ", "); + break; + } + + if (E_NDS_ABI_V0 == abi) + { + /* OLD ABI; only used in N1213HC, has performance extension 1. */ + r += snprintf (buf + r, size - r, ", Andes Star v1.0, N1213HC, MAC, PERF1"); + if (arch == E_NDS_ARCH_STAR_V1_0) + r += snprintf (buf + r, size -r, ", 16b"); /* has 16-bit instructions */ + return; + } + + switch (arch) + { + case E_NDS_ARCH_STAR_V1_0: + case E_NDS_ARCH_STAR_V2_0: + case E_NDS_ARCH_STAR_V3_0: + case E_NDS_ARCH_STAR_V3_M: + r += snprintf (buf + r, size - r, ", %s", ARCH_STRINGS[arch >> EF_NDS_ARCH_SHIFT]); + break; + + default: + r += snprintf (buf + r, size - r, ", "); + /* ARCH version determines how the e_flags are interpreted. + If it is unknown, we cannot proceed. */ + return; + } + + /* Newer ABI; Now handle architecture specific flags. */ + if (arch == E_NDS_ARCH_STAR_V1_0) + { + if (config & E_NDS32_HAS_MFUSR_PC_INST) + r += snprintf (buf + r, size -r, ", MFUSR_PC"); + + if (!(config & E_NDS32_HAS_NO_MAC_INST)) + r += snprintf (buf + r, size -r, ", MAC"); + + if (config & E_NDS32_HAS_DIV_INST) + r += snprintf (buf + r, size -r, ", DIV"); + + if (config & E_NDS32_HAS_16BIT_INST) + r += snprintf (buf + r, size -r, ", 16b"); + } + else + { + if (config & E_NDS32_HAS_MFUSR_PC_INST) + { + if (version <= E_NDS32_ELF_VER_1_3) + r += snprintf (buf + r, size -r, ", [B8]"); + else + r += snprintf (buf + r, size -r, ", EX9"); + } + + if (config & E_NDS32_HAS_MAC_DX_INST) + r += snprintf (buf + r, size -r, ", MAC_DX"); + + if (config & E_NDS32_HAS_DIV_DX_INST) + r += snprintf (buf + r, size -r, ", DIV_DX"); + + if (config & E_NDS32_HAS_16BIT_INST) + { + if (version <= E_NDS32_ELF_VER_1_3) + r += snprintf (buf + r, size -r, ", 16b"); + else + r += snprintf (buf + r, size -r, ", IFC"); + } + } + + if (config & E_NDS32_HAS_EXT_INST) + r += snprintf (buf + r, size -r, ", PERF1"); + + if (config & E_NDS32_HAS_EXT2_INST) + r += snprintf (buf + r, size -r, ", PERF2"); + + if (config & E_NDS32_HAS_FPU_INST) + { + has_fpu = 1; + r += snprintf (buf + r, size -r, ", FPU_SP"); + } + + if (config & E_NDS32_HAS_FPU_DP_INST) + { + has_fpu = 1; + r += snprintf (buf + r, size -r, ", FPU_DP"); + } + + if (config & E_NDS32_HAS_FPU_MAC_INST) + { + has_fpu = 1; + r += snprintf (buf + r, size -r, ", FPU_MAC"); + } + + if (has_fpu) + { + switch ((config & E_NDS32_FPU_REG_CONF) >> E_NDS32_FPU_REG_CONF_SHIFT) + { + case E_NDS32_FPU_REG_8SP_4DP: + r += snprintf (buf + r, size -r, ", FPU_REG:8/4"); + break; + case E_NDS32_FPU_REG_16SP_8DP: + r += snprintf (buf + r, size -r, ", FPU_REG:16/8"); + break; + case E_NDS32_FPU_REG_32SP_16DP: + r += snprintf (buf + r, size -r, ", FPU_REG:32/16"); + break; + case E_NDS32_FPU_REG_32SP_32DP: + r += snprintf (buf + r, size -r, ", FPU_REG:32/32"); + break; + } + } + + if (config & E_NDS32_HAS_AUDIO_INST) + r += snprintf (buf + r, size -r, ", AUDIO"); + + if (config & E_NDS32_HAS_STRING_INST) + r += snprintf (buf + r, size -r, ", STR"); + + if (config & E_NDS32_HAS_REDUCED_REGS) + r += snprintf (buf + r, size -r, ", 16REG"); + + if (config & E_NDS32_HAS_VIDEO_INST) + { + if (version <= E_NDS32_ELF_VER_1_3) + r += snprintf (buf + r, size -r, ", VIDEO"); + else + r += snprintf (buf + r, size -r, ", SATURATION"); + } + + if (config & E_NDS32_HAS_ENCRIPT_INST) + r += snprintf (buf + r, size -r, ", ENCRP"); + + if (config & E_NDS32_HAS_L2C_INST) + r += snprintf (buf + r, size -r, ", L2C"); +} + static char * get_machine_flags (unsigned e_flags, unsigned e_machine) { @@ -2461,6 +2756,16 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) strcat (buf, _(", relocatable-lib")); break; + case EM_PPC64: + if (e_flags & EF_PPC64_ABI) + { + char abi[] = ", abiv0"; + + abi[6] += e_flags & EF_PPC64_ABI; + strcat (buf, abi); + } + break; + case EM_V800: if ((e_flags & EF_RH850_ABI) == EF_RH850_ABI) strcat (buf, ", RH850 ABI"); @@ -2591,6 +2896,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) case E_MIPS_MACH_LS3A: strcat (buf, ", loongson-3a"); 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; case E_MIPS_MACH_XLR: strcat (buf, ", xlr"); break; case 0: /* We simply ignore the field in this case to avoid confusion: @@ -2633,12 +2939,18 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) case E_MIPS_ARCH_5: strcat (buf, ", mips5"); break; case E_MIPS_ARCH_32: strcat (buf, ", mips32"); break; case E_MIPS_ARCH_32R2: strcat (buf, ", mips32r2"); break; + case E_MIPS_ARCH_32R6: strcat (buf, ", mips32r6"); break; case E_MIPS_ARCH_64: strcat (buf, ", mips64"); break; case E_MIPS_ARCH_64R2: strcat (buf, ", mips64r2"); break; + case E_MIPS_ARCH_64R6: strcat (buf, ", mips64r6"); break; default: strcat (buf, _(", unknown ISA")); break; } break; + case EM_NDS32: + decode_NDS32_machine_flags (e_flags, buf, sizeof buf); + break; + case EM_SH: switch ((e_flags & EF_SH_MACH_MASK)) { @@ -2672,6 +2984,11 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) if (e_flags & EF_SH_FDPIC) strcat (buf, ", fdpic"); break; + + case EM_OR1K: + if (e_flags & EF_OR1K_NODELAY) + strcat (buf, ", no delay"); + break; case EM_SPARCV9: if (e_flags & EF_SPARC_32PLUS) @@ -2785,6 +3102,8 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) case EM_RL78: if (e_flags & E_FLAG_RL78_G10) strcat (buf, ", G10"); + if (e_flags & E_FLAG_RL78_64BIT_DOUBLES) + strcat (buf, ", 64-bit doubles"); break; case EM_RX: @@ -2941,6 +3260,8 @@ get_mips_segment_type (unsigned long type) return "RTPROC"; case PT_MIPS_OPTIONS: return "OPTIONS"; + case PT_MIPS_ABIFLAGS: + return "ABIFLAGS"; default: break; } @@ -3140,6 +3461,7 @@ get_mips_section_type_name (unsigned int sh_type) case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; + case SHT_MIPS_ABIFLAGS: return "MIPS_ABIFLAGS"; default: break; } @@ -3867,21 +4189,31 @@ process_file_header (void) return 1; } - -static int +static bfd_boolean get_32bit_program_headers (FILE * file, Elf_Internal_Phdr * pheaders) { Elf32_External_Phdr * phdrs; Elf32_External_Phdr * external; Elf_Internal_Phdr * internal; unsigned int i; + unsigned int size = elf_header.e_phentsize; + unsigned int num = elf_header.e_phnum; + + /* PR binutils/17531: Cope with unexpected section header sizes. */ + if (size == 0 || num == 0) + return FALSE; + if (size < sizeof * phdrs) + { + error (_("The e_phentsize field in the ELF header is less than the size of an ELF program header\n")); + return FALSE; + } + if (size > sizeof * phdrs) + warn (_("The e_phentsize field in the ELF header is larger than the size of an ELF program header\n")); phdrs = (Elf32_External_Phdr *) get_data (NULL, file, elf_header.e_phoff, - elf_header.e_phentsize, - elf_header.e_phnum, - _("program headers")); - if (!phdrs) - return 0; + size, num, _("program headers")); + if (phdrs == NULL) + return FALSE; for (i = 0, internal = pheaders, external = phdrs; i < elf_header.e_phnum; @@ -3898,24 +4230,34 @@ get_32bit_program_headers (FILE * file, Elf_Internal_Phdr * pheaders) } free (phdrs); - - return 1; + return TRUE; } -static int +static bfd_boolean get_64bit_program_headers (FILE * file, Elf_Internal_Phdr * pheaders) { Elf64_External_Phdr * phdrs; Elf64_External_Phdr * external; Elf_Internal_Phdr * internal; unsigned int i; + unsigned int size = elf_header.e_phentsize; + unsigned int num = elf_header.e_phnum; + + /* PR binutils/17531: Cope with unexpected section header sizes. */ + if (size == 0 || num == 0) + return FALSE; + if (size < sizeof * phdrs) + { + error (_("The e_phentsize field in the ELF header is less than the size of an ELF program header\n")); + return FALSE; + } + if (size > sizeof * phdrs) + warn (_("The e_phentsize field in the ELF header is larger than the size of an ELF program header\n")); phdrs = (Elf64_External_Phdr *) get_data (NULL, file, elf_header.e_phoff, - elf_header.e_phentsize, - elf_header.e_phnum, - _("program headers")); + size, num, _("program headers")); if (!phdrs) - return 0; + return FALSE; for (i = 0, internal = pheaders, external = phdrs; i < elf_header.e_phnum; @@ -3932,8 +4274,7 @@ get_64bit_program_headers (FILE * file, Elf_Internal_Phdr * pheaders) } free (phdrs); - - return 1; + return TRUE; } /* Returns 1 if the program headers were read into `program_headers'. */ @@ -3952,7 +4293,8 @@ get_program_headers (FILE * file) if (phdrs == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory reading %u program headers\n"), + elf_header.e_phnum); return 0; } @@ -4108,6 +4450,9 @@ process_program_headers (FILE * file) } } + if (do_segments) + putc ('\n', stdout); + switch (segment->p_type) { case PT_DYNAMIC: @@ -4118,6 +4463,12 @@ process_program_headers (FILE * file) section in the DYNAMIC segment. */ dynamic_addr = segment->p_offset; dynamic_size = segment->p_filesz; + /* PR binutils/17512: Avoid corrupt dynamic section info in the segment. */ + if (dynamic_addr + dynamic_size >= current_file_size) + { + error (_("the dynamic segment offset + size exceeds the size of the file\n")); + dynamic_addr = dynamic_size = 0; + } /* Try to locate the .dynamic section. If there is a section header table, we can easily locate it. */ @@ -4161,7 +4512,7 @@ process_program_headers (FILE * file) else { char fmt [32]; - int ret = snprintf (fmt, sizeof (fmt), "%%%ds", PATH_MAX); + int ret = snprintf (fmt, sizeof (fmt), "%%%ds", PATH_MAX - 1); if (ret >= (int) sizeof (fmt) || ret < 0) error (_("Internal error: failed to create format string to display program interpreter\n")); @@ -4171,14 +4522,11 @@ process_program_headers (FILE * file) error (_("Unable to read program interpreter name\n")); if (do_segments) - printf (_("\n [Requesting program interpreter: %s]"), + printf (_(" [Requesting program interpreter: %s]\n"), program_interpreter); } break; } - - if (do_segments) - putc ('\n', stdout); } if (do_segments && section_headers != NULL && string_table != NULL) @@ -4200,7 +4548,7 @@ process_program_headers (FILE * file) { if (!ELF_TBSS_SPECIAL (section, segment) && ELF_SECTION_IN_SEGMENT_STRICT (section, segment)) - printf ("%s ", SECTION_NAME (section)); + printf ("%s ", printable_section_name (section)); } putc ('\n',stdout); @@ -4242,26 +4590,46 @@ offset_from_vma (FILE * file, bfd_vma vma, bfd_size_type size) } -static int -get_32bit_section_headers (FILE * file, unsigned int num) +/* Allocate memory and load the sections headers into the global pointer + SECTION_HEADERS. If PROBE is true, this is just a probe and we do not + generate any error messages if the load fails. */ + +static bfd_boolean +get_32bit_section_headers (FILE * file, bfd_boolean probe) { Elf32_External_Shdr * shdrs; Elf_Internal_Shdr * internal; unsigned int i; + unsigned int size = elf_header.e_shentsize; + unsigned int num = probe ? 1 : elf_header.e_shnum; + + /* PR binutils/17531: Cope with unexpected section header sizes. */ + if (size == 0 || num == 0) + return FALSE; + if (size < sizeof * shdrs) + { + if (! probe) + error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n")); + return FALSE; + } + if (!probe && size > sizeof * shdrs) + warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n")); shdrs = (Elf32_External_Shdr *) get_data (NULL, file, elf_header.e_shoff, - elf_header.e_shentsize, num, - _("section headers")); - if (!shdrs) - return 0; + size, num, + probe ? NULL : _("section headers")); + if (shdrs == NULL) + return FALSE; + if (section_headers != NULL) + free (section_headers); section_headers = (Elf_Internal_Shdr *) cmalloc (num, sizeof (Elf_Internal_Shdr)); - if (section_headers == NULL) { - error (_("Out of memory\n")); - return 0; + if (!probe) + error (_("Out of memory reading %u section headers\n"), num); + return FALSE; } for (i = 0, internal = section_headers; @@ -4281,30 +4649,45 @@ get_32bit_section_headers (FILE * file, unsigned int num) } free (shdrs); - - return 1; + return TRUE; } -static int -get_64bit_section_headers (FILE * file, unsigned int num) +static bfd_boolean +get_64bit_section_headers (FILE * file, bfd_boolean probe) { Elf64_External_Shdr * shdrs; Elf_Internal_Shdr * internal; unsigned int i; + unsigned int size = elf_header.e_shentsize; + unsigned int num = probe ? 1 : elf_header.e_shnum; + + /* PR binutils/17531: Cope with unexpected section header sizes. */ + if (size == 0 || num == 0) + return FALSE; + if (size < sizeof * shdrs) + { + if (! probe) + error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n")); + return FALSE; + } + if (! probe && size > sizeof * shdrs) + warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n")); shdrs = (Elf64_External_Shdr *) get_data (NULL, file, elf_header.e_shoff, - elf_header.e_shentsize, num, - _("section headers")); - if (!shdrs) - return 0; + size, num, + probe ? NULL : _("section headers")); + if (shdrs == NULL) + return FALSE; + if (section_headers != NULL) + free (section_headers); section_headers = (Elf_Internal_Shdr *) cmalloc (num, sizeof (Elf_Internal_Shdr)); - if (section_headers == NULL) { - error (_("Out of memory\n")); - return 0; + if (! probe) + error (_("Out of memory reading %u section headers\n"), num); + return FALSE; } for (i = 0, internal = section_headers; @@ -4324,8 +4707,7 @@ get_64bit_section_headers (FILE * file, unsigned int num) } free (shdrs); - - return 1; + return TRUE; } static Elf_Internal_Sym * @@ -4347,6 +4729,13 @@ get_32bit_elf_symbols (FILE * file, goto exit_point; } + if (section->sh_size > current_file_size) + { + error (_("Section %s has an invalid sh_size of 0x%lx\n"), + printable_section_name (section), (unsigned long) section->sh_size); + goto exit_point; + } + number = section->sh_size / section->sh_entsize; if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1) @@ -4377,7 +4766,8 @@ get_32bit_elf_symbols (FILE * file, if (isyms == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory reading %lu symbols\n"), + (unsigned long) number); goto exit_point; } @@ -4427,6 +4817,13 @@ get_64bit_elf_symbols (FILE * file, goto exit_point; } + if (section->sh_size > current_file_size) + { + error (_("Section %s has an invalid sh_size of 0x%lx\n"), + printable_section_name (section), (unsigned long) section->sh_size); + goto exit_point; + } + number = section->sh_size / section->sh_entsize; if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1) @@ -4456,7 +4853,8 @@ get_64bit_elf_symbols (FILE * file, if (isyms == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory reading %lu symbols\n"), + (unsigned long) number); goto exit_point; } @@ -4744,10 +5142,10 @@ process_section_headers (FILE * file) if (is_32bit_elf) { - if (! get_32bit_section_headers (file, elf_header.e_shnum)) + if (! get_32bit_section_headers (file, FALSE)) return 0; } - else if (! get_64bit_section_headers (file, elf_header.e_shnum)) + else if (! get_64bit_section_headers (file, FALSE)) return 0; /* Read in the string table, so that we have names to display. */ @@ -4821,19 +5219,22 @@ process_section_headers (FILE * file) break; } -#define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \ - do \ - { \ - bfd_size_type expected_entsize = is_32bit_elf ? size32 : size64; \ - if (section->sh_entsize != expected_entsize) \ +#define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \ + do \ + { \ + bfd_size_type expected_entsize = is_32bit_elf ? size32 : size64; \ + if (section->sh_entsize != expected_entsize) \ { \ - error (_("Section %d has invalid sh_entsize of %" BFD_VMA_FMT "x\n"), \ - i, section->sh_entsize); \ - error (_("(Using the expected size of %d for the rest of this dump)\n"), \ - (int) expected_entsize); \ + char buf[40]; \ + sprintf_vma (buf, section->sh_entsize); \ + /* Note: coded this way so that there is a single string for \ + translation. */ \ + error (_("Section %d has invalid sh_entsize of %s\n"), i, buf); \ + error (_("(Using the expected size of %u for the rest of this dump)\n"), \ + (unsigned) expected_entsize); \ section->sh_entsize = expected_entsize; \ - } \ - } \ + } \ + } \ while (0) #define CHECK_ENTSIZE(section, i, type) \ @@ -4909,6 +5310,8 @@ process_section_headers (FILE * file) || (do_debug_lines && const_strneq (name, "line.")) || (do_debug_pubnames && const_strneq (name, "pubnames")) || (do_debug_pubtypes && const_strneq (name, "pubtypes")) + || (do_debug_pubnames && const_strneq (name, "gnu_pubnames")) + || (do_debug_pubtypes && const_strneq (name, "gnu_pubtypes")) || (do_debug_aranges && const_strneq (name, "aranges")) || (do_debug_ranges && const_strneq (name, "ranges")) || (do_debug_frames && const_strneq (name, "frame")) @@ -4944,7 +5347,6 @@ process_section_headers (FILE * file) ) request_dump_bynumber (i, DEBUG_DUMP); } - } if (! do_sections) @@ -5001,14 +5403,9 @@ process_section_headers (FILE * file) { printf (" [%2u] ", i); if (do_section_details) - { - print_symbol (INT_MAX, SECTION_NAME (section)); - printf ("\n "); - } + printf ("%s\n ", printable_section_name (section)); else - { - print_symbol (-17, SECTION_NAME (section)); - } + print_symbol (-17, SECTION_NAME (section)); printf (do_wide ? " %-15s " : " %-15.15s ", get_section_type_name (section->sh_type)); @@ -5241,7 +5638,8 @@ process_section_groups (FILE * file) if (section_headers_groups == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory reading %u section group headers\n"), + elf_header.e_shnum); return 0; } @@ -5265,7 +5663,8 @@ process_section_groups (FILE * file) if (section_groups == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory reading %lu groups\n"), + (unsigned long) group_count); return 0; } @@ -5281,8 +5680,8 @@ process_section_groups (FILE * file) { if (section->sh_type == SHT_GROUP) { - char * name = SECTION_NAME (section); - char * group_name; + const char * name = printable_section_name (section); + const char * group_name; unsigned char * start; unsigned char * indices; unsigned int entry, j, size; @@ -5353,9 +5752,10 @@ process_section_groups (FILE * file) strtab_sec = sec; if (strtab) free (strtab); + strtab = (char *) get_data (NULL, file, strtab_sec->sh_offset, - 1, strtab_sec->sh_size, - _("string table")); + 1, strtab_sec->sh_size, + _("string table")); strtab_size = strtab != NULL ? strtab_sec->sh_size : 0; } group_name = sym->st_name < strtab_size @@ -5426,7 +5826,7 @@ process_section_groups (FILE * file) if (do_section_groups) { sec = section_headers + entry; - printf (" [%5u] %s\n", entry, SECTION_NAME (sec)); + printf (" [%5u] %s\n", entry, printable_section_name (sec)); } g = (struct group_list *) xmalloc (sizeof (struct group_list)); @@ -5734,7 +6134,7 @@ process_relocs (FILE * file) if (string_table == NULL) printf ("%d", section->sh_name); else - printf ("'%s'", SECTION_NAME (section)); + printf ("'%s'", printable_section_name (section)); printf (_(" at offset 0x%lx contains %lu entries:\n"), rel_offset, (unsigned long) (rel_size / section->sh_entsize)); @@ -5766,8 +6166,8 @@ process_relocs (FILE * file) strsec = section_headers + symsec->sh_link; strtab = (char *) get_data (NULL, file, strsec->sh_offset, - 1, strsec->sh_size, - _("string table")); + 1, strsec->sh_size, + _("string table")); strtablen = strtab == NULL ? 0 : strsec->sh_size; } @@ -6072,7 +6472,11 @@ ia64_process_unwind (FILE * file) aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms); strsec = section_headers + sec->sh_link; - assert (aux.strtab == NULL); + if (aux.strtab != NULL) + { + error (_("Multiple auxillary string tables encountered\n")); + free (aux.strtab); + } aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset, 1, strsec->sh_size, _("string table")); @@ -6090,13 +6494,16 @@ ia64_process_unwind (FILE * file) char * suffix; size_t len, len2; - for (i = unwstart, sec = section_headers + unwstart; + for (i = unwstart, sec = section_headers + unwstart, unwsec = NULL; i < elf_header.e_shnum; ++i, ++sec) if (sec->sh_type == SHT_IA_64_UNWIND) { unwsec = sec; break; } + /* We have already counted the number of SHT_IA64_UNWIND + sections so the loop above should never fail. */ + assert (unwsec != NULL); unwstart = i + 1; len = sizeof (ELF_STRING_ia64_unwind_once) - 1; @@ -6104,18 +6511,26 @@ ia64_process_unwind (FILE * file) if ((unwsec->sh_flags & SHF_GROUP) != 0) { /* We need to find which section group it is in. */ - struct group_list * g = section_headers_groups [i]->root; + struct group_list * g; - for (; g != NULL; g = g->next) + if (section_headers_groups == NULL + || section_headers_groups [i] == NULL) + i = elf_header.e_shnum; + else { - sec = section_headers + g->section_index; + g = section_headers_groups [i]->root; - if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info)) - break; - } + for (; g != NULL; g = g->next) + { + sec = section_headers + g->section_index; - if (g == NULL) - i = elf_header.e_shnum; + if (streq (SECTION_NAME (sec), ELF_STRING_ia64_unwind_info)) + break; + } + + if (g == NULL) + i = elf_header.e_shnum; + } } else if (strneq (SECTION_NAME (unwsec), ELF_STRING_ia64_unwind_once, len)) { @@ -6151,14 +6566,14 @@ ia64_process_unwind (FILE * file) if (string_table == NULL) printf ("%d", unwsec->sh_name); else - printf (_("'%s'"), SECTION_NAME (unwsec)); + printf ("'%s'", printable_section_name (unwsec)); } else { aux.info_addr = sec->sh_addr; aux.info = (unsigned char *) get_data (NULL, file, sec->sh_offset, 1, - sec->sh_size, - _("unwind info")); + sec->sh_size, + _("unwind info")); aux.info_size = aux.info == NULL ? 0 : sec->sh_size; printf (_("\nUnwind section ")); @@ -6166,7 +6581,7 @@ ia64_process_unwind (FILE * file) if (string_table == NULL) printf ("%d", unwsec->sh_name); else - printf (_("'%s'"), SECTION_NAME (unwsec)); + printf ("'%s'", printable_section_name (unwsec)); printf (_(" at offset 0x%lx contains %lu entries:\n"), (unsigned long) unwsec->sh_offset, @@ -6483,7 +6898,11 @@ hppa_process_unwind (FILE * file) aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms); strsec = section_headers + sec->sh_link; - assert (aux.strtab == NULL); + if (aux.strtab != NULL) + { + error (_("Multiple auxillary string tables encountered\n")); + free (aux.strtab); + } aux.strtab = (char *) get_data (NULL, file, strsec->sh_offset, 1, strsec->sh_size, _("string table")); @@ -6500,10 +6919,8 @@ hppa_process_unwind (FILE * file) { if (streq (SECTION_NAME (sec), ".PARISC.unwind")) { - printf (_("\nUnwind section ")); - printf (_("'%s'"), SECTION_NAME (sec)); - - printf (_(" at offset 0x%lx contains %lu entries:\n"), + printf (_("\nUnwind section '%s' at offset 0x%lx contains %lu entries:\n"), + printable_section_name (sec), (unsigned long) sec->sh_offset, (unsigned long) (sec->sh_size / (2 * eh_addr_size + 8))); @@ -6607,6 +7024,9 @@ get_unwind_section_word (struct arm_unw_aux_info * aux, unsigned int word; bfd_boolean wrapped; + if (sec == NULL || arm_sec == NULL) + return FALSE; + addr->section = SHN_UNDEF; addr->offset = 0; @@ -6662,6 +7082,10 @@ get_unwind_section_word (struct arm_unw_aux_info * aux, if (arm_sec->data == NULL) return FALSE; + /* If the offset is invalid then fail. */ + if (word_offset > sec->sh_size - 4) + return FALSE; + /* Get the word at the required offset. */ word = byte_get (arm_sec->data + word_offset, 4); @@ -6689,7 +7113,9 @@ get_unwind_section_word (struct arm_unw_aux_info * aux, if (rp->r_offset < word_offset) continue; - sym = aux->symtab + ELF32_R_SYM (rp->r_info); + /* PR 17531: file: 027-161405-0.004 */ + if (aux->symtab == NULL) + continue; if (arm_sec->rel_type == SHT_REL) { @@ -6700,47 +7126,76 @@ get_unwind_section_word (struct arm_unw_aux_info * aux, else if (arm_sec->rel_type == SHT_RELA) offset = rp->r_addend; else - abort (); - - offset += sym->st_value; - prelval = offset - (arm_sec->sec->sh_addr + rp->r_offset); - - /* Check that we are processing the expected reloc type. */ - if (elf_header.e_machine == EM_ARM) { - relname = elf_arm_reloc_type (ELF32_R_TYPE (rp->r_info)); + error (_("Unknown section relocation type %d encountered\n"), + arm_sec->rel_type); + break; + } + + /* PR 17531 file: 027-1241568-0.004. */ + if (ELF32_R_SYM (rp->r_info) >= aux->nsyms) + { + error (_("Bad symbol index in unwind relocation (%lu > %lu)\n"), + (unsigned long) ELF32_R_SYM (rp->r_info), aux->nsyms); + break; + } + + sym = aux->symtab + ELF32_R_SYM (rp->r_info); + offset += sym->st_value; + prelval = offset - (arm_sec->sec->sh_addr + rp->r_offset); + + /* Check that we are processing the expected reloc type. */ + if (elf_header.e_machine == EM_ARM) + { + relname = elf_arm_reloc_type (ELF32_R_TYPE (rp->r_info)); + if (relname == NULL) + { + warn (_("Skipping unknown ARM relocation type: %d\n"), + (int) ELF32_R_TYPE (rp->r_info)); + continue; + } if (streq (relname, "R_ARM_NONE")) continue; if (! streq (relname, "R_ARM_PREL31")) { - warn (_("Skipping unexpected relocation type %s\n"), relname); + warn (_("Skipping unexpected ARM relocation type %s\n"), relname); continue; } } else if (elf_header.e_machine == EM_TI_C6000) { relname = elf_tic6x_reloc_type (ELF32_R_TYPE (rp->r_info)); + if (relname == NULL) + { + warn (_("Skipping unknown C6000 relocation type: %d\n"), + (int) ELF32_R_TYPE (rp->r_info)); + continue; + } if (streq (relname, "R_C6000_NONE")) continue; if (! streq (relname, "R_C6000_PREL31")) { - warn (_("Skipping unexpected relocation type %s\n"), relname); + warn (_("Skipping unexpected C6000 relocation type %s\n"), relname); continue; } prelval >>= 1; } else - /* This function currently only supports ARM and TI unwinders. */ - abort (); + { + /* This function currently only supports ARM and TI unwinders. */ + warn (_("Only TI and ARM unwinders are currently supported\n")); + break; + } word = (word & ~ (bfd_vma) 0x7fffffff) | (prelval & 0x7fffffff); addr->section = sym->st_shndx; addr->offset = offset; + if (sym_name) * sym_name = sym->st_name; break; @@ -6928,11 +7383,15 @@ decode_arm_unwind_bytecode (struct arm_unw_aux_info *aux, if ((buf[i] & 0x80) == 0) break; } - assert (i < sizeof (buf)); - offset = read_uleb128 (buf, &len, buf + i + 1); - assert (len == i + 1); - offset = offset * 4 + 0x204; - printf ("vsp = vsp + %ld", offset); + if (i == sizeof (buf)) + printf (_("corrupt change to vsp")); + else + { + offset = read_uleb128 (buf, &len, buf + i + 1); + assert (len == i + 1); + offset = offset * 4 + 0x204; + printf ("vsp = vsp + %ld", offset); + } } else if (op == 0xb3 || op == 0xc8 || op == 0xc9) { @@ -7307,7 +7766,7 @@ decode_arm_unwind (struct arm_unw_aux_info * aux, break; default: - error (_("Unsupported architecture type %d encountered when decoding unwind table"), + error (_("Unsupported architecture type %d encountered when decoding unwind table\n"), elf_header.e_machine); } @@ -7427,7 +7886,7 @@ arm_process_unwind (FILE *file) break; default: - error (_("Unsupported architecture type %d encountered when processing unwind table"), + error (_("Unsupported architecture type %d encountered when processing unwind table\n"), elf_header.e_machine); return; } @@ -7445,7 +7904,13 @@ arm_process_unwind (FILE *file) aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms); strsec = section_headers + sec->sh_link; - assert (aux.strtab == NULL); + + /* PR binutils/17531 file: 011-12666-0.004. */ + if (aux.strtab != NULL) + { + error (_("Multiple string tables found in file.\n")); + free (aux.strtab); + } aux.strtab = get_data (NULL, file, strsec->sh_offset, 1, strsec->sh_size, _("string table")); aux.strtab_size = aux.strtab != NULL ? strsec->sh_size : 0; @@ -7462,7 +7927,7 @@ arm_process_unwind (FILE *file) if (sec->sh_type == sec_type) { printf (_("\nUnwind table index '%s' at offset 0x%lx contains %lu entries:\n"), - SECTION_NAME (sec), + printable_section_name (sec), (unsigned long) sec->sh_offset, (unsigned long) (sec->sh_size / (2 * eh_addr_size))); @@ -7541,7 +8006,12 @@ dynamic_section_mips_val (Elf_Internal_Dyn * entry) if (VALID_DYNAMIC_NAME (entry->d_un.d_val)) printf (_("Interface Version: %s"), GET_DYNAMIC_NAME (entry->d_un.d_val)); else - printf (_(""), entry->d_un.d_ptr); + { + char buf[40]; + sprintf_vma (buf, entry->d_un.d_ptr); + /* Note: coded this way so that there is a single string for translation. */ + printf (_(""), buf); + } break; case DT_MIPS_TIME_STAMP: @@ -7736,11 +8206,11 @@ get_32bit_dynamic_section (FILE * file) if (!edyn) return 0; -/* SGI's ELF has more than one section in the DYNAMIC segment, and we - might not have the luxury of section headers. Look for the DT_NULL - terminator to determine the number of entries. */ + /* SGI's ELF has more than one section in the DYNAMIC segment, and we + might not have the luxury of section headers. Look for the DT_NULL + terminator to determine the number of entries. */ for (ext = edyn, dynamic_nent = 0; - (char *) ext < (char *) edyn + dynamic_size; + (char *) ext < (char *) edyn + dynamic_size - sizeof (* entry); ext++) { dynamic_nent++; @@ -7752,7 +8222,8 @@ get_32bit_dynamic_section (FILE * file) sizeof (* entry)); if (dynamic_section == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for %lu dynamic entries\n"), + (unsigned long) dynamic_nent); free (edyn); return 0; } @@ -7777,16 +8248,18 @@ get_64bit_dynamic_section (FILE * file) Elf64_External_Dyn * ext; Elf_Internal_Dyn * entry; + /* Read in the data. */ edyn = (Elf64_External_Dyn *) get_data (NULL, file, dynamic_addr, 1, dynamic_size, _("dynamic section")); if (!edyn) return 0; -/* SGI's ELF has more than one section in the DYNAMIC segment, and we - might not have the luxury of section headers. Look for the DT_NULL - terminator to determine the number of entries. */ + /* SGI's ELF has more than one section in the DYNAMIC segment, and we + might not have the luxury of section headers. Look for the DT_NULL + terminator to determine the number of entries. */ for (ext = edyn, dynamic_nent = 0; - (char *) ext < (char *) edyn + dynamic_size; + /* PR 17533 file: 033-67080-0.004 - do not read off the end of the buffer. */ + (char *) ext < ((char *) edyn) + dynamic_size - sizeof (* ext); ext++) { dynamic_nent++; @@ -7798,11 +8271,13 @@ get_64bit_dynamic_section (FILE * file) sizeof (* entry)); if (dynamic_section == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for %lu dynamic entries\n"), + (unsigned long) dynamic_nent); free (edyn); return 0; } + /* Convert from external to internal formats. */ for (ext = edyn, entry = dynamic_section; entry < dynamic_section + dynamic_nent; ext++, entry++) @@ -7903,6 +8378,7 @@ process_dynamic_section (FILE * file) section.sh_entsize = sizeof (Elf32_External_Sym); else section.sh_entsize = sizeof (Elf64_External_Sym); + section.sh_name = string_table_length; dynamic_symbols = GET_ELF_SYMBOLS (file, §ion, & num_dynamic_syms); if (num_dynamic_syms < 1) @@ -7972,7 +8448,11 @@ process_dynamic_section (FILE * file) { /* Note: these braces are necessary to avoid a syntax error from the SunOS4 C compiler. */ - assert (sizeof (Elf_External_Syminfo) == entry->d_un.d_val); + /* PR binutils/17531: A corrupt file can trigger this test. + So do not use an assert, instead generate an error message. */ + if (sizeof (Elf_External_Syminfo) != entry->d_un.d_val) + error (_("Bad value (%d) for SYMINENT entry\n"), + (int) entry->d_un.d_val); } else if (entry->d_tag == DT_SYMINSZ) syminsz = entry->d_un.d_val; @@ -7997,7 +8477,8 @@ process_dynamic_section (FILE * file) dynamic_syminfo = (Elf_Internal_Syminfo *) malloc (syminsz); if (dynamic_syminfo == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating %lu byte for dynamic symbol info\n"), + (unsigned long) syminsz); return 0; } @@ -8015,8 +8496,8 @@ process_dynamic_section (FILE * file) } if (do_dynamic && dynamic_addr) - printf (_("\nDynamic section at offset 0x%lx contains %u entries:\n"), - dynamic_addr, dynamic_nent); + printf (_("\nDynamic section at offset 0x%lx contains %lu entries:\n"), + dynamic_addr, (unsigned long) dynamic_nent); if (do_dynamic) printf (_(" Tag Type Name/Value\n")); @@ -8428,9 +8909,14 @@ process_dynamic_section (FILE * file) time_t atime = entry->d_un.d_val; tmp = gmtime (&atime); - printf ("%04u-%02u-%02uT%02u:%02u:%02u\n", - tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, - tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + /* PR 17533 file: 041-1244816-0.004. */ + if (tmp == NULL) + printf (_("tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); } break; @@ -8537,17 +9023,15 @@ process_version_sections (FILE * file) found = 1; - printf - (_("\nVersion definition section '%s' contains %u entries:\n"), - SECTION_NAME (section), section->sh_info); + printf (_("\nVersion definition section '%s' contains %u entries:\n"), + printable_section_name (section), + section->sh_info); printf (_(" Addr: 0x")); printf_vma (section->sh_addr); - printf (_(" Offset: %#08lx Link: %u (%s)\n"), + printf (_(" Offset: %#08lx Link: %u (%s)"), (unsigned long) section->sh_offset, section->sh_link, - section->sh_link < elf_header.e_shnum - ? SECTION_NAME (section_headers + section->sh_link) - : _("")); + printable_section_name_from_index (section->sh_link)); edefs = (Elf_External_Verdef *) get_data (NULL, file, section->sh_offset, 1,section->sh_size, @@ -8655,15 +9139,13 @@ process_version_sections (FILE * file) found = 1; printf (_("\nVersion needs section '%s' contains %u entries:\n"), - SECTION_NAME (section), section->sh_info); + printable_section_name (section), section->sh_info); printf (_(" Addr: 0x")); printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %u (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, - section->sh_link < elf_header.e_shnum - ? SECTION_NAME (section_headers + section->sh_link) - : _("")); + printable_section_name_from_index (section->sh_link)); eneed = (Elf_External_Verneed *) get_data (NULL, file, section->sh_offset, 1, @@ -8747,6 +9229,12 @@ process_version_sections (FILE * file) if (j < ent.vn_cnt) warn (_("Missing Version Needs auxillary information\n")); + if (ent.vn_next == 0 && cnt < section->sh_info - 1) + { + warn (_("Corrupt Version Needs structure - offset to next structure is zero with entries still left to be processed\n")); + cnt = section->sh_info; + break; + } idx += ent.vn_next; } @@ -8760,8 +9248,8 @@ process_version_sections (FILE * file) case SHT_GNU_versym: { Elf_Internal_Shdr * link_section; - int total; - int cnt; + size_t total; + unsigned int cnt; unsigned char * edata; unsigned short * data; char * strtab; @@ -8796,14 +9284,14 @@ process_version_sections (FILE * file) break; } - printf (_("\nVersion symbols section '%s' contains %d entries:\n"), - SECTION_NAME (section), total); + printf (_("\nVersion symbols section '%s' contains %lu entries:\n"), + printable_section_name (section), (unsigned long) total); printf (_(" Addr: ")); printf_vma (section->sh_addr); printf (_(" Offset: %#08lx Link: %u (%s)\n"), (unsigned long) section->sh_offset, section->sh_link, - SECTION_NAME (link_section)); + printable_section_name (link_section)); off = offset_from_vma (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)], @@ -8952,7 +9440,9 @@ process_version_sections (FILE * file) _("version def")) == NULL) { ivd.vd_next = 0; - ivd.vd_ndx = 0; + /* PR 17531: file: 046-1082287-0.004. */ + ivd.vd_ndx = (data[cnt + j] & VERSYM_VERSION) + 1; + break; } else { @@ -9063,13 +9553,8 @@ get_symbol_type (unsigned int type) default: if (type >= STT_LOPROC && type <= STT_HIPROC) { - if (elf_header.e_machine == EM_ARM) - { - if (type == STT_ARM_TFUNC) - return "THUMB_FUNC"; - if (type == STT_ARM_16BIT) - return "THUMB_LABEL"; - } + if (elf_header.e_machine == EM_ARM && type == STT_ARM_TFUNC) + return "THUMB_FUNC"; if (elf_header.e_machine == EM_SPARCV9 && type == STT_REGISTER) return "REGISTER"; @@ -9200,6 +9685,19 @@ get_ia64_symbol_other (unsigned int other) return NULL; } +static const char * +get_ppc64_symbol_other (unsigned int other) +{ + if (PPC64_LOCAL_ENTRY_OFFSET (other) != 0) + { + static char buf[32]; + snprintf (buf, sizeof buf, _(": %d"), + PPC64_LOCAL_ENTRY_OFFSET (other)); + return buf; + } + return NULL; +} + static const char * get_symbol_other (unsigned int other) { @@ -9217,6 +9715,9 @@ get_symbol_other (unsigned int other) case EM_IA_64: result = get_ia64_symbol_other (other); break; + case EM_PPC64: + result = get_ppc64_symbol_other (other); + break; default: break; } @@ -9263,7 +9764,7 @@ get_symbol_index_type (unsigned int type) else if (type >= SHN_LORESERVE) sprintf (buff, "RSV[0x%04x]", type & 0xffff); else if (type >= elf_header.e_shnum) - sprintf (buff, "bad section index[%3d]", type); + sprintf (buff, _("bad section index[%3d]"), type); else sprintf (buff, "%3d", type); break; @@ -9273,30 +9774,41 @@ get_symbol_index_type (unsigned int type) } static bfd_vma * -get_dynamic_data (FILE * file, unsigned int number, unsigned int ent_size) +get_dynamic_data (FILE * file, size_t number, unsigned int ent_size) { unsigned char * e_data; bfd_vma * i_data; - e_data = (unsigned char *) cmalloc (number, ent_size); + /* Be kind to memory chekers (eg valgrind, address sanitizer) by not + attempting to allocate memory when the read is bound to fail. */ + if (ent_size * number > current_file_size) + { + error (_("Invalid number of dynamic entries: %lu\n"), + (unsigned long) number); + return NULL; + } + e_data = (unsigned char *) cmalloc (number, ent_size); if (e_data == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory reading %lu dynamic entries\n"), + (unsigned long) number); return NULL; } if (fread (e_data, ent_size, number, file) != number) { - error (_("Unable to read in dynamic data\n")); + error (_("Unable to read in %lu bytes of dynamic data\n"), + (unsigned long) (number * ent_size)); + free (e_data); return NULL; } i_data = (bfd_vma *) cmalloc (number, sizeof (*i_data)); - if (i_data == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for %lu dynamic entries\n"), + (unsigned long) number); free (e_data); return NULL; } @@ -9315,12 +9827,19 @@ print_dynamic_symbol (bfd_vma si, unsigned long hn) Elf_Internal_Sym * psym; int n; - psym = dynamic_symbols + si; - n = print_vma (si, DEC_5); if (n < 5) fputs (&" "[n], stdout); printf (" %3lu: ", hn); + + if (dynamic_symbols == NULL || si >= num_dynamic_syms) + { + printf (_("\n"), + (unsigned long) si); + return; + } + + psym = dynamic_symbols + si; print_vma (psym->st_value, LONG_HEX); putchar (' '); print_vma (psym->st_size, DEC_5); @@ -9347,14 +9866,15 @@ static int process_symbol_table (FILE * file) { Elf_Internal_Shdr * section; - bfd_vma nbuckets = 0; - bfd_vma nchains = 0; + bfd_size_type nbuckets = 0; + bfd_size_type nchains = 0; bfd_vma * buckets = NULL; bfd_vma * chains = NULL; bfd_vma ngnubuckets = 0; bfd_vma * gnubuckets = NULL; bfd_vma * gnuchains = NULL; bfd_vma gnusymidx = 0; + bfd_size_type ngnuchains = 0; if (!do_syms && !do_dyn_syms && !do_histogram) return 1; @@ -9367,7 +9887,7 @@ process_symbol_table (FILE * file) { unsigned char nb[8]; unsigned char nc[8]; - int hash_ent_size = 4; + unsigned int hash_ent_size = 4; if ((elf_header.e_machine == EM_ALPHA || elf_header.e_machine == EM_S390 @@ -9516,6 +10036,7 @@ process_symbol_table (FILE * file) } gnuchains = get_dynamic_data (file, maxchain, 4); + ngnuchains = maxchain; no_gnu_hash: if (gnuchains == NULL) @@ -9531,7 +10052,8 @@ process_symbol_table (FILE * file) if ((dynamic_info[DT_HASH] || dynamic_info_DT_GNU_HASH) && do_syms && do_using_dynamic - && dynamic_strings != NULL) + && dynamic_strings != NULL + && dynamic_symbols != NULL) { unsigned long hn; @@ -9574,11 +10096,12 @@ process_symbol_table (FILE * file) print_dynamic_symbol (si, hn); si++; } - while ((gnuchains[off++] & 1) == 0); + while (off < ngnuchains && (gnuchains[off++] & 1) == 0); } } } - else if (do_dyn_syms || (do_syms && !do_using_dynamic)) + else if ((do_dyn_syms || (do_syms && !do_using_dynamic)) + && section_headers != NULL) { unsigned int i; @@ -9602,12 +10125,12 @@ process_symbol_table (FILE * file) if (section->sh_entsize == 0) { printf (_("\nSymbol table '%s' has a sh_entsize of zero!\n"), - SECTION_NAME (section)); + printable_section_name (section)); continue; } printf (_("\nSymbol table '%s' contains %lu entries:\n"), - SECTION_NAME (section), + printable_section_name (section), (unsigned long) (section->sh_size / section->sh_entsize)); if (is_32bit_elf) @@ -9837,14 +10360,15 @@ process_symbol_table (FILE * file) printf (_("\nHistogram for bucket list length (total of %lu buckets):\n"), (unsigned long) nbuckets); - printf (_(" Length Number %% of total Coverage\n")); lengths = (unsigned long *) calloc (nbuckets, sizeof (*lengths)); if (lengths == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for histogram buckets\n")); return 0; } + + printf (_(" Length Number %% of total Coverage\n")); for (hn = 0; hn < nbuckets; ++hn) { for (si = buckets[hn]; si > 0 && si < nchains; si = chains[si]) @@ -9852,6 +10376,15 @@ process_symbol_table (FILE * file) ++nsyms; if (maxlength < ++lengths[hn]) ++maxlength; + + /* PR binutils/17531: A corrupt binary could contain broken + histogram data. Do not go into an infinite loop trying + to process it. */ + if (chains[si] == si) + { + error (_("histogram chain links to itself\n")); + break; + } } } @@ -9859,7 +10392,7 @@ process_symbol_table (FILE * file) if (counts == NULL) { free (lengths); - error (_("Out of memory\n")); + error (_("Out of memory allocating space for histogram counts\n")); return 0; } @@ -9899,15 +10432,16 @@ process_symbol_table (FILE * file) unsigned long nzero_counts = 0; unsigned long nsyms = 0; + printf (_("\nHistogram for `.gnu.hash' bucket list length (total of %lu buckets):\n"), + (unsigned long) ngnubuckets); + lengths = (unsigned long *) calloc (ngnubuckets, sizeof (*lengths)); if (lengths == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for gnu histogram buckets\n")); return 0; } - printf (_("\nHistogram for `.gnu.hash' bucket list length (total of %lu buckets):\n"), - (unsigned long) ngnubuckets); printf (_(" Length Number %% of total Coverage\n")); for (hn = 0; hn < ngnubuckets; ++hn) @@ -9916,7 +10450,9 @@ process_symbol_table (FILE * file) bfd_vma off, length = 1; for (off = gnubuckets[hn] - gnusymidx; - (gnuchains[off] & 1) == 0; ++off) + /* PR 17531 file: 010-77222-0.004. */ + off < ngnuchains && (gnuchains[off] & 1) == 0; + ++off) ++length; lengths[hn] = length; if (length > maxlength) @@ -9928,7 +10464,7 @@ process_symbol_table (FILE * file) if (counts == NULL) { free (lengths); - error (_("Out of memory\n")); + error (_("Out of memory allocating space for gnu histogram counts\n")); return 0; } @@ -9982,7 +10518,9 @@ process_syminfo (FILE * file ATTRIBUTE_UNUSED) unsigned short int flags = dynamic_syminfo[i].si_flags; printf ("%4d: ", i); - if (VALID_DYNAMIC_NAME (dynamic_symbols[i].st_name)) + if (i >= num_dynamic_syms) + printf (_("")); + else if (VALID_DYNAMIC_NAME (dynamic_symbols[i].st_name)) print_symbol (30, GET_DYNAMIC_NAME (dynamic_symbols[i].st_name)); else printf (_(""), dynamic_symbols[i].st_name); @@ -10085,7 +10623,7 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, default: if (saved_sym != NULL) - error (_("Unhandled MSP430 reloc type found after SYM_DIFF reloc")); + error (_("Unhandled MSP430 reloc type found after SYM_DIFF reloc\n")); break; } break; @@ -10121,7 +10659,7 @@ target_specific_reloc_handling (Elf_Internal_Rela * reloc, break; default: if (saved_sym != NULL) - error (_("Unhandled MN10300 reloc type found after SYM_DIFF reloc")); + error (_("Unhandled MN10300 reloc type found after SYM_DIFF reloc\n")); break; } break; @@ -10233,13 +10771,14 @@ is_32bit_abs_reloc (unsigned int reloc_type) return reloc_type == 1; /* R_MSP430_32 or R_MSP320_ABS32. */ case EM_MT: return reloc_type == 2; /* R_MT_32. */ + case EM_NDS32: + return reloc_type == 20; /* R_NDS32_RELA. */ case EM_ALTERA_NIOS2: return reloc_type == 12; /* R_NIOS2_BFD_RELOC_32. */ case EM_NIOS32: return reloc_type == 1; /* R_NIOS_32. */ - case EM_OPENRISC: - case EM_OR32: - return reloc_type == 1; /* R_OR32_32. */ + case EM_OR1K: + return reloc_type == 1; /* R_OR1K_32. */ case EM_PARISC: return (reloc_type == 1 /* R_PARISC_DIR32. */ || reloc_type == 41); /* R_PARISC_SECREL32. */ @@ -10327,6 +10866,8 @@ is_32bit_pcrel_reloc (unsigned int reloc_type) return reloc_type == 3; /* R_ARM_REL32 */ case EM_MICROBLAZE: return reloc_type == 2; /* R_MICROBLAZE_32_PCREL. */ + case EM_OR1K: + return reloc_type == 9; /* R_OR1K_32_PCREL. */ case EM_PARISC: return reloc_type == 9; /* R_PARISC_PCREL32. */ case EM_PPC: @@ -10486,10 +11027,14 @@ is_16bit_abs_reloc (unsigned int reloc_type) return reloc_type == 2; /* R_MSP430_ABS16. */ case EM_MSP430_OLD: return reloc_type == 5; /* R_MSP430_16_BYTE. */ + case EM_NDS32: + return reloc_type == 19; /* R_NDS32_RELA. */ case EM_ALTERA_NIOS2: return reloc_type == 13; /* R_NIOS2_BFD_RELOC_16. */ case EM_NIOS32: return reloc_type == 9; /* R_NIOS_16. */ + case EM_OR1K: + return reloc_type == 2; /* R_OR1K_16. */ case EM_TI_C6000: return reloc_type == 2; /* R_C6000_ABS16. */ case EM_XC16X: @@ -10546,9 +11091,16 @@ is_none_reloc (unsigned int reloc_type) 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_NDS32: + return (reloc_type == 0 /* R_XTENSA_NONE. */ + || reloc_type == 204 /* R_NDS32_DIFF8. */ + || reloc_type == 205 /* R_NDS32_DIFF16. */ + || reloc_type == 206 /* R_NDS32_DIFF32. */ + || reloc_type == 207 /* R_NDS32_ULEB128. */); case EM_XTENSA_OLD: case EM_XTENSA: return (reloc_type == 0 /* R_XTENSA_NONE. */ @@ -10647,7 +11199,7 @@ apply_relocations (void * file, else { warn (_("unable to apply unsupported reloc type %d to section %s\n"), - reloc_type, SECTION_NAME (section)); + reloc_type, printable_section_name (section)); continue; } @@ -10656,7 +11208,7 @@ apply_relocations (void * file, { warn (_("skipping invalid relocation offset 0x%lx in section %s\n"), (unsigned long) rp->r_offset, - SECTION_NAME (section)); + printable_section_name (section)); continue; } @@ -10664,7 +11216,7 @@ apply_relocations (void * file, if (sym_index >= num_syms) { warn (_("skipping invalid relocation symbol index 0x%lx in section %s\n"), - sym_index, SECTION_NAME (section)); + sym_index, printable_section_name (section)); continue; } sym = symtab + sym_index; @@ -10688,7 +11240,7 @@ apply_relocations (void * file, warn (_("skipping unexpected symbol type %s in %ld'th relocation in section %s\n"), get_symbol_type (ELF_ST_TYPE (sym->st_info)), (long int)(rp - relocs), - SECTION_NAME (relsec)); + printable_section_name (relsec)); continue; } @@ -10731,10 +11283,9 @@ apply_relocations (void * file, static int disassemble_section (Elf_Internal_Shdr * section, FILE * file) { - printf (_("\nAssembly dump of section %s\n"), - SECTION_NAME (section)); + printf (_("\nAssembly dump of section %s\n"), printable_section_name (section)); - /* XXX -- to be done --- XXX */ + /* FIXME: XXX -- to be done --- XXX */ return 1; } @@ -10753,7 +11304,7 @@ get_section_contents (Elf_Internal_Shdr * section, FILE * file) if (num_bytes == 0 || section->sh_type == SHT_NOBITS) { printf (_("\nSection '%s' has no data to dump.\n"), - SECTION_NAME (section)); + printable_section_name (section)); return NULL; } @@ -10770,14 +11321,13 @@ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file) char * data; char * end; char * start; - char * name = SECTION_NAME (section); bfd_boolean some_strings_shown; start = get_section_contents (section, file); if (start == NULL) return; - printf (_("\nString dump of section '%s':\n"), name); + printf (_("\nString dump of section '%s':\n"), printable_section_name (section)); /* If the section being dumped has relocations against it the user might be expecting these relocations to have been applied. Check for this @@ -10812,15 +11362,26 @@ dump_section_as_strings (Elf_Internal_Shdr * section, FILE * file) if (data < end) { + size_t maxlen = end - data; + #ifndef __MSVCRT__ /* PR 11128: Use two separate invocations in order to work around bugs in the Solaris 8 implementation of printf. */ printf (" [%6tx] ", data - start); - printf ("%s\n", data); #else - printf (" [%6Ix] %s\n", (size_t) (data - start), data); + printf (" [%6Ix] ", (size_t) (data - start)); #endif - data += strlen (data); + if (maxlen > 0) + { + print_symbol ((int) maxlen, data); + putchar ('\n'); + data += strnlen (data, maxlen); + } + else + { + printf (_("\n")); + data = end; + } some_strings_shown = TRUE; } } @@ -10848,7 +11409,7 @@ dump_section_as_bytes (Elf_Internal_Shdr * section, if (start == NULL) return; - printf (_("\nHex dump of section '%s':\n"), SECTION_NAME (section)); + printf (_("\nHex dump of section '%s':\n"), printable_section_name (section)); if (relocate) { @@ -11079,6 +11640,7 @@ static int display_debug_section (int shndx, Elf_Internal_Shdr * section, FILE * file) { char * name = SECTION_NAME (section); + const char * print_name = printable_section_name (section); bfd_size_type length; int result = 1; int i; @@ -11086,7 +11648,7 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, FILE * file) length = section->sh_size; if (length == 0) { - printf (_("\nSection '%s' has no debugging data.\n"), name); + printf (_("\nSection '%s' has no debugging data.\n"), print_name); return 0; } if (section->sh_type == SHT_NOBITS) @@ -11095,7 +11657,8 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, FILE * file) which has the NOBITS type - the bits in the file will be random. This can happen when a file containing a .eh_frame section is stripped with the --only-keep-debug command line option. */ - printf (_("section '%s' has the NOBITS type - its contents are unreliable.\n"), name); + printf (_("section '%s' has the NOBITS type - its contents are unreliable.\n"), + print_name); return 0; } @@ -11140,7 +11703,7 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, FILE * file) if (i == max) { - printf (_("Unrecognized debug section: %s\n"), name); + printf (_("Unrecognized debug section: %s\n"), print_name); result = 0; } @@ -11259,13 +11822,25 @@ display_tag_value (int tag, if (p >= end) { - warn (_("corrupt tag\n")); + warn (_("\n")); } else if (tag & 1) { - /* FIXME: we could read beyond END here. */ - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; + /* PR 17531 file: 027-19978-0.004. */ + size_t maxlen = (end - p) - 1; + + putchar ('"'); + if (maxlen > 0) + { + print_symbol ((int) maxlen, (const char *) p); + p += strnlen ((char *) p, maxlen) + 1; + } + else + { + printf (_("")); + p = (unsigned char *) end; + } + printf ("\"\n"); } else { @@ -11276,16 +11851,17 @@ display_tag_value (int tag, printf ("%ld (0x%lx)\n", val, val); } + assert (p <= end); return p; } /* ARM EABI attributes section. */ typedef struct { - int tag; + unsigned int tag; const char * name; /* 0 = special, 1 = string, 2 = uleb123, > 0x80 == table lookup. */ - int type; + unsigned int type; const char ** table; } arm_attr_public_tag; @@ -11403,12 +11979,12 @@ static unsigned char * display_arm_attribute (unsigned char * p, const unsigned char * const end) { - int tag; + unsigned int tag; unsigned int len; - int val; + unsigned int val; arm_attr_public_tag * attr; unsigned i; - int type; + unsigned int type; tag = read_uleb128 (p, &len, end); p += len; @@ -11483,14 +12059,30 @@ display_arm_attribute (unsigned char * p, break; case 32: /* Tag_compatibility. */ - val = read_uleb128 (p, &len, end); - p += len; - printf (_("flag = %d, vendor = %s\n"), val, p); - p += strlen ((char *) p) + 1; + { + val = read_uleb128 (p, &len, end); + p += len; + printf (_("flag = %d, vendor = "), val); + if (p < end - 1) + { + size_t maxlen = (end - p) - 1; + + print_symbol ((int) maxlen, (const char *) p); + p += strnlen ((char *) p, maxlen) + 1; + } + else + { + printf (_("")); + p = (unsigned char *) end; + } + putchar ('\n'); + } break; case 64: /* Tag_nodefaults. */ - p++; + /* PR 17531: file: 001-505008-0.01. */ + if (p < end) + p++; printf (_("True\n")); break; @@ -11501,14 +12093,15 @@ display_arm_attribute (unsigned char * p, { val = read_uleb128 (p, &len, end); p += len; - if ((unsigned int)val >= ARRAY_SIZE (arm_attr_tag_CPU_arch)) + if ((unsigned int) val >= ARRAY_SIZE (arm_attr_tag_CPU_arch)) printf ("??? (%d)\n", val); else printf ("%s\n", arm_attr_tag_CPU_arch[val]); } else printf ("???\n"); - while (*(p++) != '\0' /* NUL terminator. */); + while (p < end && *(p++) != '\0' /* NUL terminator. */) + ; break; default: @@ -11555,15 +12148,28 @@ display_gnu_attribute (unsigned char * p, { val = read_uleb128 (p, &len, end); p += len; + + printf (_("flag = %d, vendor = "), val); if (p == end) { - printf (_("flag = %d, vendor = \n"), val); + printf (_("\n")); warn (_("corrupt vendor attribute\n")); } else { - printf (_("flag = %d, vendor = %s\n"), val, p); - p += strlen ((char *) p) + 1; + if (p < end - 1) + { + size_t maxlen = (end - p) - 1; + + print_symbol ((int) maxlen, (const char *) p); + p += strnlen ((char *) p, maxlen) + 1; + } + else + { + printf (_("")); + p = (unsigned char *) end; + } + putchar ('\n'); } return p; } @@ -11639,7 +12245,7 @@ display_power_gnu_attribute (unsigned char * p, { if (p == end) { - warn (_("corrupt Tag_GNU_Power_ABI_Struct_Return")); + warn (_("corrupt Tag_GNU_Power_ABI_Struct_Return\n")); return p; } @@ -11673,6 +12279,7 @@ display_sparc_hwcaps (int mask) if (mask) { int first = 1; + if (mask & ELF_SPARC_HWCAP_MUL32) fputs ("mul32", stdout), first = 0; if (mask & ELF_SPARC_HWCAP_DIV32) @@ -11707,8 +12314,43 @@ display_sparc_hwcaps (int mask) printf ("%scspare", first ? "" : "|"), first = 0; } else - fputc('0', stdout); - fputc('\n', stdout); + fputc ('0', stdout); + fputc ('\n', stdout); +} + +static void +display_sparc_hwcaps2 (int mask) +{ + if (mask) + { + int first = 1; + + if (mask & ELF_SPARC_HWCAP2_FJATHPLUS) + fputs ("fjathplus", stdout), first = 0; + if (mask & ELF_SPARC_HWCAP2_VIS3B) + printf ("%svis3b", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_ADP) + printf ("%sadp", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_SPARC5) + printf ("%ssparc5", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_MWAIT) + printf ("%smwait", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_XMPMUL) + printf ("%sxmpmul", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_XMONT) + printf ("%sxmont2", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_NSEC) + printf ("%snsec", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_FJATHHPC) + printf ("%sfjathhpc", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_FJDES) + printf ("%sfjdes", first ? "" : "|"), first = 0; + if (mask & ELF_SPARC_HWCAP2_FJAES) + printf ("%sfjaes", first ? "" : "|"), first = 0; + } + else + fputc ('0', stdout); + fputc ('\n', stdout); } static unsigned char * @@ -11716,21 +12358,64 @@ display_sparc_gnu_attribute (unsigned char * p, int tag, const unsigned char * const end) { + unsigned int len; + int val; + if (tag == Tag_GNU_Sparc_HWCAPS) { - unsigned int len; - int val; - val = read_uleb128 (p, &len, end); p += len; printf (" Tag_GNU_Sparc_HWCAPS: "); display_sparc_hwcaps (val); return p; - } + } + if (tag == Tag_GNU_Sparc_HWCAPS2) + { + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_GNU_Sparc_HWCAPS2: "); + display_sparc_hwcaps2 (val); + return p; + } return display_tag_value (tag, p, end); } +static void +print_mips_fp_abi_value (int val) +{ + switch (val) + { + case Val_GNU_MIPS_ABI_FP_ANY: + printf (_("Hard or soft float\n")); + break; + case Val_GNU_MIPS_ABI_FP_DOUBLE: + printf (_("Hard float (double precision)\n")); + break; + case Val_GNU_MIPS_ABI_FP_SINGLE: + printf (_("Hard float (single precision)\n")); + break; + case Val_GNU_MIPS_ABI_FP_SOFT: + printf (_("Soft float\n")); + break; + case Val_GNU_MIPS_ABI_FP_OLD_64: + printf (_("Hard float (MIPS32r2 64-bit FPU 12 callee-saved)\n")); + break; + case Val_GNU_MIPS_ABI_FP_XX: + printf (_("Hard float (32-bit CPU, Any FPU)\n")); + break; + case Val_GNU_MIPS_ABI_FP_64: + printf (_("Hard float (32-bit CPU, 64-bit FPU)\n")); + break; + case Val_GNU_MIPS_ABI_FP_64A: + printf (_("Hard float compat (32-bit CPU, 64-bit FPU)\n")); + break; + default: + printf ("??? (%d)\n", val); + break; + } +} + static unsigned char * display_mips_gnu_attribute (unsigned char * p, int tag, @@ -11745,27 +12430,8 @@ display_mips_gnu_attribute (unsigned char * p, p += len; printf (" Tag_GNU_MIPS_ABI_FP: "); - switch (val) - { - case Val_GNU_MIPS_ABI_FP_ANY: - printf (_("Hard or soft float\n")); - break; - case Val_GNU_MIPS_ABI_FP_DOUBLE: - printf (_("Hard float (double precision)\n")); - break; - case Val_GNU_MIPS_ABI_FP_SINGLE: - printf (_("Hard float (single precision)\n")); - break; - case Val_GNU_MIPS_ABI_FP_SOFT: - printf (_("Soft float\n")); - break; - case Val_GNU_MIPS_ABI_FP_64: - printf (_("Hard float (MIPS32r2 64-bit FPU)\n")); - break; - default: - printf ("??? (%d)\n", val); - break; - } + print_mips_fp_abi_value (val); + return p; } @@ -12000,18 +12666,45 @@ display_tic6x_attribute (unsigned char * p, return p; case Tag_ABI_compatibility: - val = read_uleb128 (p, &len, end); - p += len; - printf (" Tag_ABI_compatibility: "); - printf (_("flag = %d, vendor = %s\n"), val, p); - p += strlen ((char *) p) + 1; - return p; + { + val = read_uleb128 (p, &len, end); + p += len; + printf (" Tag_ABI_compatibility: "); + printf (_("flag = %d, vendor = "), val); + if (p < end - 1) + { + size_t maxlen = (end - p) - 1; + + print_symbol ((int) maxlen, (const char *) p); + p += strnlen ((char *) p, maxlen) + 1; + } + else + { + printf (_("")); + p = (unsigned char *) end; + } + putchar ('\n'); + return p; + } case Tag_ABI_conformance: - printf (" Tag_ABI_conformance: "); - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; - return p; + { + printf (" Tag_ABI_conformance: \""); + if (p < end - 1) + { + size_t maxlen = (end - p) - 1; + + print_symbol ((int) maxlen, (const char *) p); + p += strnlen ((char *) p, maxlen) + 1; + } + else + { + printf (_("")); + p = (unsigned char *) end; + } + printf ("\"\n"); + return p; + } } return display_tag_value (tag, p, end); @@ -12023,6 +12716,7 @@ display_raw_attribute (unsigned char * p, unsigned char * end) unsigned long addr = 0; size_t bytes = end - p; + assert (end > p); while (bytes) { int j; @@ -12119,8 +12813,20 @@ display_msp430x_attribute (unsigned char * p, if (tag & 1) { - printf ("\"%s\"\n", p); - p += strlen ((char *) p) + 1; + putchar ('"'); + if (p < end - 1) + { + size_t maxlen = (end - p) - 1; + + print_symbol ((int) maxlen, (const char *) p); + p += strnlen ((char *) p, maxlen) + 1; + } + else + { + printf (_("")); + p = (unsigned char *) end; + } + printf ("\"\n"); } else { @@ -12131,6 +12837,7 @@ display_msp430x_attribute (unsigned char * p, break; } + assert (p <= end); return p; } @@ -12142,11 +12849,6 @@ process_attributes (FILE * file, unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int, const unsigned char * const)) { Elf_Internal_Shdr * sect; - unsigned char * contents; - unsigned char * p; - unsigned char * end; - bfd_vma section_len; - bfd_vma len; unsigned i; /* Find the section header so that we get the size. */ @@ -12154,6 +12856,9 @@ process_attributes (FILE * file, i < elf_header.e_shnum; i++, sect++) { + unsigned char * contents; + unsigned char * p; + if (sect->sh_type != proc_type && sect->sh_type != SHT_GNU_ATTRIBUTES) continue; @@ -12165,27 +12870,52 @@ process_attributes (FILE * file, p = contents; if (*p == 'A') { - len = sect->sh_size - 1; + bfd_vma section_len; + + section_len = sect->sh_size - 1; p++; - while (len > 0) + while (section_len > 0) { - int namelen; + bfd_vma attr_len; + unsigned int namelen; bfd_boolean public_section; bfd_boolean gnu_section; - section_len = byte_get (p, 4); + if (section_len <= 4) + { + error (_("Tag section ends prematurely\n")); + break; + } + attr_len = byte_get (p, 4); p += 4; - if (section_len > len) + if (attr_len > section_len) + { + error (_("Bad attribute length (%u > %u)\n"), + (unsigned) attr_len, (unsigned) section_len); + attr_len = section_len; + } + /* PR 17531: file: 001-101425-0.004 */ + else if (attr_len < 5) + { + error (_("Attribute length of %u is too small\n"), (unsigned) attr_len); + break; + } + + section_len -= attr_len; + attr_len -= 4; + + namelen = strnlen ((char *) p, attr_len) + 1; + if (namelen == 0 || namelen >= attr_len) { - printf (_("ERROR: Bad section length (%d > %d)\n"), - (int) section_len, (int) len); - section_len = len; + error (_("Corrupt attribute section name\n")); + break; } - len -= section_len; - printf (_("Attribute Section: %s\n"), p); + printf (_("Attribute Section: ")); + print_symbol (INT_MAX, (const char *) p); + putchar ('\n'); if (public_name && streq ((char *) p, public_name)) public_section = TRUE; @@ -12197,26 +12927,44 @@ process_attributes (FILE * file, else gnu_section = FALSE; - namelen = strlen ((char *) p) + 1; p += namelen; - section_len -= namelen + 4; + attr_len -= namelen; - while (section_len > 0) + while (attr_len > 0 && p < contents + sect->sh_size) { - int tag = *(p++); + int tag; int val; bfd_vma size; + unsigned char * end; + + /* PR binutils/17531: Safe handling of corrupt files. */ + if (attr_len < 6) + { + error (_("Unused bytes at end of section\n")); + section_len = 0; + break; + } + tag = *(p++); size = byte_get (p, 4); - if (size > section_len) + if (size > attr_len) { - printf (_("ERROR: Bad subsection length (%d > %d)\n"), - (int) size, (int) section_len); - size = section_len; + error (_("Bad subsection length (%u > %u)\n"), + (unsigned) size, (unsigned) attr_len); + size = attr_len; + } + /* PR binutils/17531: Safe handling of corrupt files. */ + if (size < 6) + { + error (_("Bad subsection length (%u < 6)\n"), + (unsigned) size); + section_len = 0; + break; } - section_len -= size; + attr_len -= size; end = p + size - 1; + assert (end <= contents + sect->sh_size); p += 4; switch (tag) @@ -12248,29 +12996,33 @@ process_attributes (FILE * file, break; } - if (public_section) + if (public_section && display_pub_attribute != NULL) { while (p < end) p = display_pub_attribute (p, end); + assert (p <= end); } - else if (gnu_section) + else if (gnu_section && display_proc_gnu_attribute != NULL) { while (p < end) p = display_gnu_attribute (p, display_proc_gnu_attribute, end); + assert (p <= end); } - else + else if (p < end) { - printf (_(" Unknown section contexts\n")); + printf (_(" Unknown attribute:\n")); display_raw_attribute (p, end); p = end; } + else + attr_len = 0; } } } else - printf (_("Unknown format '%c'\n"), *p); + printf (_("Unknown format '%c' (%d)\n"), *p, *p); free (contents); } @@ -12361,10 +13113,123 @@ print_mips_pltgot_entry (unsigned char * data, bfd_vma pltgot, bfd_vma addr) return addr + (is_32bit_elf ? 4 : 8); } +static void +print_mips_ases (unsigned int mask) +{ + if (mask & AFL_ASE_DSP) + fputs ("\n\tDSP ASE", stdout); + if (mask & AFL_ASE_DSPR2) + fputs ("\n\tDSP R2 ASE", stdout); + if (mask & AFL_ASE_EVA) + fputs ("\n\tEnhanced VA Scheme", stdout); + if (mask & AFL_ASE_MCU) + fputs ("\n\tMCU (MicroController) ASE", stdout); + if (mask & AFL_ASE_MDMX) + fputs ("\n\tMDMX ASE", stdout); + if (mask & AFL_ASE_MIPS3D) + fputs ("\n\tMIPS-3D ASE", stdout); + if (mask & AFL_ASE_MT) + fputs ("\n\tMT ASE", stdout); + if (mask & AFL_ASE_SMARTMIPS) + fputs ("\n\tSmartMIPS ASE", stdout); + if (mask & AFL_ASE_VIRT) + fputs ("\n\tVZ ASE", stdout); + if (mask & AFL_ASE_MSA) + fputs ("\n\tMSA ASE", stdout); + if (mask & AFL_ASE_MIPS16) + fputs ("\n\tMIPS16 ASE", stdout); + if (mask & AFL_ASE_MICROMIPS) + fputs ("\n\tMICROMIPS ASE", stdout); + if (mask & AFL_ASE_XPA) + fputs ("\n\tXPA ASE", stdout); + if (mask == 0) + fprintf (stdout, "\n\t%s", _("None")); + else if ((mask & ~AFL_ASE_MASK) != 0) + fprintf (stdout, "\n\t%s (%x)", _("Unknown"), mask & ~AFL_ASE_MASK); +} + +static void +print_mips_isa_ext (unsigned int isa_ext) +{ + switch (isa_ext) + { + case 0: + fputs (_("None"), stdout); + break; + case AFL_EXT_XLR: + fputs ("RMI XLR", stdout); + break; + case AFL_EXT_OCTEON2: + fputs ("Cavium Networks Octeon2", stdout); + break; + 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; + case AFL_EXT_5900: + fputs ("Toshiba R5900", stdout); + break; + case AFL_EXT_4650: + fputs ("MIPS R4650", stdout); + break; + case AFL_EXT_4010: + fputs ("LSI R4010", stdout); + break; + case AFL_EXT_4100: + fputs ("NEC VR4100", stdout); + break; + case AFL_EXT_3900: + fputs ("Toshiba R3900", stdout); + break; + case AFL_EXT_10000: + fputs ("MIPS R10000", stdout); + break; + case AFL_EXT_SB1: + fputs ("Broadcom SB-1", stdout); + break; + case AFL_EXT_4111: + fputs ("NEC VR4111/VR4181", stdout); + break; + case AFL_EXT_4120: + fputs ("NEC VR4120", stdout); + break; + case AFL_EXT_5400: + fputs ("NEC VR5400", stdout); + break; + case AFL_EXT_5500: + fputs ("NEC VR5500", stdout); + break; + case AFL_EXT_LOONGSON_2E: + fputs ("ST Microelectronics Loongson 2E", stdout); + break; + case AFL_EXT_LOONGSON_2F: + fputs ("ST Microelectronics Loongson 2F", stdout); + break; + default: + fprintf (stdout, "%s (%d)", _("Unknown"), isa_ext); + } +} + +static int +get_mips_reg_size (int reg_size) +{ + return (reg_size == AFL_REG_NONE) ? 0 + : (reg_size == AFL_REG_32) ? 32 + : (reg_size == AFL_REG_64) ? 64 + : (reg_size == AFL_REG_128) ? 128 + : -1; +} + static int process_mips_specific (FILE * file) { Elf_Internal_Dyn * entry; + Elf_Internal_Shdr *sect = NULL; size_t liblist_offset = 0; size_t liblistno = 0; size_t conflictsno = 0; @@ -12382,12 +13247,66 @@ process_mips_specific (FILE * file) process_attributes (file, NULL, SHT_GNU_ATTRIBUTES, NULL, display_mips_gnu_attribute); + sect = find_section (".MIPS.abiflags"); + + if (sect != NULL) + { + Elf_External_ABIFlags_v0 *abiflags_ext; + Elf_Internal_ABIFlags_v0 abiflags_in; + + if (sizeof (Elf_External_ABIFlags_v0) != sect->sh_size) + fputs ("\nCorrupt ABI Flags section.\n", stdout); + else + { + abiflags_ext = get_data (NULL, file, sect->sh_offset, 1, + sect->sh_size, _("MIPS ABI Flags section")); + if (abiflags_ext) + { + abiflags_in.version = BYTE_GET (abiflags_ext->version); + abiflags_in.isa_level = BYTE_GET (abiflags_ext->isa_level); + abiflags_in.isa_rev = BYTE_GET (abiflags_ext->isa_rev); + abiflags_in.gpr_size = BYTE_GET (abiflags_ext->gpr_size); + abiflags_in.cpr1_size = BYTE_GET (abiflags_ext->cpr1_size); + abiflags_in.cpr2_size = BYTE_GET (abiflags_ext->cpr2_size); + abiflags_in.fp_abi = BYTE_GET (abiflags_ext->fp_abi); + abiflags_in.isa_ext = BYTE_GET (abiflags_ext->isa_ext); + abiflags_in.ases = BYTE_GET (abiflags_ext->ases); + abiflags_in.flags1 = BYTE_GET (abiflags_ext->flags1); + abiflags_in.flags2 = BYTE_GET (abiflags_ext->flags2); + + printf ("\nMIPS ABI Flags Version: %d\n", abiflags_in.version); + printf ("\nISA: MIPS%d", abiflags_in.isa_level); + if (abiflags_in.isa_rev > 1) + printf ("r%d", abiflags_in.isa_rev); + printf ("\nGPR size: %d", + get_mips_reg_size (abiflags_in.gpr_size)); + printf ("\nCPR1 size: %d", + get_mips_reg_size (abiflags_in.cpr1_size)); + printf ("\nCPR2 size: %d", + get_mips_reg_size (abiflags_in.cpr2_size)); + fputs ("\nFP ABI: ", stdout); + print_mips_fp_abi_value (abiflags_in.fp_abi); + fputs ("ISA Extension: ", stdout); + print_mips_isa_ext (abiflags_in.isa_ext); + fputs ("\nASEs:", stdout); + print_mips_ases (abiflags_in.ases); + printf ("\nFLAGS 1: %8.8lx", abiflags_in.flags1); + printf ("\nFLAGS 2: %8.8lx", abiflags_in.flags2); + fputc ('\n', stdout); + free (abiflags_ext); + } + } + } + /* We have a lot of special sections. Thanks SGI! */ if (dynamic_section == NULL) /* No information available. */ return 0; - for (entry = dynamic_section; entry->d_tag != DT_NULL; ++entry) + for (entry = dynamic_section; + /* PR 17531 file: 012-50589-0.004. */ + entry < dynamic_section + dynamic_nent && entry->d_tag != DT_NULL; + ++entry) switch (entry->d_tag) { case DT_MIPS_LIBLIST: @@ -12521,15 +13440,20 @@ process_mips_specific (FILE * file) if (options_offset != 0) { Elf_External_Options * eopt; - Elf_Internal_Shdr * sect = section_headers; Elf_Internal_Options * iopt; Elf_Internal_Options * option; size_t offset; int cnt; + sect = section_headers; /* Find the section header so that we get the size. */ - while (sect->sh_type != SHT_MIPS_OPTIONS) - ++sect; + sect = find_section_by_type (SHT_MIPS_OPTIONS); + /* PR 17533 file: 012-277276-0.004. */ + if (sect == NULL) + { + error (_("No MIPS_OPTIONS header found\n")); + return 0; + } eopt = (Elf_External_Options *) get_data (NULL, file, options_offset, 1, sect->sh_size, _("options")); @@ -12539,7 +13463,7 @@ process_mips_specific (FILE * file) cmalloc ((sect->sh_size / sizeof (eopt)), sizeof (* iopt)); if (iopt == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocatinf space for MIPS options\n")); return 0; } @@ -12564,7 +13488,7 @@ process_mips_specific (FILE * file) } printf (_("\nSection '%s' contains %d entries:\n"), - SECTION_NAME (sect), cnt); + printable_section_name (sect), cnt); option = iopt; @@ -12731,7 +13655,7 @@ process_mips_specific (FILE * file) iconf = (Elf32_Conflict *) cmalloc (conflictsno, sizeof (* iconf)); if (iconf == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for dynamic conflicts\n")); return 0; } @@ -12772,15 +13696,22 @@ process_mips_specific (FILE * file) for (cnt = 0; cnt < conflictsno; ++cnt) { - Elf_Internal_Sym * psym = & dynamic_symbols[iconf[cnt]]; - printf ("%5lu: %8lu ", (unsigned long) cnt, iconf[cnt]); - print_vma (psym->st_value, FULL_HEX); - putchar (' '); - if (VALID_DYNAMIC_NAME (psym->st_name)) - print_symbol (25, GET_DYNAMIC_NAME (psym->st_name)); + + if (iconf[cnt] >= num_dynamic_syms) + printf (_("")); else - printf (_(""), psym->st_name); + { + Elf_Internal_Sym * psym; + + psym = & dynamic_symbols[iconf[cnt]]; + print_vma (psym->st_value, FULL_HEX); + putchar (' '); + if (VALID_DYNAMIC_NAME (psym->st_name)) + print_symbol (25, GET_DYNAMIC_NAME (psym->st_name)); + else + printf (_(""), psym->st_name); + } putchar ('\n'); } @@ -12797,8 +13728,17 @@ process_mips_specific (FILE * file) ent = pltgot; addr_size = (is_32bit_elf ? 4 : 8); local_end = pltgot + local_gotno * addr_size; - global_end = local_end + (symtabno - gotsym) * addr_size; + /* PR binutils/17533 file: 012-111227-0.004 */ + if (symtabno < gotsym) + { + error (_("The GOT symbol offset (%lu) is greater than the symbol table size (%lu)\n"), + (long) gotsym, (long) symtabno); + return 0; + } + + global_end = local_end + (symtabno - gotsym) * addr_size; + assert (global_end >= local_end); offset = offset_from_vma (file, pltgot, global_end - pltgot); data = (unsigned char *) get_data (NULL, file, offset, global_end - pltgot, 1, @@ -12855,21 +13795,32 @@ process_mips_specific (FILE * file) _("Ndx"), _("Name")); sym_width = (is_32bit_elf ? 80 : 160) - 28 - addr_size * 6 - 1; + for (i = gotsym; i < symtabno; i++) { - Elf_Internal_Sym * psym; - - psym = dynamic_symbols + i; ent = print_mips_got_entry (data, pltgot, ent); printf (" "); - print_vma (psym->st_value, LONG_HEX); - printf (" %-7s %3s ", - get_symbol_type (ELF_ST_TYPE (psym->st_info)), - get_symbol_index_type (psym->st_shndx)); - if (VALID_DYNAMIC_NAME (psym->st_name)) - print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name)); + + if (dynamic_symbols == NULL) + printf (_("")); + else if (i < num_dynamic_syms) + { + Elf_Internal_Sym * psym = dynamic_symbols + i; + + print_vma (psym->st_value, LONG_HEX); + printf (" %-7s %3s ", + get_symbol_type (ELF_ST_TYPE (psym->st_info)), + get_symbol_index_type (psym->st_shndx)); + + if (VALID_DYNAMIC_NAME (psym->st_name)) + print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name)); + else + printf (_(""), psym->st_name); + } else - printf (_(""), psym->st_name); + printf (_(""), + (unsigned long) i); + printf ("\n"); } printf ("\n"); @@ -12928,19 +13879,26 @@ process_mips_specific (FILE * file) sym_width = (is_32bit_elf ? 80 : 160) - 17 - addr_size * 6 - 1; for (i = 0; i < count; i++) { - Elf_Internal_Sym * psym; + unsigned long idx = get_reloc_symindex (rels[i].r_info); - psym = dynamic_symbols + get_reloc_symindex (rels[i].r_info); ent = print_mips_pltgot_entry (data, mips_pltgot, ent); printf (" "); - print_vma (psym->st_value, LONG_HEX); - printf (" %-7s %3s ", - get_symbol_type (ELF_ST_TYPE (psym->st_info)), - get_symbol_index_type (psym->st_shndx)); - if (VALID_DYNAMIC_NAME (psym->st_name)) - print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name)); + + if (idx >= num_dynamic_syms) + printf (_(""), idx); else - printf (_(""), psym->st_name); + { + Elf_Internal_Sym * psym = dynamic_symbols + idx; + + print_vma (psym->st_value, LONG_HEX); + printf (" %-7s %3s ", + get_symbol_type (ELF_ST_TYPE (psym->st_info)), + get_symbol_index_type (psym->st_shndx)); + if (VALID_DYNAMIC_NAME (psym->st_name)) + print_symbol (sym_width, GET_DYNAMIC_NAME (psym->st_name)); + else + printf (_(""), psym->st_name); + } printf ("\n"); } printf ("\n"); @@ -12953,6 +13911,40 @@ process_mips_specific (FILE * file) return 1; } +static int +process_nds32_specific (FILE * file) +{ + Elf_Internal_Shdr *sect = NULL; + + sect = find_section (".nds32_e_flags"); + if (sect != NULL) + { + unsigned int *flag; + + printf ("\nNDS32 elf flags section:\n"); + flag = get_data (NULL, file, sect->sh_offset, 1, + sect->sh_size, _("NDS32 elf flags section")); + + switch ((*flag) & 0x3) + { + case 0: + printf ("(VEC_SIZE):\tNo entry.\n"); + break; + case 1: + printf ("(VEC_SIZE):\t4 bytes\n"); + break; + case 2: + printf ("(VEC_SIZE):\t16 bytes\n"); + break; + case 3: + printf ("(VEC_SIZE):\treserved\n"); + break; + } + } + + return TRUE; +} + static int process_gnu_liblist (FILE * file) { @@ -12998,7 +13990,7 @@ process_gnu_liblist (FILE * file) strtab_size = string_sec->sh_size; printf (_("\nLibrary list section '%s' contains %lu entries:\n"), - SECTION_NAME (section), + printable_section_name (section), (unsigned long) (section->sh_size / sizeof (Elf32_External_Lib))); puts (_(" Library Time Stamp Checksum Version Flags")); @@ -13262,6 +14254,13 @@ print_gnu_note (Elf_Internal_Note *pnote) unsigned long os, major, minor, subminor; const char *osname; + /* PR 17531: file: 030-599401-0.004. */ + if (pnote->descsz < 16) + { + printf (_(" \n")); + break; + } + os = byte_get ((unsigned char *) pnote->descdata, 4); major = byte_get ((unsigned char *) pnote->descdata + 4, 4); minor = byte_get ((unsigned char *) pnote->descdata + 8, 4); @@ -13293,6 +14292,17 @@ print_gnu_note (Elf_Internal_Note *pnote) major, minor, subminor); } break; + + case NT_GNU_GOLD_VERSION: + { + unsigned long i; + + printf (_(" Version: ")); + for (i = 0; i < pnote->descsz && pnote->descdata[i] != '\0'; ++i) + printf ("%c", pnote->descdata[i]); + printf ("\n"); + } + break; } return 1; @@ -13680,7 +14690,7 @@ process_corefile_note_segment (FILE * file, bfd_vma offset, bfd_vma length) if (temp == NULL) { - error (_("Out of memory\n")); + error (_("Out of memory allocating space for inote name\n")); res = 0; break; } @@ -13734,15 +14744,23 @@ process_note_sections (FILE * file) { Elf_Internal_Shdr * section; unsigned long i; + int n = 0; int res = 1; for (i = 0, section = section_headers; i < elf_header.e_shnum && section != NULL; i++, section++) if (section->sh_type == SHT_NOTE) - res &= process_corefile_note_segment (file, - (bfd_vma) section->sh_offset, - (bfd_vma) section->sh_size); + { + res &= process_corefile_note_segment (file, + (bfd_vma) section->sh_offset, + (bfd_vma) section->sh_size); + n++; + } + + if (n == 0) + /* Try processing NOTE segments instead. */ + return process_corefile_note_segments (file); return res; } @@ -13779,6 +14797,9 @@ process_arch_specific (FILE * file) case EM_MIPS_RS3_LE: return process_mips_specific (file); break; + case EM_NDS32: + return process_nds32_specific (file); + break; case EM_PPC: return process_power_specific (file); break; @@ -13883,9 +14904,9 @@ get_file_header (FILE * file) /* There may be some extensions in the first section header. Don't bomb if we can't read it. */ if (is_32bit_elf) - get_32bit_section_headers (file, 1); + get_32bit_section_headers (file, TRUE); else - get_64bit_section_headers (file, 1); + get_64bit_section_headers (file, TRUE); } return 1; @@ -14327,6 +15348,8 @@ process_file (char * file_name) return 1; } + current_file_size = (bfd_size_type) statbuf.st_size; + if (memcmp (armag, ARMAG, SARMAG) == 0) ret = process_archive (file_name, file, FALSE); else if (memcmp (armag, ARMAGT, SARMAG) == 0) @@ -14344,6 +15367,7 @@ process_file (char * file_name) fclose (file); + current_file_size = 0; return ret; } -- cgit v1.2.3