summaryrefslogtreecommitdiffstats
path: root/binutils-2.25/binutils/readelf.c
diff options
context:
space:
mode:
authorAndrew Hsieh <andrewhsieh@google.com>2014-12-09 17:57:18 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2014-12-09 19:50:14 +0800
commit5e8c1cf25beccac1d22d10dc866912394f42771b (patch)
treeee16b70f804484dc8e434e647e699ab50da2620f /binutils-2.25/binutils/readelf.c
parent8eebd7953384e6662ca926b003f2cdda8ccd3ee5 (diff)
downloadtoolchain_binutils-5e8c1cf25beccac1d22d10dc866912394f42771b.tar.gz
toolchain_binutils-5e8c1cf25beccac1d22d10dc866912394f42771b.tar.bz2
toolchain_binutils-5e8c1cf25beccac1d22d10dc866912394f42771b.zip
[2.25] sync to a30720e3e633f275250e26f85ccae5dbdddfb6c6
local patches will be re-applied later commit a30720e3e633f275250e26f85ccae5dbdddfb6c6 Author: Alan Modra <amodra@gmail.com> Date: Wed Nov 19 10:30:16 2014 +1030 daily update Change-Id: Ieb2a3f4dd2ecb289ac5305ff08d428b2847494ab
Diffstat (limited to 'binutils-2.25/binutils/readelf.c')
-rw-r--r--binutils-2.25/binutils/readelf.c1730
1 files changed, 1377 insertions, 353 deletions
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 <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com>
@@ -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 _("<corrupt>");
+
+ 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,_(", <unknown>"));
}
+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, ", <unrecognized ABI>");
+ 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, ", <unrecognized ELF version number>");
+ 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, ", <unrecognized architecture>");
+ /* 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,8 +7126,21 @@ get_unwind_section_word (struct arm_unw_aux_info * aux,
else if (arm_sec->rel_type == SHT_RELA)
offset = rp->r_addend;
else
- abort ();
+ {
+ 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);
@@ -6709,38 +7148,54 @@ get_unwind_section_word (struct arm_unw_aux_info * aux,
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 (_("<corrupt: %" BFD_VMA_FMT "d>"), 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 (_("<corrupt: %s>"), 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, &section, & 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 (_("<corrupt time val: %lx"),
+ (unsigned long) atime);
+ else
+ 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);
}
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)
- : _("<corrupt>"));
+ 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)
- : _("<corrupt>"));
+ 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";
@@ -9201,6 +9686,19 @@ get_ia64_symbol_other (unsigned int other)
}
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, _("<localentry>: %d"),
+ PPC64_LOCAL_ENTRY_OFFSET (other));
+ return buf;
+ }
+ return NULL;
+}
+
+static const char *
get_symbol_other (unsigned int other)
{
const char * result = NULL;
@@ -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 (_("<No info available for dynamic symbol number %lu>\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 (_("<corrupt index>"));
+ else if (VALID_DYNAMIC_NAME (dynamic_symbols[i].st_name))
print_symbol (30, GET_DYNAMIC_NAME (dynamic_symbols[i].st_name));
else
printf (_("<corrupt: %19ld>"), 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 (_("<corrupt>\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 (_("<corrupt tag>\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 (_("<corrupt string tag>"));
+ 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 (_("<corrupt>"));
+ 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 = <corrupt>\n"), val);
+ printf (_("<corrupt>\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 (_("<corrupt>"));
+ 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 (_("<corrupt>"));
+ 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 (_("<corrupt>"));
+ 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 (_("<corrupt>"));
+ 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 (_("<corrupt symbol index>"));
else
- printf (_("<corrupt: %14ld>"), 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 (_("<corrupt: %14ld>"), 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 (_("<no dynamic symbols>"));
+ 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 (_("<corrupt: %14ld>"), psym->st_name);
+ }
else
- printf (_("<corrupt: %14ld>"), psym->st_name);
+ printf (_("<symbol index %lu exceeds number of dynamic symbols>"),
+ (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 (_("<corrupt symbol index: %lu>"), idx);
else
- printf (_("<corrupt: %14ld>"), 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 (_("<corrupt: %14ld>"), psym->st_name);
+ }
printf ("\n");
}
printf ("\n");
@@ -12954,6 +13912,40 @@ process_mips_specific (FILE * file)
}
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)
{
Elf_Internal_Shdr * section;
@@ -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 (_(" <corrupt GNU_ABI_TAG>\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;
}