/* readelf.c -- display contents of an ELF format file
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010, 2011, 2012
- 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>
#ifdef HAVE_ZLIB_H
#include <zlib.h>
#endif
+#ifdef HAVE_WCHAR_H
+#include <wchar.h>
+#endif
#if __GNUC__ >= 2
/* Define BFD64 here, even if our default architecture is 32 bit ELF
#define RELOC_MACROS_GEN_FUNC
+#include "elf/aarch64.h"
#include "elf/alpha.h"
#include "elf/arc.h"
#include "elf/arm.h"
#include "elf/m68hc11.h"
#include "elf/mcore.h"
#include "elf/mep.h"
+#include "elf/metag.h"
#include "elf/microblaze.h"
#include "elf/mips.h"
#include "elf/mmix.h"
#include "elf/moxie.h"
#include "elf/mt.h"
#include "elf/msp430.h"
-#include "elf/or32.h"
+#include "elf/nds32.h"
+#include "elf/nios2.h"
+#include "elf/or1k.h"
#include "elf/pj.h"
#include "elf/ppc.h"
#include "elf/ppc64.h"
#include "safe-ctype.h"
#include "filenames.h"
+#ifndef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &(((TYPE *) 0)->MEMBER))
+#endif
+
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;
return 0;
}
-/* Display a symbol on stdout. Handles the display of non-printing characters.
+/* Display a symbol on stdout. Handles the display of control characters and
+ multibye characters (assuming the host environment supports them).
+
+ Display at most abs(WIDTH) characters, truncating as necessary, unless do_wide is true.
- If DO_WIDE is not true then format the symbol to be at most WIDTH characters,
- truncating as necessary. If WIDTH is negative then format the string to be
- exactly - WIDTH characters, truncating or padding as necessary.
+ If WIDTH is negative then ensure that the output is at least (- WIDTH) characters,
+ padding as necessary.
Returns the number of emitted characters. */
static unsigned int
print_symbol (int width, const char *symbol)
{
- const char *c;
bfd_boolean extra_padding = FALSE;
- unsigned int num_printed = 0;
+ int num_printed = 0;
+#ifdef HAVE_MBSTATE_T
+ mbstate_t state;
+#endif
+ int width_remaining;
- if (do_wide)
- {
- /* Set the width to a very large value. This simplifies the
- code below. */
- width = INT_MAX;
- }
- else if (width < 0)
+ if (width < 0)
{
/* Keep the width positive. This also helps. */
width = - width;
extra_padding = TRUE;
}
- while (width)
- {
- int len;
-
- c = symbol;
-
- /* Look for non-printing symbols inside the symbol's name.
- This test is triggered in particular by the names generated
- by the assembler for local labels. */
- while (ISPRINT (*c))
- c++;
-
- len = c - symbol;
-
- if (len)
- {
- if (len > width)
- len = width;
+ if (do_wide)
+ /* Set the remaining width to a very large value.
+ This simplifies the code below. */
+ width_remaining = INT_MAX;
+ else
+ width_remaining = width;
- printf ("%.*s", len, symbol);
+#ifdef HAVE_MBSTATE_T
+ /* Initialise the multibyte conversion state. */
+ memset (& state, 0, sizeof (state));
+#endif
- width -= len;
- num_printed += len;
- }
+ while (width_remaining)
+ {
+ size_t n;
+ const char c = *symbol++;
- if (*c == 0 || width == 0)
+ if (c == 0)
break;
- /* Now display the non-printing character, if
- there is room left in which to dipslay it. */
- if ((unsigned char) *c < 32)
+ /* Do not print control characters directly as they can affect terminal
+ settings. Such characters usually appear in the names generated
+ by the assembler for local labels. */
+ if (ISCNTRL (c))
{
- if (width < 2)
+ if (width_remaining < 2)
break;
- printf ("^%c", *c + 0x40);
-
- width -= 2;
+ printf ("^%c", c + 0x40);
+ width_remaining -= 2;
num_printed += 2;
}
+ else if (ISPRINT (c))
+ {
+ putchar (c);
+ width_remaining --;
+ num_printed ++;
+ }
else
{
- if (width < 6)
- break;
-
- printf ("<0x%.2x>", (unsigned char) *c);
-
- width -= 6;
- num_printed += 6;
+#ifdef HAVE_MBSTATE_T
+ wchar_t w;
+#endif
+ /* Let printf do the hard work of displaying multibyte characters. */
+ printf ("%.1s", symbol - 1);
+ width_remaining --;
+ num_printed ++;
+
+#ifdef HAVE_MBSTATE_T
+ /* Try to find out how many bytes made up the character that was
+ just printed. Advance the symbol pointer past the bytes that
+ were displayed. */
+ n = mbrtowc (& w, symbol - 1, MB_CUR_MAX, & state);
+#else
+ n = 1;
+#endif
+ if (n != (size_t) -1 && n != (size_t) -2 && n > 0)
+ symbol += (n - 1);
}
-
- symbol = c + 1;
}
- if (extra_padding && width > 0)
+ if (extra_padding && num_printed < width)
{
/* Fill in the remaining spaces. */
- printf ("%-*s", width, " ");
- num_printed += 2;
+ printf ("%-*s", width - num_printed, " ");
+ num_printed = width;
}
return num_printed;
return NULL;
}
+/* Return a pointer to section NAME, or NULL if no such section exists,
+ restricted to the list of sections given in SET. */
+
+static Elf_Internal_Shdr *
+find_section_in_set (const char * name, unsigned int * set)
+{
+ unsigned int i;
+
+ if (set != NULL)
+ {
+ while ((i = *set++) > 0)
+ if (streq (SECTION_NAME (section_headers + i), name))
+ return section_headers + i;
+ }
+
+ return find_section (name);
+}
+
/* Read an unsigned LEB128 encoded value from p. Set *PLEN to the number of
bytes read. */
-static unsigned long
-read_uleb128 (unsigned char *data, unsigned int *length_return)
+static inline unsigned long
+read_uleb128 (unsigned char *data,
+ unsigned int *length_return,
+ const unsigned char * const end)
{
- return read_leb128 (data, length_return, 0);
+ return read_leb128 (data, length_return, FALSE, end);
}
/* Return true if the current file is for IA-64 machine and OpenVMS ABI.
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;
/* Targets that use RELA relocations. */
case EM_68K:
case EM_860:
+ case EM_AARCH64:
case EM_ADAPTEVA_EPIPHANY:
case EM_ALPHA:
case EM_ALTERA_NIOS2:
case EM_M32R:
case EM_MCORE:
case EM_CYGNUS_MEP:
+ case EM_METAG:
case EM_MMIX:
case EM_MN10200:
case EM_CYGNUS_MN10200:
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:
case EM_TI_C6000:
case EM_TILEGX:
case EM_TILEPRO:
+ case EM_V800:
case EM_V850:
case EM_CYGNUS_V850:
case EM_VAX:
return is_32bit_elf ? ELF32_R_SYM (reloc_info) : ELF64_R_SYM (reloc_info);
}
+static inline bfd_boolean
+uses_msp430x_relocs (void)
+{
+ return
+ elf_header.e_machine == EM_MSP430 /* Paranoia. */
+ /* GCC uses osabi == ELFOSBI_STANDALONE. */
+ && (((elf_header.e_flags & EF_MSP430_MACH) == E_MSP430_MACH_MSP430X)
+ /* TI compiler uses ELFOSABI_NONE. */
+ || (elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE));
+}
+
/* Display the contents of the relocation data found at the specified
offset. */
rtype = NULL;
break;
+ case EM_AARCH64:
+ rtype = elf_aarch64_reloc_type (type);
+ break;
+
case EM_M32R:
case EM_CYGNUS_M32R:
rtype = elf_m32r_reloc_type (type);
rtype = elf_spu_reloc_type (type);
break;
+ case EM_V800:
+ rtype = v800_reloc_type (type);
+ break;
case EM_V850:
case EM_CYGNUS_V850:
rtype = v850_reloc_type (type);
break;
case EM_MSP430:
+ if (uses_msp430x_relocs ())
+ {
+ rtype = elf_msp430x_reloc_type (type);
+ break;
+ }
case EM_MSP430_OLD:
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;
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:
rtype = elf_rx_reloc_type (type);
break;
+ case EM_METAG:
+ rtype = elf_metag_reloc_type (type);
+ break;
+
case EM_XC16X:
case EM_C166:
rtype = elf_xc16x_reloc_type (type);
case EM_XGATE:
rtype = elf_xgate_reloc_type (type);
break;
+
+ case EM_ALTERA_NIOS2:
+ rtype = elf_nios2_reloc_type (type);
+ break;
}
if (rtype == NULL)
}
else if (is_rela)
{
- printf ("%*c", is_32bit_elf ?
- (do_wide ? 34 : 28) : (do_wide ? 26 : 20), ' ');
- print_vma (rels[i].r_addend, LONG_HEX);
+ bfd_signed_vma off = rels[i].r_addend;
+
+ printf ("%*c", is_32bit_elf ? 12 : 20, ' ');
+ if (off < 0)
+ printf ("-%" BFD_VMA_FMT "x", - off);
+ else
+ printf ("%" BFD_VMA_FMT "x", off);
}
if (elf_header.e_machine == EM_SPARCV9
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;
}
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;
}
}
}
+static const char *
+get_nios2_dynamic_type (unsigned long type)
+{
+ switch (type)
+ {
+ case DT_NIOS2_GP: return "NIOS2_GP";
+ default:
+ return NULL;
+ }
+}
+
static const char *
get_dynamic_type (unsigned long type)
{
case EM_TI_C6000:
result = get_tic6x_dynamic_type (type);
break;
+ case EM_ALTERA_NIOS2:
+ result = get_nios2_dynamic_type (type);
+ break;
default:
result = NULL;
break;
switch (e_machine)
{
case EM_NONE: return _("None");
+ case EM_AARCH64: return "AArch64";
case EM_M32: return "WE32100";
case EM_SPARC: return "Sparc";
case EM_SPU: return "SPU";
case EM_960: return "Intel 90860";
case EM_PPC: return "PowerPC";
case EM_PPC64: return "PowerPC64";
- case EM_V800: return "NEC V800";
case EM_FR20: return "Fujitsu FR20";
case EM_RH32: return "TRW RH32";
case EM_MCORE: return "MCORE";
case EM_IA_64: return "Intel IA-64";
case EM_MIPS_X: return "Stanford MIPS-X";
case EM_COLDFIRE: return "Motorola Coldfire";
- case EM_68HC12: return "Motorola M68HC12";
case EM_ALPHA: return "Alpha";
case EM_CYGNUS_D10V:
case EM_D10V: return "d10v";
case EM_CYGNUS_M32R:
case EM_M32R: return "Renesas M32R (formerly Mitsubishi M32r)";
case EM_CYGNUS_V850:
+ case EM_V800: return "Renesas V850 (using RH850 ABI)";
case EM_V850: return "Renesas V850";
case EM_CYGNUS_MN10300:
case EM_MN10300: return "mn10300";
case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 bit microcontroller";
case EM_ST7: return "STMicroelectronics ST7 8-bit microcontroller";
case EM_68HC16: return "Motorola MC68HC16 Microcontroller";
+ case EM_68HC12: return "Motorola MC68HC12 Microcontroller";
case EM_68HC11: return "Motorola MC68HC11 Microcontroller";
case EM_68HC08: return "Motorola MC68HC08 Microcontroller";
case EM_68HC05: return "Motorola MC68HC05 Microcontroller";
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";
case EM_MICROBLAZE_OLD: return "Xilinx MicroBlaze";
case EM_RL78: return "Renesas RL78";
case EM_RX: return "Renesas RX";
- case EM_METAG: return "Imagination Technologies META processor architecture";
+ case EM_METAG: return "Imagination Technologies Meta processor architecture";
case EM_MCST_ELBRUS: return "MCST Elbrus general purpose hardware architecture";
case EM_ECOG16: return "Cyan Technology eCOG16 family";
case EM_ETPU: return "Freescale Extended Time Processing Unit";
case EF_ARM_EABI_VER4:
strcat (buf, ", Version4 EABI");
- goto eabi;
+ while (e_flags)
+ {
+ unsigned flag;
+
+ /* Process flags one bit at a time. */
+ flag = e_flags & - e_flags;
+ e_flags &= ~ flag;
+
+ switch (flag)
+ {
+ case EF_ARM_BE8:
+ strcat (buf, ", BE8");
+ break;
+
+ case EF_ARM_LE8:
+ strcat (buf, ", LE8");
+ break;
+
+ default:
+ unknown = 1;
+ break;
+ }
+ break;
+ }
+ break;
case EF_ARM_EABI_VER5:
strcat (buf, ", Version5 EABI");
- eabi:
while (e_flags)
{
unsigned flag;
strcat (buf, ", LE8");
break;
+ case EF_ARM_ABI_FLOAT_SOFT: /* Conflicts with EF_ARM_SOFT_FLOAT. */
+ strcat (buf, ", soft-float ABI");
+ break;
+
+ case EF_ARM_ABI_FLOAT_HARD: /* Conflicts with EF_ARM_VFP_FLOAT. */
+ strcat (buf, ", hard-float ABI");
+ break;
+
default:
unknown = 1;
break;
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)
{
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");
+
+ if (e_flags & EF_V800_850E3)
+ strcat (buf, ", V3 architecture");
+
+ if ((e_flags & (EF_RH850_FPU_DOUBLE | EF_RH850_FPU_SINGLE)) == 0)
+ strcat (buf, ", FPU not used");
+
+ if ((e_flags & (EF_RH850_REGMODE22 | EF_RH850_REGMODE32)) == 0)
+ strcat (buf, ", regmode: COMMON");
+
+ if ((e_flags & (EF_RH850_GP_FIX | EF_RH850_GP_NOFIX)) == 0)
+ strcat (buf, ", r4 not used");
+
+ if ((e_flags & (EF_RH850_EP_FIX | EF_RH850_EP_NOFIX)) == 0)
+ strcat (buf, ", r30 not used");
+
+ if ((e_flags & (EF_RH850_TP_FIX | EF_RH850_TP_NOFIX)) == 0)
+ strcat (buf, ", r5 not used");
+
+ if ((e_flags & (EF_RH850_REG2_RESERVE | EF_RH850_REG2_NORESERVE)) == 0)
+ strcat (buf, ", r2 not used");
+
+ for (e_flags &= 0xFFFF; e_flags; e_flags &= ~ (e_flags & - e_flags))
+ {
+ switch (e_flags & - e_flags)
+ {
+ case EF_RH850_FPU_DOUBLE: strcat (buf, ", double precision FPU"); break;
+ case EF_RH850_FPU_SINGLE: strcat (buf, ", single precision FPU"); break;
+ case EF_RH850_SIMD: strcat (buf, ", SIMD"); break;
+ case EF_RH850_CACHE: strcat (buf, ", CACHE"); break;
+ case EF_RH850_MMU: strcat (buf, ", MMU"); break;
+ case EF_RH850_REGMODE22: strcat (buf, ", regmode:22"); break;
+ case EF_RH850_REGMODE32: strcat (buf, ", regmode:23"); break;
+ case EF_RH850_DATA_ALIGN8: strcat (buf, ", 8-byte alignment"); break;
+ case EF_RH850_GP_FIX: strcat (buf, ", r4 fixed"); break;
+ case EF_RH850_GP_NOFIX: strcat (buf, ", r4 free"); break;
+ case EF_RH850_EP_FIX: strcat (buf, ", r30 fixed"); break;
+ case EF_RH850_EP_NOFIX: strcat (buf, ", r30 free"); break;
+ case EF_RH850_TP_FIX: strcat (buf, ", r5 fixed"); break;
+ case EF_RH850_TP_NOFIX: strcat (buf, ", r5 free"); break;
+ case EF_RH850_REG2_RESERVE: strcat (buf, ", r2 fixed"); break;
+ case EF_RH850_REG2_NORESERVE: strcat (buf, ", r2 free"); break;
+ default: break;
+ }
+ }
+ break;
+
case EM_V850:
case EM_CYGNUS_V850:
switch (e_flags & EF_V850_ARCH)
{
+ case E_V850E3V5_ARCH:
+ strcat (buf, ", v850e3v5");
+ break;
case E_V850E2V3_ARCH:
strcat (buf, ", v850e2v3");
break;
if (e_flags & EF_MIPS_32BITMODE)
strcat (buf, ", 32bitmode");
+ if (e_flags & EF_MIPS_NAN2008)
+ strcat (buf, ", nan2008");
+
+ if (e_flags & EF_MIPS_FP64)
+ strcat (buf, ", fp64");
+
switch ((e_flags & EF_MIPS_MACH))
{
case E_MIPS_MACH_3900: strcat (buf, ", 3900"); break;
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:
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;
- if (e_flags & EF_SH_PIC)
- strcat (buf, ", pic");
-
- if (e_flags & EF_SH_FDPIC)
- strcat (buf, ", fdpic");
+ case EM_NDS32:
+ decode_NDS32_machine_flags (e_flags, buf, sizeof buf);
break;
case EM_SH:
default: strcat (buf, _(", unknown ISA")); break;
}
+ if (e_flags & EF_SH_PIC)
+ strcat (buf, ", pic");
+
+ 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)
strcat (buf, ", G-Float");
break;
+ 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:
if (e_flags & E_FLAG_RX_64BIT_DOUBLES)
strcat (buf, ", 64-bit doubles");
if (e_flags & E_FLAG_RX_DSP)
strcat (buf, ", dsp");
if (e_flags & E_FLAG_RX_PID)
- strcat (buf, ", pid");
+ strcat (buf, ", pid");
+ if (e_flags & E_FLAG_RX_ABI)
+ strcat (buf, ", RX ABI");
break;
case EM_S390:
if ((e_flags & EF_C6000_REL))
strcat (buf, ", relocatable module");
break;
+
+ case EM_MSP430:
+ strcat (buf, _(": architecture variant: "));
+ switch (e_flags & EF_MSP430_MACH)
+ {
+ case E_MSP430_MACH_MSP430x11: strcat (buf, "MSP430x11"); break;
+ case E_MSP430_MACH_MSP430x11x1 : strcat (buf, "MSP430x11x1 "); break;
+ case E_MSP430_MACH_MSP430x12: strcat (buf, "MSP430x12"); break;
+ case E_MSP430_MACH_MSP430x13: strcat (buf, "MSP430x13"); break;
+ case E_MSP430_MACH_MSP430x14: strcat (buf, "MSP430x14"); break;
+ case E_MSP430_MACH_MSP430x15: strcat (buf, "MSP430x15"); break;
+ case E_MSP430_MACH_MSP430x16: strcat (buf, "MSP430x16"); break;
+ case E_MSP430_MACH_MSP430x31: strcat (buf, "MSP430x31"); break;
+ case E_MSP430_MACH_MSP430x32: strcat (buf, "MSP430x32"); break;
+ case E_MSP430_MACH_MSP430x33: strcat (buf, "MSP430x33"); break;
+ case E_MSP430_MACH_MSP430x41: strcat (buf, "MSP430x41"); break;
+ case E_MSP430_MACH_MSP430x42: strcat (buf, "MSP430x42"); break;
+ case E_MSP430_MACH_MSP430x43: strcat (buf, "MSP430x43"); break;
+ case E_MSP430_MACH_MSP430x44: strcat (buf, "MSP430x44"); break;
+ case E_MSP430_MACH_MSP430X : strcat (buf, "MSP430X"); break;
+ default:
+ strcat (buf, _(": unknown")); break;
+ }
+
+ if (e_flags & ~ EF_MSP430_MACH)
+ strcat (buf, _(": unknown extra flag bits also present"));
}
}
}
}
+static const char *
+get_aarch64_segment_type (unsigned long type)
+{
+ switch (type)
+ {
+ case PT_AARCH64_ARCHEXT:
+ return "AARCH64_ARCHEXT";
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
static const char *
get_arm_segment_type (unsigned long type)
{
return "RTPROC";
case PT_MIPS_OPTIONS:
return "OPTIONS";
+ case PT_MIPS_ABIFLAGS:
+ return "ABIFLAGS";
default:
break;
}
switch (elf_header.e_machine)
{
+ case EM_AARCH64:
+ result = get_aarch64_segment_type (p_type);
+ break;
case EM_ARM:
result = get_arm_segment_type (p_type);
break;
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;
}
return NULL;
}
+static const char *
+get_aarch64_section_type_name (unsigned int sh_type)
+{
+ switch (sh_type)
+ {
+ case SHT_AARCH64_ATTRIBUTES:
+ return "AARCH64_ATTRIBUTES";
+ default:
+ break;
+ }
+ return NULL;
+}
+
static const char *
get_arm_section_type_name (unsigned int sh_type)
{
return NULL;
}
+static const char *
+get_msp430x_section_type_name (unsigned int sh_type)
+{
+ switch (sh_type)
+ {
+ case SHT_MSP430_SEC_FLAGS: return "MSP430_SEC_FLAGS";
+ case SHT_MSP430_SYM_ALIASES: return "MSP430_SYM_ALIASES";
+ case SHT_MSP430_ATTRIBUTES: return "MSP430_ATTRIBUTES";
+ default: return NULL;
+ }
+}
+
static const char *
get_section_type_name (unsigned int sh_type)
{
case EM_K1OM:
result = get_x86_64_section_type_name (sh_type);
break;
+ case EM_AARCH64:
+ result = get_aarch64_section_type_name (sh_type);
+ break;
case EM_ARM:
result = get_arm_section_type_name (sh_type);
break;
case EM_TI_C6000:
result = get_tic6x_section_type_name (sh_type);
break;
+ case EM_MSP430:
+ result = get_msp430x_section_type_name (sh_type);
+ break;
default:
result = NULL;
break;
#define OPTION_DYN_SYMS 513
#define OPTION_DWARF_DEPTH 514
#define OPTION_DWARF_START 515
+#define OPTION_DWARF_CHECK 516
static struct option options[] =
{
{"dwarf-depth", required_argument, 0, OPTION_DWARF_DEPTH},
{"dwarf-start", required_argument, 0, OPTION_DWARF_START},
+ {"dwarf-check", no_argument, 0, OPTION_DWARF_CHECK},
{"version", no_argument, 0, 'v'},
{"wide", no_argument, 0, 'W'},
-w[lLiaprmfFsoRt] or\n\
--debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,\n\
=frames-interp,=str,=loc,=Ranges,=pubtypes,\n\
- =gdb_index,=trace_info,=trace_abbrev,=trace_aranges]\n\
+ =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,\n\
+ =addr,=cu_index]\n\
Display the contents of DWARF2 debug sections\n"));
fprintf (stream, _("\
--dwarf-depth=N Do not display DIEs at depth N or greater\n\
dwarf_start_die = strtoul (optarg, & cp, 0);
}
break;
+ case OPTION_DWARF_CHECK:
+ dwarf_check = 1;
+ break;
case OPTION_DYN_SYMS:
do_dyn_syms++;
break;
}
}
+ if (do_segments)
+ putc ('\n', stdout);
+
switch (segment->p_type)
{
case PT_DYNAMIC:
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. */
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"));
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)
goto exit_point;
}
+ if (section->sh_size > current_file_size)
+ {
+ error (_("Section %s has an invalid sh_size of 0x%lx\n"),
+ SECTION_NAME (section), section->sh_size);
+ goto exit_point;
+ }
+
number = section->sh_size / section->sh_entsize;
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
goto exit_point;
}
+ if (section->sh_size > current_file_size)
+ {
+ error (_("Section %s has an invalid sh_size of 0x%lx\n"),
+ SECTION_NAME (section), section->sh_size);
+ goto exit_point;
+ }
+
number = section->sh_size / section->sh_entsize;
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
break;
}
-#define CHECK_ENTSIZE_VALUES(section, i, size32, size64) \
- do \
- { \
- size_t expected_entsize \
- = is_32bit_elf ? size32 : size64; \
- if (section->sh_entsize != expected_entsize) \
- error (_("Section %d has invalid sh_entsize %lx (expected %lx)\n"), \
- i, (unsigned long int) section->sh_entsize, \
- (unsigned long int) expected_entsize); \
- 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) \
+ { \
+ 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) \
+
+#define CHECK_ENTSIZE(section, i, type) \
CHECK_ENTSIZE_VALUES (section, i, sizeof (Elf32_External_##type), \
sizeof (Elf64_External_##type))
else if ((do_debugging || do_debug_info || do_debug_abbrevs
|| do_debug_lines || do_debug_pubnames || do_debug_pubtypes
|| do_debug_aranges || do_debug_frames || do_debug_macinfo
- || do_debug_str || do_debug_loc || do_debug_ranges)
+ || do_debug_str || do_debug_loc || do_debug_ranges
+ || do_debug_addr || do_debug_cu_index)
&& (const_strneq (name, ".debug_")
|| const_strneq (name, ".zdebug_")))
{
name += sizeof (".debug_") - 1;
if (do_debugging
- || (do_debug_info && streq (name, "info"))
- || (do_debug_info && streq (name, "types"))
- || (do_debug_abbrevs && streq (name, "abbrev"))
- || (do_debug_lines && streq (name, "line"))
- || (do_debug_pubnames && streq (name, "pubnames"))
- || (do_debug_pubtypes && streq (name, "pubtypes"))
- || (do_debug_aranges && streq (name, "aranges"))
- || (do_debug_ranges && streq (name, "ranges"))
- || (do_debug_frames && streq (name, "frame"))
- || (do_debug_macinfo && streq (name, "macinfo"))
- || (do_debug_macinfo && streq (name, "macro"))
- || (do_debug_str && streq (name, "str"))
- || (do_debug_loc && streq (name, "loc"))
+ || (do_debug_info && const_strneq (name, "info"))
+ || (do_debug_info && const_strneq (name, "types"))
+ || (do_debug_abbrevs && const_strneq (name, "abbrev"))
+ || (do_debug_lines && strcmp (name, "line") == 0)
+ || (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"))
+ || (do_debug_macinfo && const_strneq (name, "macinfo"))
+ || (do_debug_macinfo && const_strneq (name, "macro"))
+ || (do_debug_str && const_strneq (name, "str"))
+ || (do_debug_loc && const_strneq (name, "loc"))
+ || (do_debug_addr && const_strneq (name, "addr"))
+ || (do_debug_cu_index && const_strneq (name, "cu_index"))
+ || (do_debug_cu_index && const_strneq (name, "tu_index"))
)
request_dump_bynumber (i, DEBUG_DUMP);
}
i < elf_header.e_shnum;
i++, section++)
{
+ printf (" [%2u] ", i);
if (do_section_details)
{
- printf (" [%2u] %s\n",
- i,
- SECTION_NAME (section));
- if (is_32bit_elf || do_wide)
- printf (" %-15.15s ",
- get_section_type_name (section->sh_type));
+ print_symbol (INT_MAX, SECTION_NAME (section));
+ printf ("\n ");
}
else
- printf ((do_wide ? " [%2u] %-17s %-15s "
- : " [%2u] %-17.17s %-15.15s "),
- i,
- SECTION_NAME (section),
- get_section_type_name (section->sh_type));
+ {
+ print_symbol (-17, SECTION_NAME (section));
+ }
+
+ printf (do_wide ? " %-15s " : " %-15.15s ",
+ get_section_type_name (section->sh_type));
if (is_32bit_elf)
{
W (write), A (alloc), X (execute), M (merge), S (strings)\n\
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)\n\
O (extra OS processing required) o (OS specific), p (processor specific)\n"));
- }
+ }
return 1;
}
++relsec)
{
if (relsec->sh_info >= elf_header.e_shnum
- || section_headers + relsec->sh_info != sec)
+ || section_headers + relsec->sh_info != sec
+ /* PR 15745: Check the section type as well. */
+ || (relsec->sh_type != SHT_REL
+ && relsec->sh_type != SHT_RELA))
continue;
arm_sec->rel_type = relsec->sh_type;
relsec->sh_size,
& arm_sec->rela, & arm_sec->nrelas))
return FALSE;
- break;
}
- else if (relsec->sh_type == SHT_RELA)
+ else /* relsec->sh_type == SHT_RELA */
{
if (!slurp_rela_relocs (aux->file, relsec->sh_offset,
relsec->sh_size,
& arm_sec->rela, & arm_sec->nrelas))
return FALSE;
- break;
}
- else
- warn (_("unexpected relocation type (%d) for section %d"),
- relsec->sh_type, relsec->sh_info);
+ break;
}
arm_sec->next_rela = arm_sec->rela;
if (streq (relname, "R_ARM_NONE"))
continue;
-
+
if (! streq (relname, "R_ARM_PREL31"))
{
warn (_("Skipping unexpected relocation type %s\n"), relname);
else if (elf_header.e_machine == EM_TI_C6000)
{
relname = elf_tic6x_reloc_type (ELF32_R_TYPE (rp->r_info));
-
+
if (streq (relname, "R_C6000_NONE"))
continue;
static const char *tic6x_unwind_regnames[16] =
{
- "A15", "B15", "B14", "B13", "B12", "B11", "B10", "B3",
- "A14", "A13", "A12", "A11", "A10",
+ "A15", "B15", "B14", "B13", "B12", "B11", "B10", "B3",
+ "A14", "A13", "A12", "A11", "A10",
"[invalid reg 13]", "[invalid reg 14]", "[invalid reg 15]"
};
break;
}
assert (i < sizeof (buf));
- offset = read_uleb128 (buf, &len);
+ offset = read_uleb128 (buf, &len, buf + i + 1);
assert (len == i + 1);
offset = offset * 4 + 0x204;
printf ("vsp = vsp + %ld", offset);
break;
}
assert (i < sizeof (buf));
- offset = read_uleb128 (buf, &len);
+ offset = read_uleb128 (buf, &len, buf + i + 1);
assert (len == i + 1);
offset = offset * 8 + 0x408;
printf (_("sp = sp + %ld"), offset);
else
{
/* ARM EHABI Section 6.3:
-
+
An exception-handling table entry for the compact model looks like:
-
+
31 30-28 27-24 23-0
-- ----- ----- ----
1 0 index Data for personalityRoutine[index] */
sec_type = SHT_C6000_UNWIND;
break;
- default:
+ default:
error (_("Unsupported architecture type %d encountered when processing unwind table"),
elf_header.e_machine);
return;
for (i = 0; handlers[i].handler != NULL; i++)
if (elf_header.e_machine == handlers[i].machtype)
- return handlers[i].handler (file);
+ {
+ handlers[i].handler (file);
+ return;
+ }
printf (_("\nThe decoding of unwind sections for machine type %s is not currently supported.\n"),
get_machine_name (elf_header.e_machine));
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:
printf (" NODUMP");
val ^= DF_1_NODUMP;
}
- if (val & DF_1_CONLFAT)
+ if (val & DF_1_CONFALT)
+ {
+ printf (" CONFALT");
+ val ^= DF_1_CONFALT;
+ }
+ if (val & DF_1_ENDFILTEE)
+ {
+ printf (" ENDFILTEE");
+ val ^= DF_1_ENDFILTEE;
+ }
+ if (val & DF_1_DISPRELDNE)
+ {
+ printf (" DISPRELDNE");
+ val ^= DF_1_DISPRELDNE;
+ }
+ if (val & DF_1_DISPRELPND)
+ {
+ printf (" DISPRELPND");
+ val ^= DF_1_DISPRELPND;
+ }
+ if (val & DF_1_NODIRECT)
+ {
+ printf (" NODIRECT");
+ val ^= DF_1_NODIRECT;
+ }
+ if (val & DF_1_IGNMULDEF)
{
- printf (" CONLFAT");
- val ^= DF_1_CONLFAT;
+ printf (" IGNMULDEF");
+ val ^= DF_1_IGNMULDEF;
+ }
+ if (val & DF_1_NOKSYMS)
+ {
+ printf (" NOKSYMS");
+ val ^= DF_1_NOKSYMS;
+ }
+ if (val & DF_1_NOHDR)
+ {
+ printf (" NOHDR");
+ val ^= DF_1_NOHDR;
+ }
+ if (val & DF_1_EDITED)
+ {
+ printf (" EDITED");
+ val ^= DF_1_EDITED;
+ }
+ if (val & DF_1_NORELOC)
+ {
+ printf (" NORELOC");
+ val ^= DF_1_NORELOC;
+ }
+ if (val & DF_1_SYMINTPOSE)
+ {
+ printf (" SYMINTPOSE");
+ val ^= DF_1_SYMINTPOSE;
+ }
+ if (val & DF_1_GLOBAUDIT)
+ {
+ printf (" GLOBAUDIT");
+ val ^= DF_1_GLOBAUDIT;
+ }
+ if (val & DF_1_SINGLETON)
+ {
+ printf (" SINGLETON");
+ val ^= DF_1_SINGLETON;
}
if (val != 0)
printf (" %lx", val);
int j;
int isum;
- /* Check for negative or very large indicies. */
- if ((unsigned char *) edefs + idx < (unsigned char *) edefs)
+ /* Check for very large indicies. */
+ if (idx > (size_t) (endbuf - (char *) edefs))
break;
vstart = ((char *) edefs) + idx;
ent.vd_ndx, ent.vd_cnt);
/* Check for overflow. */
- if ((unsigned char *)(vstart + ent.vd_aux) < (unsigned char *) vstart
- || (unsigned char *)(vstart + ent.vd_aux) > (unsigned char *) endbuf)
+ if (ent.vd_aux > (size_t) (endbuf - vstart))
break;
vstart += ent.vd_aux;
for (j = 1; j < ent.vd_cnt; j++)
{
/* Check for overflow. */
- if ((unsigned char *)(vstart + aux.vda_next) < (unsigned char *) vstart
- || (unsigned char *)(vstart + aux.vda_next) > (unsigned char *) endbuf)
+ if (aux.vda_next > (size_t) (endbuf - vstart))
break;
isum += aux.vda_next;
int isum;
char * vstart;
- if ((unsigned char *) eneed + idx < (unsigned char *) eneed)
+ if (idx > (size_t) (endbuf - (char *) eneed))
break;
vstart = ((char *) eneed) + idx;
printf (_(" Cnt: %d\n"), ent.vn_cnt);
/* Check for overflow. */
- if ((unsigned char *)(vstart + ent.vn_aux) < (unsigned char *) vstart
- || (unsigned char *)(vstart + ent.vn_aux) > (unsigned char *) endbuf)
+ if (ent.vn_aux > (size_t) (endbuf - vstart))
break;
vstart += ent.vn_aux;
get_ver_flags (aux.vna_flags), aux.vna_other);
/* Check for overflow. */
- if ((unsigned char *)(vstart + aux.vna_next) < (unsigned char *) vstart
- || (unsigned char *)(vstart + aux.vna_next) > (unsigned char *) endbuf)
+ if (aux.vna_next > (size_t) (endbuf - vstart))
break;
isum += aux.vna_next;
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;
}
if (get_data (&evn, file, offset, sizeof (evn), 1,
_("version need")) == NULL)
break;
-
+
ivn.vn_aux = BYTE_GET (evn.vn_aux);
ivn.vn_next = BYTE_GET (evn.vn_next);
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, _("<localentry>: %d"),
+ PPC64_LOCAL_ENTRY_OFFSET (other));
+ return buf;
+ }
+ return NULL;
+}
+
static const char *
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;
}
sprintf (buff, "OS [0x%04x]", type & 0xffff);
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);
else
sprintf (buff, "%3d", type);
break;
n = print_vma (si, DEC_5);
if (n < 5)
- fputs (" " + n, stdout);
+ fputs (&" "[n], stdout);
printf (" %3lu: ", hn);
print_vma (psym->st_value, LONG_HEX);
putchar (' ');
counts = (unsigned long *) calloc (maxlength + 1, sizeof (*counts));
if (counts == NULL)
{
+ free (lengths);
error (_("Out of memory\n"));
return 0;
}
counts = (unsigned long *) calloc (maxlength + 1, sizeof (*counts));
if (counts == NULL)
{
+ free (lengths);
error (_("Out of memory\n"));
return 0;
}
switch (elf_header.e_machine)
{
+ case EM_MSP430:
+ case EM_MSP430_OLD:
+ {
+ static Elf_Internal_Sym * saved_sym = NULL;
+
+ switch (reloc_type)
+ {
+ case 10: /* R_MSP430_SYM_DIFF */
+ if (uses_msp430x_relocs ())
+ break;
+ case 21: /* R_MSP430X_SYM_DIFF */
+ saved_sym = symtab + get_reloc_symindex (reloc->r_info);
+ return TRUE;
+
+ case 1: /* R_MSP430_32 or R_MSP430_ABS32 */
+ case 3: /* R_MSP430_16 or R_MSP430_ABS8 */
+ goto handle_sym_diff;
+
+ case 5: /* R_MSP430_16_BYTE */
+ case 9: /* R_MSP430_8 */
+ if (uses_msp430x_relocs ())
+ break;
+ goto handle_sym_diff;
+
+ case 2: /* R_MSP430_ABS16 */
+ case 15: /* R_MSP430X_ABS16 */
+ if (! uses_msp430x_relocs ())
+ break;
+ goto handle_sym_diff;
+
+ handle_sym_diff:
+ if (saved_sym != NULL)
+ {
+ bfd_vma value;
+
+ value = reloc->r_addend
+ + (symtab[get_reloc_symindex (reloc->r_info)].st_value
+ - saved_sym->st_value);
+
+ byte_put (start + reloc->r_offset, value, reloc_type == 1 ? 4 : 2);
+
+ saved_sym = NULL;
+ return TRUE;
+ }
+ break;
+
+ default:
+ if (saved_sym != NULL)
+ error (_("Unhandled MSP430 reloc type found after SYM_DIFF reloc"));
+ break;
+ }
+ break;
+ }
+
case EM_MN10300:
case EM_CYGNUS_MN10300:
{
return reloc_type == 1; /* R_860_32. */
case EM_960:
return reloc_type == 2; /* R_960_32. */
+ case EM_AARCH64:
+ return reloc_type == 258; /* R_AARCH64_ABS32 */
case EM_ALPHA:
return reloc_type == 1; /* R_ALPHA_REFLONG. */
case EM_ARC:
return reloc_type == 1; /* R_MCORE_ADDR32. */
case EM_CYGNUS_MEP:
return reloc_type == 4; /* R_MEP_32. */
+ case EM_METAG:
+ return reloc_type == 2; /* R_METAG_ADDR32. */
case EM_MICROBLAZE:
return reloc_type == 1; /* R_MICROBLAZE_32. */
case EM_MIPS:
return reloc_type == 1; /* R_MOXIE_32. */
case EM_MSP430_OLD:
case EM_MSP430:
- return reloc_type == 1; /* R_MSP43_32. */
+ 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. */
case EM_CYGNUS_V850:
case EM_V850:
return reloc_type == 6; /* R_V850_ABS32. */
+ case EM_V800:
+ return reloc_type == 0x33; /* R_V810_WORD. */
case EM_VAX:
return reloc_type == 1; /* R_VAX_32. */
case EM_X86_64:
return reloc_type == 2; /* R_386_PC32. */
case EM_68K:
return reloc_type == 4; /* R_68K_PC32. */
+ case EM_AARCH64:
+ return reloc_type == 261; /* R_AARCH64_PREL32 */
case EM_ADAPTEVA_EPIPHANY:
return reloc_type == 6;
case EM_ALPHA:
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:
{
switch (elf_header.e_machine)
{
+ case EM_AARCH64:
+ return reloc_type == 257; /* R_AARCH64_ABS64. */
case EM_ALPHA:
return reloc_type == 2; /* R_ALPHA_REFQUAD. */
case EM_IA_64:
{
switch (elf_header.e_machine)
{
+ case EM_AARCH64:
+ return reloc_type == 260; /* R_AARCH64_PREL64. */
case EM_ALPHA:
return reloc_type == 11; /* R_ALPHA_SREL64. */
case EM_IA_64:
case EM_M32C_OLD:
case EM_M32C:
return reloc_type == 1; /* R_M32C_16 */
- case EM_MSP430_OLD:
case EM_MSP430:
+ if (uses_msp430x_relocs ())
+ 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:
case EM_C166:
return reloc_type == 2; /* R_XC16C_ABS_16. */
+ case EM_CYGNUS_MN10200:
+ case EM_MN10200:
+ return reloc_type == 2; /* R_MN10200_16. */
case EM_CYGNUS_MN10300:
case EM_MN10300:
return reloc_type == 2; /* R_MN10300_16. */
case EM_TILEPRO: /* R_TILEPRO_NONE. */
case EM_XC16X:
case EM_C166: /* R_XC16X_NONE. */
+ case EM_ALTERA_NIOS2: /* R_NIOS2_NONE. */
+ case EM_NIOS32: /* R_NIOS_NONE. */
+ case EM_OR1K: /* R_OR1K_NONE. */
return reloc_type == 0;
+ case EM_AARCH64:
+ return reloc_type == 0 || reloc_type == 256;
+ case EM_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. */
|| reloc_type == 17 /* R_XTENSA_DIFF8. */
|| reloc_type == 18 /* R_XTENSA_DIFF16. */
|| reloc_type == 19 /* R_XTENSA_DIFF32. */);
+ case EM_METAG:
+ return reloc_type == 3; /* R_METAG_NONE. */
}
return FALSE;
}
}
rloc = start + rp->r_offset;
- if ((rloc + reloc_size) > end)
+ if ((rloc + reloc_size) > end || (rloc < start))
{
warn (_("skipping invalid relocation offset 0x%lx in section %s\n"),
(unsigned long) rp->r_offset,
return 1;
}
+/* If this is not NULL, load_debug_section will only look for sections
+ within the list of sections given here. */
+unsigned int *section_subset = NULL;
+
int
load_debug_section (enum dwarf_section_display_enum debug, void * file)
{
Elf_Internal_Shdr * sec;
/* Locate the debug section. */
- sec = find_section (section->uncompressed_name);
+ sec = find_section_in_set (section->uncompressed_name, section_subset);
if (sec != NULL)
section->name = section->uncompressed_name;
else
{
- sec = find_section (section->compressed_name);
+ sec = find_section_in_set (section->compressed_name, section_subset);
if (sec != NULL)
section->name = section->compressed_name;
}
if (sec == NULL)
return 0;
+ /* If we're loading from a subset of sections, and we've loaded
+ a section matching this name before, it's likely that it's a
+ different one. */
+ if (section_subset != NULL)
+ free_debug_section (debug);
+
return load_specific_debug_section (debug, sec, (FILE *) file);
}
}
static int
-display_debug_section (Elf_Internal_Shdr * section, FILE * file)
+display_debug_section (int shndx, Elf_Internal_Shdr * section, FILE * file)
{
char * name = SECTION_NAME (section);
bfd_size_type length;
/* See if we know how to display the contents of this section. */
for (i = 0; i < max; i++)
if (streq (debug_displays[i].section.uncompressed_name, name)
+ || (i == line && const_strneq (name, ".debug_line."))
|| streq (debug_displays[i].section.compressed_name, name))
{
struct dwarf_section * sec = &debug_displays [i].section;
if (secondary)
free_debug_section ((enum dwarf_section_display_enum) i);
- if (streq (sec->uncompressed_name, name))
+ if (i == line && const_strneq (name, ".debug_line."))
+ sec->name = name;
+ else if (streq (sec->uncompressed_name, name))
sec->name = sec->uncompressed_name;
else
sec->name = sec->compressed_name;
if (load_specific_debug_section ((enum dwarf_section_display_enum) i,
section, file))
{
+ /* If this debug section is part of a CU/TU set in a .dwp file,
+ restrict load_debug_section to the sections in that set. */
+ section_subset = find_cu_tu_set (file, shndx);
+
result &= debug_displays[i].display (sec, file);
+ section_subset = NULL;
+
if (secondary || (i != info && i != abbrev))
free_debug_section ((enum dwarf_section_display_enum) i);
}
dump_section_as_strings (section, file);
if (dump_sects[i] & DEBUG_DUMP)
- display_debug_section (section, file);
+ display_debug_section (i, section, file);
}
/* Check to see if the user requested a
fputs ("0", stdout);
}
+/* Display's the value of TAG at location P. If TAG is
+ greater than 0 it is assumed to be an unknown tag, and
+ a message is printed to this effect. Otherwise it is
+ assumed that a message has already been printed.
+
+ If the bottom bit of TAG is set it assumed to have a
+ string value, otherwise it is assumed to have an integer
+ value.
+
+ Returns an updated P pointing to the first unread byte
+ beyond the end of TAG's value.
+
+ Reads at or beyond END will not be made. */
+
+static unsigned char *
+display_tag_value (int tag,
+ unsigned char * p,
+ const unsigned char * const end)
+{
+ unsigned long val;
+
+ if (tag > 0)
+ printf (" Tag_unknown_%d: ", tag);
+
+ if (p >= end)
+ {
+ warn (_("corrupt tag\n"));
+ }
+ else if (tag & 1)
+ {
+ /* FIXME: we could read beyond END here. */
+ printf ("\"%s\"\n", p);
+ p += strlen ((char *) p) + 1;
+ }
+ else
+ {
+ unsigned int len;
+
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf ("%ld (0x%lx)\n", val, val);
+ }
+
+ 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;
static const char * arm_attr_tag_CPU_arch[] =
{"Pre-v4", "v4", "v4T", "v5T", "v5TE", "v5TEJ", "v6", "v6KZ", "v6T2",
- "v6K", "v7", "v6-M", "v6S-M", "v7E-M"};
+ "v6K", "v7", "v6-M", "v6S-M", "v7E-M", "v8"};
static const char * arm_attr_tag_ARM_ISA_use[] = {"No", "Yes"};
static const char * arm_attr_tag_THUMB_ISA_use[] =
{"No", "Thumb-1", "Thumb-2"};
static const char * arm_attr_tag_FP_arch[] =
- {"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", "VFPv4-D16"};
+ {"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", "VFPv4-D16",
+ "FP for ARMv8"};
static const char * arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1", "WMMXv2"};
static const char * arm_attr_tag_Advanced_SIMD_arch[] =
- {"No", "NEONv1", "NEONv1 with Fused-MAC"};
+ {"No", "NEONv1", "NEONv1 with Fused-MAC", "NEON for ARMv8"};
static const char * arm_attr_tag_PCS_config[] =
{"None", "Bare platform", "Linux application", "Linux DSO", "PalmOS 2004",
"PalmOS (reserved)", "SymbianOS 2004", "SymbianOS (reserved)"};
#undef LOOKUP
static unsigned char *
-display_arm_attribute (unsigned char * p)
+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);
+ tag = read_uleb128 (p, &len, end);
p += len;
attr = NULL;
for (i = 0; i < ARRAY_SIZE (arm_attr_public_tags); i++)
switch (tag)
{
case 7: /* Tag_CPU_arch_profile. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
switch (val)
{
break;
case 24: /* Tag_align_needed. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
switch (val)
{
break;
case 25: /* Tag_align_preserved. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
switch (val)
{
break;
case 32: /* Tag_compatibility. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (_("flag = %d, vendor = %s\n"), val, p);
p += strlen ((char *) p) + 1;
break;
case 65: /* Tag_also_compatible_with. */
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
if (val == 6 /* Tag_CPU_arch. */)
{
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
if ((unsigned int)val >= ARRAY_SIZE (arm_attr_tag_CPU_arch))
printf ("??? (%d)\n", val);
return p;
case 1:
+ return display_tag_value (-1, p, end);
case 2:
- type = attr->type;
- break;
+ return display_tag_value (0, p, end);
default:
assert (attr->type & 0x80);
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
type = attr->type & 0x7f;
if (val >= type)
return p;
}
}
- else
- {
- if (tag & 1)
- type = 1; /* String. */
- else
- type = 2; /* uleb128. */
- printf (" Tag_unknown_%d: ", tag);
- }
- if (type == 1)
- {
- printf ("\"%s\"\n", p);
- p += strlen ((char *) p) + 1;
- }
- else
- {
- val = read_uleb128 (p, &len);
- p += len;
- printf ("%d (0x%x)\n", val, val);
- }
-
- return p;
+ return display_tag_value (tag, p, end);
}
static unsigned char *
display_gnu_attribute (unsigned char * p,
- unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int))
+ unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int, const unsigned char * const),
+ const unsigned char * const end)
{
int tag;
unsigned int len;
int val;
- int type;
- tag = read_uleb128 (p, &len);
+ tag = read_uleb128 (p, &len, end);
p += len;
/* Tag_compatibility is the only generic GNU attribute defined at
present. */
if (tag == 32)
{
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
- printf (_("flag = %d, vendor = %s\n"), val, p);
- p += strlen ((char *) p) + 1;
+ if (p == end)
+ {
+ printf (_("flag = %d, vendor = <corrupt>\n"), val);
+ warn (_("corrupt vendor attribute\n"));
+ }
+ else
+ {
+ printf (_("flag = %d, vendor = %s\n"), val, p);
+ p += strlen ((char *) p) + 1;
+ }
return p;
}
if ((tag & 2) == 0 && display_proc_gnu_attribute)
- return display_proc_gnu_attribute (p, tag);
+ return display_proc_gnu_attribute (p, tag, end);
- if (tag & 1)
- type = 1; /* String. */
- else
- type = 2; /* uleb128. */
- printf (" Tag_unknown_%d: ", tag);
-
- if (type == 1)
- {
- printf ("\"%s\"\n", p);
- p += strlen ((char *) p) + 1;
- }
- else
- {
- val = read_uleb128 (p, &len);
- p += len;
- printf ("%d (0x%x)\n", val, val);
- }
-
- return p;
+ return display_tag_value (tag, p, end);
}
static unsigned char *
-display_power_gnu_attribute (unsigned char * p, int tag)
+display_power_gnu_attribute (unsigned char * p,
+ int tag,
+ const unsigned char * const end)
{
- int type;
unsigned int len;
int val;
if (tag == Tag_GNU_Power_ABI_FP)
{
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_GNU_Power_ABI_FP: ");
if (tag == Tag_GNU_Power_ABI_Vector)
{
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_GNU_Power_ABI_Vector: ");
switch (val)
if (tag == Tag_GNU_Power_ABI_Struct_Return)
{
- val = read_uleb128 (p, &len);
+ if (p == end)
+ {
+ warn (_("corrupt Tag_GNU_Power_ABI_Struct_Return"));
+ return p;
+ }
+
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_GNU_Power_ABI_Struct_Return: ");
switch (val)
return p;
}
- if (tag & 1)
- type = 1; /* String. */
- else
- type = 2; /* uleb128. */
- printf (" Tag_unknown_%d: ", tag);
-
- if (type == 1)
- {
- printf ("\"%s\"\n", p);
- p += strlen ((char *) p) + 1;
- }
- else
- {
- val = read_uleb128 (p, &len);
- p += len;
- printf ("%d (0x%x)\n", val, val);
- }
-
- return p;
+ return display_tag_value (tag & 1, p, end);
}
static void
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 *
-display_sparc_gnu_attribute (unsigned char * p, int tag)
+display_sparc_gnu_attribute (unsigned char * p,
+ int tag,
+ const unsigned char * const end)
{
- int type;
unsigned int len;
int val;
if (tag == Tag_GNU_Sparc_HWCAPS)
{
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_GNU_Sparc_HWCAPS: ");
-
display_sparc_hwcaps (val);
return p;
- }
-
- if (tag & 1)
- type = 1; /* String. */
- else
- type = 2; /* uleb128. */
- printf (" Tag_unknown_%d: ", tag);
-
- if (type == 1)
- {
- printf ("\"%s\"\n", p);
- p += strlen ((char *) p) + 1;
}
- else
+ if (tag == Tag_GNU_Sparc_HWCAPS2)
{
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
- printf ("%d (0x%x)\n", val, val);
+ printf (" Tag_GNU_Sparc_HWCAPS2: ");
+ display_sparc_hwcaps2 (val);
+ return p;
}
- return p;
+ return display_tag_value (tag, p, end);
}
-static unsigned char *
-display_mips_gnu_attribute (unsigned char * p, int tag)
+static void
+print_mips_fp_abi_value (int val)
{
- int type;
- unsigned int len;
- 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,
+ const unsigned char * const end)
+{
if (tag == Tag_GNU_MIPS_ABI_FP)
{
- val = read_uleb128 (p, &len);
+ unsigned int len;
+ int val;
+
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_GNU_MIPS_ABI_FP: ");
+ print_mips_fp_abi_value (val);
+
+ return p;
+ }
+
+ if (tag == Tag_GNU_MIPS_ABI_MSA)
+ {
+ unsigned int len;
+ int val;
+
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (" Tag_GNU_MIPS_ABI_MSA: ");
+
switch (val)
{
- case 0:
- printf (_("Hard or soft float\n"));
- break;
- case 1:
- printf (_("Hard float (double precision)\n"));
+ case Val_GNU_MIPS_ABI_MSA_ANY:
+ printf (_("Any MSA or not\n"));
break;
- case 2:
- printf (_("Hard float (single precision)\n"));
- break;
- case 3:
- printf (_("Soft float\n"));
- break;
- case 4:
- printf (_("Hard float (MIPS32r2 64-bit FPU)\n"));
+ case Val_GNU_MIPS_ABI_MSA_128:
+ printf (_("128-bit MSA\n"));
break;
default:
printf ("??? (%d)\n", val);
break;
}
return p;
- }
-
- if (tag & 1)
- type = 1; /* String. */
- else
- type = 2; /* uleb128. */
- printf (" Tag_unknown_%d: ", tag);
-
- if (type == 1)
- {
- printf ("\"%s\"\n", p);
- p += strlen ((char *) p) + 1;
- }
- else
- {
- val = read_uleb128 (p, &len);
- p += len;
- printf ("%d (0x%x)\n", val, val);
}
- return p;
+ return display_tag_value (tag & 1, p, end);
}
static unsigned char *
-display_tic6x_attribute (unsigned char * p)
+display_tic6x_attribute (unsigned char * p,
+ const unsigned char * const end)
{
int tag;
unsigned int len;
int val;
- tag = read_uleb128 (p, &len);
+ tag = read_uleb128 (p, &len, end);
p += len;
switch (tag)
{
case Tag_ISA:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ISA: ");
return p;
case Tag_ABI_wchar_t:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_wchar_t: ");
switch (val)
return p;
case Tag_ABI_stack_align_needed:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_stack_align_needed: ");
switch (val)
return p;
case Tag_ABI_stack_align_preserved:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_stack_align_preserved: ");
switch (val)
return p;
case Tag_ABI_DSBT:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_DSBT: ");
switch (val)
return p;
case Tag_ABI_PID:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_PID: ");
switch (val)
return p;
case Tag_ABI_PIC:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_PIC: ");
switch (val)
return p;
case Tag_ABI_array_object_alignment:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_array_object_alignment: ");
switch (val)
return p;
case Tag_ABI_array_object_align_expected:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_array_object_align_expected: ");
switch (val)
return p;
case Tag_ABI_compatibility:
- val = read_uleb128 (p, &len);
+ val = read_uleb128 (p, &len, end);
p += len;
printf (" Tag_ABI_compatibility: ");
printf (_("flag = %d, vendor = %s\n"), val, p);
return p;
}
- printf (" Tag_unknown_%d: ", tag);
+ return display_tag_value (tag, p, end);
+}
+
+static void
+display_raw_attribute (unsigned char * p, unsigned char * end)
+{
+ unsigned long addr = 0;
+ size_t bytes = end - p;
- if (tag & 1)
+ while (bytes)
{
- printf ("\"%s\"\n", p);
- p += strlen ((char *) p) + 1;
+ int j;
+ int k;
+ int lbytes = (bytes > 16 ? 16 : bytes);
+
+ printf (" 0x%8.8lx ", addr);
+
+ for (j = 0; j < 16; j++)
+ {
+ if (j < lbytes)
+ printf ("%2.2x", p[j]);
+ else
+ printf (" ");
+
+ if ((j & 3) == 3)
+ printf (" ");
+ }
+
+ for (j = 0; j < lbytes; j++)
+ {
+ k = p[j];
+ if (k >= ' ' && k < 0x7f)
+ printf ("%c", k);
+ else
+ printf (".");
+ }
+
+ putchar ('\n');
+
+ p += lbytes;
+ bytes -= lbytes;
+ addr += lbytes;
}
- else
+
+ putchar ('\n');
+}
+
+static unsigned char *
+display_msp430x_attribute (unsigned char * p,
+ const unsigned char * const end)
+{
+ unsigned int len;
+ int val;
+ int tag;
+
+ tag = read_uleb128 (p, & len, end);
+ p += len;
+
+ switch (tag)
{
- val = read_uleb128 (p, &len);
+ case OFBA_MSPABI_Tag_ISA:
+ val = read_uleb128 (p, &len, end);
p += len;
- printf ("%d (0x%x)\n", val, val);
- }
+ printf (" Tag_ISA: ");
+ switch (val)
+ {
+ case 0: printf (_("None\n")); break;
+ case 1: printf (_("MSP430\n")); break;
+ case 2: printf (_("MSP430X\n")); break;
+ default: printf ("??? (%d)\n", val); break;
+ }
+ break;
+
+ case OFBA_MSPABI_Tag_Code_Model:
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (" Tag_Code_Model: ");
+ switch (val)
+ {
+ case 0: printf (_("None\n")); break;
+ case 1: printf (_("Small\n")); break;
+ case 2: printf (_("Large\n")); break;
+ default: printf ("??? (%d)\n", val); break;
+ }
+ break;
+
+ case OFBA_MSPABI_Tag_Data_Model:
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (" Tag_Data_Model: ");
+ switch (val)
+ {
+ case 0: printf (_("None\n")); break;
+ case 1: printf (_("Small\n")); break;
+ case 2: printf (_("Large\n")); break;
+ case 3: printf (_("Restricted Large\n")); break;
+ default: printf ("??? (%d)\n", val); break;
+ }
+ break;
+
+ default:
+ printf (_(" <unknown tag %d>: "), tag);
+
+ if (tag & 1)
+ {
+ printf ("\"%s\"\n", p);
+ p += strlen ((char *) p) + 1;
+ }
+ else
+ {
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf ("%d (0x%x)\n", val, val);
+ }
+ break;
+ }
return p;
}
process_attributes (FILE * file,
const char * public_name,
unsigned int proc_type,
- unsigned char * (* display_pub_attribute) (unsigned char *),
- unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int))
+ unsigned char * (* display_pub_attribute) (unsigned char *, const unsigned char * const),
+ unsigned char * (* display_proc_gnu_attribute) (unsigned char *, int, const unsigned char * const))
{
Elf_Internal_Shdr * sect;
unsigned char * contents;
while (len > 0)
{
- int namelen;
+ unsigned int namelen;
bfd_boolean public_section;
bfd_boolean gnu_section;
if (section_len > len)
{
- printf (_("ERROR: Bad section length (%d > %d)\n"),
- (int) section_len, (int) len);
+ error (_("Length of attribute (%u) greater than length of section (%u)\n"),
+ (unsigned) section_len, (unsigned) len);
section_len = len;
}
len -= section_len;
+ section_len -= 4;
+
+ namelen = strnlen ((char *) p, section_len) + 1;
+ if (namelen == 0 || namelen >= section_len)
+ {
+ error (_("Corrupt attribute section name\n"));
+ break;
+ }
+
printf (_("Attribute Section: %s\n"), p);
if (public_name && streq ((char *) p, public_name))
else
gnu_section = FALSE;
- namelen = strlen ((char *) p) + 1;
p += namelen;
- section_len -= namelen + 4;
-
+ section_len -= namelen;
while (section_len > 0)
{
int tag = *(p++);
size = byte_get (p, 4);
if (size > section_len)
{
- printf (_("ERROR: Bad subsection length (%d > %d)\n"),
- (int) size, (int) section_len);
+ error (_("Bad subsection length (%u > %u)\n"),
+ (unsigned) size, (unsigned) section_len);
size = section_len;
}
{
unsigned int j;
- val = read_uleb128 (p, &j);
+ val = read_uleb128 (p, &j, end);
p += j;
if (val == 0)
break;
if (public_section)
{
while (p < end)
- p = display_pub_attribute (p);
+ p = display_pub_attribute (p, end);
}
else if (gnu_section)
{
while (p < end)
p = display_gnu_attribute (p,
- display_proc_gnu_attribute);
+ display_proc_gnu_attribute,
+ end);
}
else
{
- /* ??? Do something sensible, like dump hex. */
printf (_(" Unknown section contexts\n"));
+ display_raw_attribute (p, end);
p = end;
}
}
}
}
else
- printf (_("Unknown format '%c'\n"), *p);
+ printf (_("Unknown format '%c' (%d)\n"), *p, *p);
free (contents);
}
display_tic6x_attribute, NULL);
}
+static int
+process_msp430x_specific (FILE * file)
+{
+ return process_attributes (file, "mspabi", SHT_MSP430_ATTRIBUTES,
+ display_msp430x_attribute, NULL);
+}
+
/* DATA points to the contents of a MIPS GOT that starts at VMA PLTGOT.
Print the Address, Access and Initial fields of an entry at VMA ADDR
and return the VMA of the next entry. */
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_OCTEON3:
+ fputs ("Cavium Networks Octeon3", 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;
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. */
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)
_("Type"),
/* Note for translators: "Ndx" = abbreviated form of "Index". */
_("Ndx"), _("Name"));
-
+
sym_width = (is_32bit_elf ? 80 : 160) - 28 - addr_size * 6 - 1;
for (i = gotsym; i < symtabno; i++)
{
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)
{
return _("NT_PPC_VMX (ppc Altivec registers)");
case NT_PPC_VSX:
return _("NT_PPC_VSX (ppc VSX registers)");
+ case NT_386_TLS:
+ return _("NT_386_TLS (x86 TLS information)");
+ case NT_386_IOPERM:
+ return _("NT_386_IOPERM (x86 I/O permissions)");
case NT_X86_XSTATE:
return _("NT_X86_XSTATE (x86 XSAVE extended state)");
case NT_S390_HIGH_GPRS:
return _("NT_S390_CTRS (s390 control registers)");
case NT_S390_PREFIX:
return _("NT_S390_PREFIX (s390 prefix register)");
+ case NT_S390_LAST_BREAK:
+ return _("NT_S390_LAST_BREAK (s390 last breaking event address)");
+ case NT_S390_SYSTEM_CALL:
+ return _("NT_S390_SYSTEM_CALL (s390 system call restart data)");
+ case NT_S390_TDB:
+ return _("NT_S390_TDB (s390 transaction diagnostic block)");
case NT_ARM_VFP:
return _("NT_ARM_VFP (arm VFP registers)");
+ case NT_ARM_TLS:
+ return _("NT_ARM_TLS (AArch TLS registers)");
+ case NT_ARM_HW_BREAK:
+ return _("NT_ARM_HW_BREAK (AArch hardware breakpoint registers)");
+ case NT_ARM_HW_WATCH:
+ return _("NT_ARM_HW_WATCH (AArch hardware watchpoint registers)");
case NT_PSTATUS:
return _("NT_PSTATUS (pstatus structure)");
case NT_FPREGS:
return _("NT_LWPSINFO (lwpsinfo_t structure)");
case NT_WIN32PSTATUS:
return _("NT_WIN32PSTATUS (win32_pstatus structure)");
+ case NT_SIGINFO:
+ return _("NT_SIGINFO (siginfo_t data)");
+ case NT_FILE:
+ return _("NT_FILE (mapped files)");
default:
break;
}
return buff;
}
+static int
+print_core_note (Elf_Internal_Note *pnote)
+{
+ unsigned int addr_size = is_32bit_elf ? 4 : 8;
+ bfd_vma count, page_size;
+ unsigned char *descdata, *filenames, *descend;
+
+ if (pnote->type != NT_FILE)
+ return 1;
+
+#ifndef BFD64
+ if (!is_32bit_elf)
+ {
+ printf (_(" Cannot decode 64-bit note in 32-bit build\n"));
+ /* Still "successful". */
+ return 1;
+ }
+#endif
+
+ if (pnote->descsz < 2 * addr_size)
+ {
+ printf (_(" Malformed note - too short for header\n"));
+ return 0;
+ }
+
+ descdata = (unsigned char *) pnote->descdata;
+ descend = descdata + pnote->descsz;
+
+ if (descdata[pnote->descsz - 1] != '\0')
+ {
+ printf (_(" Malformed note - does not end with \\0\n"));
+ return 0;
+ }
+
+ count = byte_get (descdata, addr_size);
+ descdata += addr_size;
+
+ page_size = byte_get (descdata, addr_size);
+ descdata += addr_size;
+
+ if (pnote->descsz < 2 * addr_size + count * 3 * addr_size)
+ {
+ printf (_(" Malformed note - too short for supplied file count\n"));
+ return 0;
+ }
+
+ printf (_(" Page size: "));
+ print_vma (page_size, DEC);
+ printf ("\n");
+
+ printf (_(" %*s%*s%*s\n"),
+ (int) (2 + 2 * addr_size), _("Start"),
+ (int) (4 + 2 * addr_size), _("End"),
+ (int) (4 + 2 * addr_size), _("Page Offset"));
+ filenames = descdata + count * 3 * addr_size;
+ while (--count > 0)
+ {
+ bfd_vma start, end, file_ofs;
+
+ if (filenames == descend)
+ {
+ printf (_(" Malformed note - filenames end too early\n"));
+ return 0;
+ }
+
+ start = byte_get (descdata, addr_size);
+ descdata += addr_size;
+ end = byte_get (descdata, addr_size);
+ descdata += addr_size;
+ file_ofs = byte_get (descdata, addr_size);
+ descdata += addr_size;
+
+ printf (" ");
+ print_vma (start, FULL_HEX);
+ printf (" ");
+ print_vma (end, FULL_HEX);
+ printf (" ");
+ print_vma (file_ofs, FULL_HEX);
+ printf ("\n %s\n", filenames);
+
+ filenames += 1 + strlen ((char *) filenames);
+ }
+
+ return 1;
+}
+
static const char *
get_gnu_elf_note_type (unsigned e_type)
{
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;
return print_gnu_note (pnote);
else if (const_strneq (pnote->namedata, "stapsdt"))
return print_stapsdt_note (pnote);
+ else if (const_strneq (pnote->namedata, "CORE"))
+ return print_core_note (pnote);
else
return 1;
}
return 0;
pnotes = (Elf_External_Note *) get_data (NULL, file, offset, 1, length,
- _("notes"));
+ _("notes"));
if (pnotes == NULL)
return 0;
external = pnotes;
- printf (_("\nNotes at offset 0x%08lx with length 0x%08lx:\n"),
+ printf (_("\nDisplaying notes found at file offset 0x%08lx with length 0x%08lx:\n"),
(unsigned long) offset, (unsigned long) length);
printf (_(" %-20s %10s\tDescription\n"), _("Owner"), _("Data size"));
- while (external < (Elf_External_Note *) ((char *) pnotes + length))
+ while ((char *) external < (char *) pnotes + length)
{
- Elf_External_Note * next;
Elf_Internal_Note inote;
+ size_t min_notesz;
+ char *next;
char * temp = NULL;
+ size_t data_remaining = ((char *) pnotes + length) - (char *) external;
if (!is_ia64_vms ())
- {
- inote.type = BYTE_GET (external->type);
- inote.namesz = BYTE_GET (external->namesz);
- inote.namedata = external->name;
- inote.descsz = BYTE_GET (external->descsz);
- inote.descdata = inote.namedata + align_power (inote.namesz, 2);
- inote.descpos = offset + (inote.descdata - (char *) pnotes);
-
- next = (Elf_External_Note *) (inote.descdata + align_power (inote.descsz, 2));
- }
+ {
+ /* PR binutils/15191
+ Make sure that there is enough data to read. */
+ min_notesz = offsetof (Elf_External_Note, name);
+ if (data_remaining < min_notesz)
+ {
+ warn (_("Corrupt note: only %d bytes remain, not enough for a full note\n"),
+ (int) data_remaining);
+ break;
+ }
+ inote.type = BYTE_GET (external->type);
+ inote.namesz = BYTE_GET (external->namesz);
+ inote.namedata = external->name;
+ inote.descsz = BYTE_GET (external->descsz);
+ inote.descdata = inote.namedata + align_power (inote.namesz, 2);
+ inote.descpos = offset + (inote.descdata - (char *) pnotes);
+ next = inote.descdata + align_power (inote.descsz, 2);
+ }
else
- {
- Elf64_External_VMS_Note *vms_external;
-
- vms_external = (Elf64_External_VMS_Note *)external;
- inote.type = BYTE_GET (vms_external->type);
- inote.namesz = BYTE_GET (vms_external->namesz);
- inote.namedata = vms_external->name;
- inote.descsz = BYTE_GET (vms_external->descsz);
- inote.descdata = inote.namedata + align_power (inote.namesz, 3);
- inote.descpos = offset + (inote.descdata - (char *) pnotes);
-
- next = (Elf_External_Note *)
- (inote.descdata + align_power (inote.descsz, 3));
- }
+ {
+ Elf64_External_VMS_Note *vms_external;
+
+ /* PR binutils/15191
+ Make sure that there is enough data to read. */
+ min_notesz = offsetof (Elf64_External_VMS_Note, name);
+ if (data_remaining < min_notesz)
+ {
+ warn (_("Corrupt note: only %d bytes remain, not enough for a full note\n"),
+ (int) data_remaining);
+ break;
+ }
+
+ vms_external = (Elf64_External_VMS_Note *) external;
+ inote.type = BYTE_GET (vms_external->type);
+ inote.namesz = BYTE_GET (vms_external->namesz);
+ inote.namedata = vms_external->name;
+ inote.descsz = BYTE_GET (vms_external->descsz);
+ inote.descdata = inote.namedata + align_power (inote.namesz, 3);
+ inote.descpos = offset + (inote.descdata - (char *) pnotes);
+ next = inote.descdata + align_power (inote.descsz, 3);
+ }
- if ( ((char *) next > ((char *) pnotes) + length)
- || ((char *) next < (char *) pnotes))
+ if (inote.descdata < (char *) external + min_notesz
+ || next < (char *) external + min_notesz
+ || data_remaining < (size_t)(next - (char *) external))
{
- warn (_("corrupt note found at offset %lx into core notes\n"),
+ warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
(unsigned long) ((char *) external - (char *) pnotes));
- warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
+ warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx\n"),
inote.type, inote.namesz, inote.descsz);
break;
}
- external = next;
-
- /* Prevent out-of-bounds indexing. */
- if (inote.namedata + inote.namesz > (char *) pnotes + length
- || inote.namedata + inote.namesz < inote.namedata)
- {
- warn (_("corrupt note found at offset %lx into core notes\n"),
- (unsigned long) ((char *) external - (char *) pnotes));
- warn (_(" type: %lx, namesize: %08lx, descsize: %08lx\n"),
- inote.type, inote.namesz, inote.descsz);
- break;
- }
+ external = (Elf_External_Note *) next;
/* Verify that name is null terminated. It appears that at least
one version of Linux (RedHat 6.0) generates corefiles that don't
{
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;
}
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;
case EM_TI_C6000:
return process_tic6x_specific (file);
break;
+ case EM_MSP430:
+ return process_msp430x_specific (file);
default:
break;
}
unsigned long current_pos;
printf (_("Index of archive %s: (%ld entries, 0x%lx bytes in the symbol table)\n"),
- file_name, arch.index_num, arch.sym_size);
+ file_name, (long) arch.index_num, arch.sym_size);
current_pos = ftell (file);
for (i = l = 0; i < arch.index_num; i++)
if (qualified_name != NULL)
{
- printf (_("Binary %s contains:\n"), qualified_name);
+ printf (_("Contents of binary %s at offset "), qualified_name);
+ (void) print_vma (arch.index_array[i], PREFIX_HEX);
+ putchar ('\n');
free (qualified_name);
}
}
l += strlen (arch.sym_table + l) + 1;
}
- if (l & 01)
- ++l;
+ if (arch.uses_64bit_indicies)
+ l = (l + 7) & ~ 7;
+ else
+ l += l & 1;
+
if (l < arch.sym_size)
- error (_("%s: symbols remain in the index symbol table, but without corresponding entries in the index table\n"),
- file_name);
+ error (_("%s: %ld bytes remain in the symbol table, but without corresponding entries in the index table\n"),
+ file_name, arch.sym_size - l);
if (fseek (file, current_pos, SEEK_SET) != 0)
{
}
else if (is_thin_archive)
{
+ /* PR 15140: Allow for corrupt thin archives. */
+ if (nested_arch.file == NULL)
+ {
+ error (_("%s: contains corrupt thin archive: %s\n"),
+ file_name, name);
+ ret = 1;
+ break;
+ }
+
/* This is a proxy for a member of a nested archive. */
archive_file_offset = arch.nested_member_origin + sizeof arch.arhdr;
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)
fclose (file);
+ current_file_size = 0;
return ret;
}