#include "elf/tilepro.h"
#include "elf/v850.h"
#include "elf/vax.h"
+#include "elf/visium.h"
#include "elf/x86-64.h"
#include "elf/xc16x.h"
#include "elf/xgate.h"
#endif
char * program_name = "readelf";
-static long archive_file_offset;
+static unsigned 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;
}
print_mode;
+/* Versioned symbol info. */
+enum versioned_symbol_info
+{
+ symbol_undefined,
+ symbol_hidden,
+ symbol_public
+};
+
+static const char *get_symbol_version_string
+ (FILE *file, int is_dynsym, const char *strtab,
+ unsigned long int strtab_size, unsigned int si,
+ Elf_Internal_Sym *psym, enum versioned_symbol_info *sym_info,
+ unsigned short *vna_other);
+
#define UNKNOWN -1
#define SECTION_NAME(X) \
} \
while (0)
\f
-/* Retrieve NMEMB structures, each SIZE bytes long from FILE starting at OFFSET.
+/* Retrieve NMEMB structures, each SIZE bytes long from FILE starting at OFFSET +
+ the offset of the current archive member, if we are examining an archive.
Put the retrieved data into VAR, if it is not NULL. Otherwise allocate a buffer
using malloc and fill that. In either case return the pointer to the start of
the retrieved data or NULL if something went wrong. If something does go wrong
- emit an error message using REASON as part of the context. */
+ and REASON is not NULL then emit an error message using REASON as part of the
+ context. */
static void *
-get_data (void * var, FILE * file, long offset, size_t size, size_t nmemb,
+get_data (void * var, FILE * file, unsigned long offset, size_t size, size_t nmemb,
const char * reason)
{
void * mvar;
+ size_t amt = size * nmemb;
if (size == 0 || nmemb == 0)
return NULL;
- if (fseek (file, archive_file_offset + offset, SEEK_SET))
+ /* Be kind to memory chekers (eg valgrind, address sanitizer) by not
+ attempting to allocate memory when the read is bound to fail. */
+ if (amt > current_file_size
+ || offset + archive_file_offset + amt > current_file_size)
{
if (reason)
- error (_("Unable to seek to 0x%lx for %s\n"),
- (unsigned long) archive_file_offset + offset, reason);
+ error (_("Reading 0x%lx bytes extends past end of file for %s\n"),
+ (unsigned long) amt, 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 (fseek (file, archive_file_offset + offset, SEEK_SET))
{
if (reason)
- error (_("Reading 0x%lx bytes extends past end of file for %s\n"),
- (unsigned long) (size * nmemb), reason);
+ error (_("Unable to seek to 0x%lx for %s\n"),
+ (unsigned long) archive_file_offset + offset, reason);
return NULL;
}
return NULL;
}
- ((char *) mvar)[size * nmemb] = '\0';
+ ((char *) mvar)[amt] = '\0';
}
if (fread (mvar, size, nmemb, file) != nmemb)
{
if (reason)
error (_("Unable to read in 0x%lx bytes of %s\n"),
- (unsigned long)(size * nmemb), reason);
+ (unsigned long) amt, reason);
if (mvar != var)
free (mvar);
return NULL;
case EM_V850:
case EM_CYGNUS_V850:
case EM_VAX:
+ case EM_VISIUM:
case EM_X86_64:
case EM_L1OM:
case EM_K1OM:
unsigned long * nrelasp)
{
Elf_Internal_Rela * relas;
- unsigned long nrelas;
+ size_t nrelas;
unsigned int i;
if (is_32bit_elf)
unsigned long * nrelsp)
{
Elf_Internal_Rela * rels;
- unsigned long nrels;
+ size_t nrels;
unsigned int i;
if (is_32bit_elf)
unsigned long nsyms,
char * strtab,
unsigned long strtablen,
- int is_rela)
+ int is_rela,
+ int is_dynsym)
{
unsigned int i;
Elf_Internal_Rela * rels;
rtype = elf_vax_reloc_type (type);
break;
+ case EM_VISIUM:
+ rtype = elf_visium_reloc_type (type);
+ break;
+
case EM_ADAPTEVA_EPIPHANY:
rtype = elf_epiphany_reloc_type (type);
break;
else
{
Elf_Internal_Sym * psym;
+ const char * version_string;
+ enum versioned_symbol_info sym_info;
+ unsigned short vna_other;
psym = symtab + symtab_index;
+ version_string
+ = get_symbol_version_string (file, is_dynsym,
+ strtab, strtablen,
+ symtab_index,
+ psym,
+ &sym_info,
+ &vna_other);
+
printf (" ");
if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC)
name = strtab + psym->st_name;
len = print_symbol (width, name);
+ if (version_string)
+ printf (sym_info == symbol_public ? "@@%s" : "@%s",
+ version_string);
printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
}
else
else if (psym->st_name >= strtablen)
printf (_("<corrupt string table index: %3ld>"), psym->st_name);
else
- print_symbol (22, strtab + psym->st_name);
+ {
+ print_symbol (22, strtab + psym->st_name);
+ if (version_string)
+ printf (sym_info == symbol_public ? "@@%s" : "@%s",
+ version_string);
+ }
if (is_rela)
{
case EM_SVX: return "Silicon Graphics SVx";
case EM_ST19: return "STMicroelectronics ST19 8-bit microcontroller";
case EM_VAX: return "Digital VAX";
+ case EM_VISIUM: return "CDS VISIUMcore processor";
case EM_AVR_OLD:
case EM_AVR: return "Atmel AVR 8-bit microcontroller";
case EM_CRIS: return "Axis Communications 32-bit embedded processor";
strcat (buf,_(", <unknown>"));
}
+static void
+decode_AVR_machine_flags (unsigned e_flags, char buf[], size_t size)
+{
+ --size; /* Leave space for null terminator. */
+
+ switch (e_flags & EF_AVR_MACH)
+ {
+ case E_AVR_MACH_AVR1:
+ strncat (buf, ", avr:1", size);
+ break;
+ case E_AVR_MACH_AVR2:
+ strncat (buf, ", avr:2", size);
+ break;
+ case E_AVR_MACH_AVR25:
+ strncat (buf, ", avr:25", size);
+ break;
+ case E_AVR_MACH_AVR3:
+ strncat (buf, ", avr:3", size);
+ break;
+ case E_AVR_MACH_AVR31:
+ strncat (buf, ", avr:31", size);
+ break;
+ case E_AVR_MACH_AVR35:
+ strncat (buf, ", avr:35", size);
+ break;
+ case E_AVR_MACH_AVR4:
+ strncat (buf, ", avr:4", size);
+ break;
+ case E_AVR_MACH_AVR5:
+ strncat (buf, ", avr:5", size);
+ break;
+ case E_AVR_MACH_AVR51:
+ strncat (buf, ", avr:51", size);
+ break;
+ case E_AVR_MACH_AVR6:
+ strncat (buf, ", avr:6", size);
+ break;
+ case E_AVR_MACH_AVRTINY:
+ strncat (buf, ", avr:100", size);
+ break;
+ case E_AVR_MACH_XMEGA1:
+ strncat (buf, ", avr:101", size);
+ break;
+ case E_AVR_MACH_XMEGA2:
+ strncat (buf, ", avr:102", size);
+ break;
+ case E_AVR_MACH_XMEGA3:
+ strncat (buf, ", avr:103", size);
+ break;
+ case E_AVR_MACH_XMEGA4:
+ strncat (buf, ", avr:104", size);
+ break;
+ case E_AVR_MACH_XMEGA5:
+ strncat (buf, ", avr:105", size);
+ break;
+ case E_AVR_MACH_XMEGA6:
+ strncat (buf, ", avr:106", size);
+ break;
+ case E_AVR_MACH_XMEGA7:
+ strncat (buf, ", avr:107", size);
+ break;
+ default:
+ strncat (buf, ", avr:<unknown>", size);
+ break;
+ }
+
+ size -= strlen (buf);
+ if (e_flags & EF_AVR_LINKRELAX_PREPARED)
+ strncat (buf, ", link-relax", size);
+}
+
static void
decode_NDS32_machine_flags (unsigned e_flags, char buf[], size_t size)
{
decode_ARM_machine_flags (e_flags, buf);
break;
+ case EM_AVR:
+ decode_AVR_machine_flags (e_flags, buf, sizeof buf);
+ break;
+
case EM_BLACKFIN:
if (e_flags & EF_BFIN_PIC)
strcat (buf, ", PIC");
strcat (buf, ", abort");
break;
default:
- abort ();
+ warn (_("Unrecognised IA64 VMS Command Code: %x\n"),
+ e_flags & EF_IA_64_VMS_COMCOD);
+ strcat (buf, ", <unknown>");
}
}
break;
strcat (buf, ", G-Float");
break;
+ case EM_VISIUM:
+ if (e_flags & EF_VISIUM_ARCH_MCM)
+ strcat (buf, ", mcm");
+ else if (e_flags & EF_VISIUM_ARCH_MCM24)
+ strcat (buf, ", mcm24");
+ if (e_flags & EF_VISIUM_ARCH_GR6)
+ strcat (buf, ", gr6");
+ break;
+
case EM_RL78:
if (e_flags & E_FLAG_RL78_G10)
strcat (buf, ", G10");
case EM_MSP430:
case EM_MSP430_OLD:
+ case EM_VISIUM:
switch (osabi)
{
case ELFOSABI_STANDALONE: return _("Standalone App");
if (phdrs == NULL)
{
- error (_("Out of memory\n"));
+ error (_("Out of memory reading %u program headers\n"),
+ elf_header.e_phnum);
return 0;
}
if (section_headers == NULL)
{
if (!probe)
- error (_("Out of memory\n"));
+ error (_("Out of memory reading %u section headers\n"), num);
return FALSE;
}
if (section_headers == NULL)
{
if (! probe)
- error (_("Out of memory\n"));
+ error (_("Out of memory reading %u section headers\n"), num);
return FALSE;
}
Elf_Internal_Sym * psym;
unsigned int j;
+ if (section->sh_size == 0)
+ {
+ if (num_syms_return != NULL)
+ * num_syms_return = 0;
+ return NULL;
+ }
+
/* Run some sanity checks first. */
- if (section->sh_entsize == 0)
+ if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size)
{
- error (_("sh_entsize is zero\n"));
+ error (_("Section %s has an invalid sh_entsize of 0x%lx\n"),
+ printable_section_name (section), (unsigned long) section->sh_entsize);
goto exit_point;
}
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
{
- error (_("Invalid sh_entsize\n"));
+ error (_("Size (0x%lx) of section %s is not a multiple of its sh_entsize (0x%lx)\n"),
+ (unsigned long) section->sh_size,
+ printable_section_name (section),
+ (unsigned long) section->sh_entsize);
goto exit_point;
}
_("symbol table section indicies"));
if (shndx == NULL)
goto exit_point;
+ /* PR17531: file: heap-buffer-overflow */
+ else if (symtab_shndx_hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+ {
+ error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+ printable_section_name (symtab_shndx_hdr),
+ (unsigned long) symtab_shndx_hdr->sh_size,
+ (unsigned long) section->sh_size);
+ goto exit_point;
+ }
}
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
if (isyms == NULL)
{
- error (_("Out of memory\n"));
+ error (_("Out of memory reading %lu symbols\n"),
+ (unsigned long) number);
goto exit_point;
}
Elf_Internal_Sym * psym;
unsigned int j;
+ if (section->sh_size == 0)
+ {
+ if (num_syms_return != NULL)
+ * num_syms_return = 0;
+ return NULL;
+ }
+
/* Run some sanity checks first. */
- if (section->sh_entsize == 0)
+ if (section->sh_entsize == 0 || section->sh_entsize > section->sh_size)
{
- error (_("sh_entsize is zero\n"));
+ error (_("Section %s has an invalid sh_entsize of 0x%lx\n"),
+ printable_section_name (section),
+ (unsigned long) section->sh_entsize);
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);
+ printable_section_name (section),
+ (unsigned long) section->sh_size);
goto exit_point;
}
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
{
- error (_("Invalid sh_entsize\n"));
+ error (_("Size (0x%lx) of section %s is not a multiple of its sh_entsize (0x%lx)\n"),
+ (unsigned long) section->sh_size,
+ printable_section_name (section),
+ (unsigned long) section->sh_entsize);
goto exit_point;
}
_("symbol table section indicies"));
if (shndx == NULL)
goto exit_point;
+ else if (symtab_shndx_hdr->sh_size / sizeof (Elf_External_Sym_Shndx) < number)
+ {
+ error (_("Index section %s has an sh_size of 0x%lx - expected 0x%lx\n"),
+ printable_section_name (symtab_shndx_hdr),
+ (unsigned long) symtab_shndx_hdr->sh_size,
+ (unsigned long) section->sh_size);
+ goto exit_point;
+ }
}
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
if (isyms == NULL)
{
- error (_("Out of memory\n"));
+ error (_("Out of memory reading %lu symbols\n"),
+ (unsigned long) number);
goto exit_point;
}
if (p != buff + field_size + 4)
{
if (size < (10 + 2))
- abort ();
+ {
+ warn (_("Internal error: not enough buffer room for section flag info"));
+ return _("<unknown>");
+ }
size -= 2;
*p++ = ',';
*p++ = ' ';
if (p != buff + field_size + 4)
{
if (size < (2 + 1))
- abort ();
+ {
+ warn (_("Internal error: not enough buffer room for section flag info"));
+ return _("<unknown>");
+ }
size -= 2;
*p++ = ',';
*p++ = ' ';
if (p != buff + field_size + 4)
{
if (size < (2 + 1))
- abort ();
+ {
+ warn (_("Internal error: not enough buffer room for section flag info"));
+ return _("<unknown>");
+ }
size -= 2;
*p++ = ',';
*p++ = ' ';
if (p != buff + field_size + 4)
{
if (size < (2 + 1))
- abort ();
+ {
+ warn (_("Internal error: not enough buffer room for section flag info"));
+ return _("<unknown>");
+ }
size -= 2;
*p++ = ',';
*p++ = ' ';
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;
}
if (section_groups == NULL)
{
- error (_("Out of memory\n"));
+ error (_("Out of memory reading %lu groups\n"),
+ (unsigned long) group_count);
return 0;
}
? strtab + sym->st_name : _("<corrupt>");
}
+ /* PR 17531: file: loop. */
+ if (section->sh_entsize > section->sh_size)
+ {
+ error (_("Section %s has sh_entsize (0x%lx) which is larger than its size (0x%lx)\n"),
+ printable_section_name (section),
+ (unsigned long) section->sh_entsize,
+ (unsigned long) section->sh_size);
+ break;
+ }
+
start = (unsigned char *) get_data (NULL, file, section->sh_offset,
1, section->sh_size,
_("section data"));
offset_from_vma (file, rel_offset, rel_size),
rel_size,
dynamic_symbols, num_dynamic_syms,
- dynamic_strings, dynamic_strings_length, is_rela);
+ dynamic_strings, dynamic_strings_length,
+ is_rela, 1);
}
}
}
dump_relocations (file, rel_offset, rel_size,
- symtab, nsyms, strtab, strtablen, is_rela);
+ symtab, nsyms, strtab, strtablen,
+ is_rela,
+ symsec->sh_type == SHT_DYNSYM);
if (strtab)
free (strtab);
free (symtab);
}
else
dump_relocations (file, rel_offset, rel_size,
- NULL, 0, NULL, 0, is_rela);
+ NULL, 0, NULL, 0, is_rela, 0);
found = 1;
}
bfd_vma offset;
const unsigned char * dp;
const unsigned char * head;
+ const unsigned char * end;
const char * procname;
find_symbol_for_address (aux->symtab, aux->nsyms, aux->strtab,
printf ("], info at +0x%lx\n",
(unsigned long) (tp->info.offset - aux->seg_base));
+ /* PR 17531: file: 86232b32. */
+ if (aux->info == NULL)
+ continue;
+
+ /* PR 17531: file: 0997b4d1. */
+ if ((ABSADDR (tp->info) - aux->info_addr) >= aux->info_size)
+ {
+ warn (_("Invalid offset %lx in table entry %ld\n"),
+ (long) tp->info.offset, (long) (tp - aux->table));
+ continue;
+ }
+
head = aux->info + (ABSADDR (tp->info) - aux->info_addr);
stamp = byte_get ((unsigned char *) head, sizeof (stamp));
}
in_body = 0;
- for (dp = head + 8; dp < head + 8 + eh_addr_size * UNW_LENGTH (stamp);)
+ end = head + 8 + eh_addr_size * UNW_LENGTH (stamp);
+ /* PR 17531: file: 16ceda89. */
+ if (end > aux->info + aux->info_size)
+ end = aux->info + aux->info_size;
+ for (dp = head + 8; dp < end;)
dp = unw_decode (dp, in_body, & in_body);
}
}
-static int
+static bfd_boolean
slurp_ia64_unwind_table (FILE * file,
struct ia64_unw_aux_info * aux,
Elf_Internal_Shdr * sec)
Elf_Internal_Sym * sym;
const char * relname;
+ aux->table_len = 0;
+
/* First, find the starting address of the segment that includes
this section: */
if (elf_header.e_phnum)
{
if (! get_program_headers (file))
- return 0;
+ return FALSE;
for (seg = program_headers;
seg < program_headers + elf_header.e_phnum;
table = (unsigned char *) get_data (NULL, file, sec->sh_offset, 1, size,
_("unwind table"));
if (!table)
- return 0;
+ return FALSE;
+ aux->table_len = size / (3 * eh_addr_size);
aux->table = (struct ia64_unw_table_entry *)
- xcmalloc (size / (3 * eh_addr_size), sizeof (aux->table[0]));
+ xcmalloc (aux->table_len, sizeof (aux->table[0]));
tep = aux->table;
- for (tp = table; tp < table + size; ++tep)
+
+ for (tp = table; tp <= table + size - (3 * eh_addr_size); ++tep)
{
tep->start.section = SHN_UNDEF;
tep->end.section = SHN_UNDEF;
if (!slurp_rela_relocs (file, relsec->sh_offset, relsec->sh_size,
& rela, & nrelas))
- return 0;
+ {
+ free (aux->table);
+ aux->table = NULL;
+ aux->table_len = 0;
+ return FALSE;
+ }
for (rp = rela; rp < rela + nrelas; ++rp)
{
i = rp->r_offset / (3 * eh_addr_size);
- switch (rp->r_offset/eh_addr_size % 3)
+ /* PR 17531: file: 5bc8d9bf. */
+ if (i >= aux->table_len)
+ {
+ warn (_("Skipping reloc with overlarge offset: %lx\n"), i);
+ continue;
+ }
+
+ switch (rp->r_offset / eh_addr_size % 3)
{
case 0:
aux->table[i].start.section = sym->st_shndx;
free (rela);
}
- aux->table_len = size / (3 * eh_addr_size);
- return 1;
+ return TRUE;
}
static void
(unsigned long) unwsec->sh_offset,
(unsigned long) (unwsec->sh_size / (3 * eh_addr_size)));
- (void) slurp_ia64_unwind_table (file, & aux, unwsec);
-
- if (aux.table_len > 0)
+ if (slurp_ia64_unwind_table (file, & aux, unwsec)
+ && aux.table_len > 0)
dump_ia64_unwind (& aux);
if (aux.table)
/* Get the word at the required offset. */
word = byte_get (arm_sec->data + word_offset, 4);
+ /* PR 17531: file: id:000001,src:001266+003044,op:splice,rep:128. */
+ if (arm_sec->rela == NULL)
+ {
+ * wordp = word;
+ return TRUE;
+ }
+
/* Look through the relocs to find the one that applies to the provided offset. */
wrapped = FALSE;
for (rp = arm_sec->next_rela; rp != arm_sec->rela + arm_sec->nrelas; rp++)
if ((buf[i] & 0x80) == 0)
break;
}
- assert (i < sizeof (buf));
+ /* PR 17531: file: id:000001,src:001906+004739,op:splice,rep:2. */
+ if (i == sizeof (buf))
+ {
+ printf ("<corrupt sp adjust>\n");
+ warn (_("Corrupt stack pointer adjustment detected\n"));
+ return;
+ }
+
offset = read_uleb128 (buf, &len, buf + i + 1);
assert (len == i + 1);
offset = offset * 8 + 0x408;
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;
}
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;
}
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;
}
}
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"));
if (j < ent.vd_cnt)
printf (_(" Version def aux past end of section\n"));
+ /* PR 17531: file: id:000001,src:000172+005151,op:splice,rep:2. */
+ if (idx + ent.vd_next <= idx)
+ break;
+
idx += ent.vd_next;
}
/* Check for overflow. */
if (ent.vn_aux > (size_t) (endbuf - vstart))
break;
-
vstart += ent.vn_aux;
for (j = 0, isum = idx + ent.vn_aux; j < ent.vn_cnt; ++j)
get_ver_flags (aux.vna_flags), aux.vna_other);
/* Check for overflow. */
- if (aux.vna_next > (size_t) (endbuf - vstart))
- break;
-
+ if (aux.vna_next > (size_t) (endbuf - vstart)
+ || (aux.vna_next == 0 && j < ent.vn_cnt - 1))
+ {
+ warn (_("Invalid vna_next field of %lx\n"),
+ aux.vna_next);
+ j = ent.vn_cnt;
+ break;
+ }
isum += aux.vna_next;
vstart += aux.vna_next;
}
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;
break;
}
- printf (_("\nVersion symbols section '%s' contains %d entries:\n"),
- printable_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);
_("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
{
case STV_INTERNAL: return "INTERNAL";
case STV_HIDDEN: return "HIDDEN";
case STV_PROTECTED: return "PROTECTED";
- default: abort ();
+ default:
+ error (_("Unrecognized visibility value: %u"), visibility);
+ return _("<unknown>");
}
}
strcat (res, " RSV");
break;
default:
- abort ();
+ warn (_("Unrecognized IA64 VMS ST Function type: %d\n"),
+ VMS_ST_FUNC_TYPE (other));
+ strcat (res, " <unknown>");
+ break;
}
break;
default:
strcat (res, " LNK");
break;
default:
- abort ();
+ warn (_("Unrecognized IA64 VMS ST Linkage: %d\n"),
+ VMS_ST_LINKAGE (other));
+ strcat (res, " <unknown>");
+ break;
}
if (res[0] != 0)
}
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;
}
if (dynamic_symbols == NULL || si >= num_dynamic_syms)
{
- printf (_("<No info available>\n"));
+ printf (_("<No info available for dynamic symbol number %lu>\n"),
+ (unsigned long) si);
return;
}
putchar ('\n');
}
+static const char *
+get_symbol_version_string (FILE *file, int is_dynsym,
+ const char *strtab,
+ unsigned long int strtab_size,
+ unsigned int si, Elf_Internal_Sym *psym,
+ enum versioned_symbol_info *sym_info,
+ unsigned short *vna_other)
+{
+ const char *version_string = NULL;
+
+ if (is_dynsym
+ && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
+ {
+ unsigned char data[2];
+ unsigned short vers_data;
+ unsigned long offset;
+ int is_nobits;
+ int check_def;
+
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+ sizeof data + si * sizeof (vers_data));
+
+ if (get_data (&data, file, offset + si * sizeof (vers_data),
+ sizeof (data), 1, _("version data")) == NULL)
+ return NULL;
+
+ vers_data = byte_get (data, 2);
+
+ is_nobits = (section_headers != NULL
+ && psym->st_shndx < elf_header.e_shnum
+ && section_headers[psym->st_shndx].sh_type
+ == SHT_NOBITS);
+
+ check_def = (psym->st_shndx != SHN_UNDEF);
+
+ if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
+ {
+ if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
+ && (is_nobits || ! check_def))
+ {
+ Elf_External_Verneed evn;
+ Elf_Internal_Verneed ivn;
+ Elf_Internal_Vernaux ivna;
+
+ /* We must test both. */
+ offset = offset_from_vma
+ (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+ sizeof evn);
+
+ do
+ {
+ unsigned long vna_off;
+
+ if (get_data (&evn, file, offset, sizeof (evn), 1,
+ _("version need")) == NULL)
+ {
+ ivna.vna_next = 0;
+ ivna.vna_other = 0;
+ ivna.vna_name = 0;
+ break;
+ }
+
+ ivn.vn_aux = BYTE_GET (evn.vn_aux);
+ ivn.vn_next = BYTE_GET (evn.vn_next);
+
+ vna_off = offset + ivn.vn_aux;
+
+ do
+ {
+ Elf_External_Vernaux evna;
+
+ if (get_data (&evna, file, vna_off,
+ sizeof (evna), 1,
+ _("version need aux (3)")) == NULL)
+ {
+ ivna.vna_next = 0;
+ ivna.vna_other = 0;
+ ivna.vna_name = 0;
+ }
+ else
+ {
+ ivna.vna_other = BYTE_GET (evna.vna_other);
+ ivna.vna_next = BYTE_GET (evna.vna_next);
+ ivna.vna_name = BYTE_GET (evna.vna_name);
+ }
+
+ vna_off += ivna.vna_next;
+ }
+ while (ivna.vna_other != vers_data
+ && ivna.vna_next != 0);
+
+ if (ivna.vna_other == vers_data)
+ break;
+
+ offset += ivn.vn_next;
+ }
+ while (ivn.vn_next != 0);
+
+ if (ivna.vna_other == vers_data)
+ {
+ *sym_info = symbol_undefined;
+ *vna_other = ivna.vna_other;
+ version_string = (ivna.vna_name < strtab_size
+ ? strtab + ivna.vna_name
+ : _("<corrupt>"));
+ check_def = 0;
+ }
+ else if (! is_nobits)
+ error (_("bad dynamic symbol\n"));
+ else
+ check_def = 1;
+ }
+
+ if (check_def)
+ {
+ if (vers_data != 0x8001
+ && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
+ {
+ Elf_Internal_Verdef ivd;
+ Elf_Internal_Verdaux ivda;
+ Elf_External_Verdaux evda;
+ unsigned long off;
+
+ off = offset_from_vma
+ (file,
+ version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+ sizeof (Elf_External_Verdef));
+
+ do
+ {
+ Elf_External_Verdef evd;
+
+ if (get_data (&evd, file, off, sizeof (evd),
+ 1, _("version def")) == NULL)
+ {
+ ivd.vd_ndx = 0;
+ ivd.vd_aux = 0;
+ ivd.vd_next = 0;
+ }
+ else
+ {
+ ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
+ ivd.vd_aux = BYTE_GET (evd.vd_aux);
+ ivd.vd_next = BYTE_GET (evd.vd_next);
+ }
+
+ off += ivd.vd_next;
+ }
+ while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
+ && ivd.vd_next != 0);
+
+ off -= ivd.vd_next;
+ off += ivd.vd_aux;
+
+ if (get_data (&evda, file, off, sizeof (evda),
+ 1, _("version def aux")) == NULL)
+ return version_string;
+
+ ivda.vda_name = BYTE_GET (evda.vda_name);
+
+ if (psym->st_name != ivda.vda_name)
+ {
+ *sym_info = ((vers_data & VERSYM_HIDDEN) != 0
+ ? symbol_hidden : symbol_public);
+ version_string = (ivda.vda_name < strtab_size
+ ? strtab + ivda.vda_name
+ : _("<corrupt>"));
+ }
+ }
+ }
+ }
+ }
+ return version_string;
+}
+
/* Dump the symbol table. */
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;
{
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
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;
}
}
}
- 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;
for (si = 0, psym = symtab; si < num_syms; si++, psym++)
{
+ const char *version_string;
+ enum versioned_symbol_info sym_info;
+ unsigned short vna_other;
+
printf ("%6d: ", si);
print_vma (psym->st_value, LONG_HEX);
putchar (' ');
print_symbol (25, psym->st_name < strtab_size
? strtab + psym->st_name : _("<corrupt>"));
- if (section->sh_type == SHT_DYNSYM
- && version_info[DT_VERSIONTAGIDX (DT_VERSYM)] != 0)
+ version_string
+ = get_symbol_version_string (file,
+ section->sh_type == SHT_DYNSYM,
+ strtab, strtab_size, si,
+ psym, &sym_info, &vna_other);
+ if (version_string)
{
- unsigned char data[2];
- unsigned short vers_data;
- unsigned long offset;
- int is_nobits;
- int check_def;
-
- offset = offset_from_vma
- (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
- sizeof data + si * sizeof (vers_data));
-
- if (get_data (&data, file, offset + si * sizeof (vers_data),
- sizeof (data), 1, _("version data")) == NULL)
- break;
-
- vers_data = byte_get (data, 2);
-
- is_nobits = (psym->st_shndx < elf_header.e_shnum
- && section_headers[psym->st_shndx].sh_type
- == SHT_NOBITS);
-
- check_def = (psym->st_shndx != SHN_UNDEF);
-
- if ((vers_data & VERSYM_HIDDEN) || vers_data > 1)
- {
- if (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
- && (is_nobits || ! check_def))
- {
- Elf_External_Verneed evn;
- Elf_Internal_Verneed ivn;
- Elf_Internal_Vernaux ivna;
-
- /* We must test both. */
- offset = offset_from_vma
- (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
- sizeof evn);
-
- do
- {
- unsigned long vna_off;
-
- if (get_data (&evn, file, offset, sizeof (evn), 1,
- _("version need")) == NULL)
- {
- ivna.vna_next = 0;
- ivna.vna_other = 0;
- ivna.vna_name = 0;
- break;
- }
-
- ivn.vn_aux = BYTE_GET (evn.vn_aux);
- ivn.vn_next = BYTE_GET (evn.vn_next);
-
- vna_off = offset + ivn.vn_aux;
-
- do
- {
- Elf_External_Vernaux evna;
-
- if (get_data (&evna, file, vna_off,
- sizeof (evna), 1,
- _("version need aux (3)")) == NULL)
- {
- ivna.vna_next = 0;
- ivna.vna_other = 0;
- ivna.vna_name = 0;
- }
- else
- {
- ivna.vna_other = BYTE_GET (evna.vna_other);
- ivna.vna_next = BYTE_GET (evna.vna_next);
- ivna.vna_name = BYTE_GET (evna.vna_name);
- }
-
- vna_off += ivna.vna_next;
- }
- while (ivna.vna_other != vers_data
- && ivna.vna_next != 0);
-
- if (ivna.vna_other == vers_data)
- break;
-
- offset += ivn.vn_next;
- }
- while (ivn.vn_next != 0);
-
- if (ivna.vna_other == vers_data)
- {
- printf ("@%s (%d)",
- ivna.vna_name < strtab_size
- ? strtab + ivna.vna_name : _("<corrupt>"),
- ivna.vna_other);
- check_def = 0;
- }
- else if (! is_nobits)
- error (_("bad dynamic symbol\n"));
- else
- check_def = 1;
- }
-
- if (check_def)
- {
- if (vers_data != 0x8001
- && version_info[DT_VERSIONTAGIDX (DT_VERDEF)])
- {
- Elf_Internal_Verdef ivd;
- Elf_Internal_Verdaux ivda;
- Elf_External_Verdaux evda;
- unsigned long off;
-
- off = offset_from_vma
- (file,
- version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
- sizeof (Elf_External_Verdef));
-
- do
- {
- Elf_External_Verdef evd;
-
- if (get_data (&evd, file, off, sizeof (evd),
- 1, _("version def")) == NULL)
- {
- ivd.vd_ndx = 0;
- ivd.vd_aux = 0;
- ivd.vd_next = 0;
- }
- else
- {
- ivd.vd_ndx = BYTE_GET (evd.vd_ndx);
- ivd.vd_aux = BYTE_GET (evd.vd_aux);
- ivd.vd_next = BYTE_GET (evd.vd_next);
- }
-
- off += ivd.vd_next;
- }
- while (ivd.vd_ndx != (vers_data & VERSYM_VERSION)
- && ivd.vd_next != 0);
-
- off -= ivd.vd_next;
- off += ivd.vd_aux;
-
- if (get_data (&evda, file, off, sizeof (evda),
- 1, _("version def aux")) == NULL)
- break;
-
- ivda.vda_name = BYTE_GET (evda.vda_name);
-
- if (psym->st_name != ivda.vda_name)
- printf ((vers_data & VERSYM_HIDDEN)
- ? "@%s" : "@@%s",
- ivda.vda_name < strtab_size
- ? strtab + ivda.vda_name : _("<corrupt>"));
- }
- }
- }
+ if (sym_info == symbol_undefined)
+ printf ("@%s (%d)", version_string, vna_other);
+ else
+ printf (sym_info == symbol_hidden ? "@%s" : "@@%s",
+ version_string);
}
putchar ('\n');
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])
if (counts == NULL)
{
free (lengths);
- error (_("Out of memory\n"));
+ error (_("Out of memory allocating space for histogram counts\n"));
return 0;
}
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)
if (counts == NULL)
{
free (lengths);
- error (_("Out of memory\n"));
+ error (_("Out of memory allocating space for gnu histogram counts\n"));
return 0;
}
return reloc_type == 0x33; /* R_V810_WORD. */
case EM_VAX:
return reloc_type == 1; /* R_VAX_32. */
+ case EM_VISIUM:
+ return reloc_type == 3; /* R_VISIUM_32. */
case EM_X86_64:
case EM_L1OM:
case EM_K1OM:
case EM_XTENSA:
return reloc_type == 1; /* R_XTENSA_32. */
default:
- error (_("Missing knowledge of 32-bit reloc types used in DWARF sections of machine number %d\n"),
- elf_header.e_machine);
- abort ();
+ {
+ static unsigned int prev_warn = 0;
+
+ /* Avoid repeating the same warning multiple times. */
+ if (prev_warn != elf_header.e_machine)
+ error (_("Missing knowledge of 32-bit reloc types used in DWARF sections of machine number %d\n"),
+ elf_header.e_machine);
+ prev_warn = elf_header.e_machine;
+ return FALSE;
+ }
}
}
return reloc_type == 6; /* R_TILEGX_32_PCREL. */
case EM_TILEPRO:
return reloc_type == 4; /* R_TILEPRO_32_PCREL. */
+ case EM_VISIUM:
+ return reloc_type == 6; /* R_VISIUM_32_PCREL */
case EM_X86_64:
case EM_L1OM:
case EM_K1OM:
case EM_CYGNUS_MN10300:
case EM_MN10300:
return reloc_type == 2; /* R_MN10300_16. */
+ case EM_VISIUM:
+ return reloc_type == 2; /* R_VISIUM_16. */
case EM_XGATE:
return reloc_type == 3; /* R_XGATE_16. */
default:
reloc_size = 2;
else
{
- warn (_("unable to apply unsupported reloc type %d to section %s\n"),
- reloc_type, printable_section_name (section));
+ static unsigned int prev_reloc = 0;
+ if (reloc_type != prev_reloc)
+ warn (_("unable to apply unsupported reloc type %d to section %s\n"),
+ reloc_type, printable_section_name (section));
+ prev_reloc = reloc_type;
continue;
}
snprintf (buf, sizeof (buf), _("%s section data"), section->name);
section->address = sec->sh_addr;
+ section->user_data = NULL;
section->start = (unsigned char *) get_data (NULL, (FILE *) file,
sec->sh_offset, 1,
sec->sh_size, buf);
{"No", "Thumb-1", "Thumb-2"};
static const char * arm_attr_tag_FP_arch[] =
{"No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16", "VFPv4", "VFPv4-D16",
- "FP for ARMv8"};
+ "FP for ARMv8", "FPv5/FP-D16 for ARMv8"};
static const char * arm_attr_tag_WMMX_arch[] = {"No", "WMMXv1", "WMMXv2"};
static const char * arm_attr_tag_Advanced_SIMD_arch[] =
{"No", "NEONv1", "NEONv1 with Fused-MAC", "NEON for ARMv8"};
static const char * arm_attr_tag_ABI_HardFP_use[] =
{"As Tag_FP_arch", "SP only", "DP only", "SP and DP"};
static const char * arm_attr_tag_ABI_VFP_args[] =
- {"AAPCS", "VFP registers", "custom"};
+ {"AAPCS", "VFP registers", "custom", "compatible"};
static const char * arm_attr_tag_ABI_WMMX_args[] =
{"AAPCS", "WMMX registers", "custom"};
static const char * arm_attr_tag_ABI_optimization_goals[] =
break;
default:
- abort ();
+ printf (_("<unknown: %d>\n"), tag);
+ break;
}
return p;
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;
}
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;
}
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);
if (inote.descdata < (char *) external + min_notesz
|| next < (char *) external + min_notesz
+ /* PR binutils/17531: file: id:000000,sig:11,src:006986,op:havoc,rep:4. */
+ || inote.namedata + inote.namesz < inote.namedata
+ || inote.descdata + inote.descsz < inote.descdata
|| data_remaining < (size_t)(next - (char *) external))
{
warn (_("note with invalid namesz and/or descsz found at offset 0x%lx\n"),
if (inote.namedata[inote.namesz - 1] != '\0')
{
temp = (char *) malloc (inote.namesz + 1);
-
if (temp == NULL)
{
- error (_("Out of memory\n"));
+ error (_("Out of memory allocating space for inote name\n"));
res = 0;
break;
}
error (_("%s: unable to dump the index as none was found\n"), file_name);
else
{
- unsigned int i, l;
+ unsigned long i, l;
unsigned long current_pos;
- printf (_("Index of archive %s: (%ld entries, 0x%lx bytes in the symbol table)\n"),
- file_name, (long) arch.index_num, arch.sym_size);
+ printf (_("Index of archive %s: (%lu entries, 0x%lx bytes in the symbol table)\n"),
+ file_name, (unsigned long) arch.index_num, arch.sym_size);
current_pos = ftell (file);
for (i = l = 0; i < arch.index_num; i++)
file_name);
break;
}
- printf ("\t%s\n", arch.sym_table + l);
- l += strlen (arch.sym_table + l) + 1;
+ /* PR 17531: file: 0b6630b2. */
+ printf ("\t%.*s\n", (int) (arch.sym_size - l), arch.sym_table + l);
+ l += strnlen (arch.sym_table + l, arch.sym_size - l) + 1;
}
if (arch.uses_64bit_indicies)