/* readelf.c -- display contents of an ELF format file
- Copyright (C) 1998-2018 Free Software Foundation, Inc.
+ Copyright (C) 1998-2019 Free Software Foundation, Inc.
Originally developed by Eric Youngdale <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com>
return NULL;
}
- /* Be kind to memory chekers (eg valgrind, address sanitizer) by not
+ /* Be kind to memory checkers (eg valgrind, address sanitizer) by not
attempting to allocate memory when the read is bound to fail. */
- if (amt > filedata->file_size
- || offset + archive_file_offset + amt > filedata->file_size)
+ if (archive_file_offset > filedata->file_size
+ || offset > filedata->file_size - archive_file_offset
+ || amt > filedata->file_size - archive_file_offset - offset)
{
if (reason)
error (_("Reading %s bytes extends past end of file for %s\n"),
? ", uses String instructions" : ", bans String instructions");
if (e_flags & E_FLAG_RX_V2)
strcat (buf, ", V2");
+ if (e_flags & E_FLAG_RX_V3)
+ strcat (buf, ", V3");
break;
case EM_S390:
case PT_GNU_EH_FRAME: return "GNU_EH_FRAME";
case PT_GNU_STACK: return "GNU_STACK";
case PT_GNU_RELRO: return "GNU_RELRO";
+ case PT_GNU_PROPERTY: return "GNU_PROPERTY";
default:
if (p_type >= PT_GNU_MBIND_LO && p_type <= PT_GNU_MBIND_HI)
}
}
+static const char *
+get_riscv_section_type_name (unsigned int sh_type)
+{
+ switch (sh_type)
+ {
+ case SHT_RISCV_ATTRIBUTES: return "RISCV_ATTRIBUTES";
+ default: return NULL;
+ }
+}
+
static const char *
get_section_type_name (Filedata * filedata, unsigned int sh_type)
{
case EM_CYGNUS_V850:
result = get_v850_section_type_name (sh_type);
break;
+ case EM_RISCV:
+ result = get_riscv_section_type_name (sh_type);
+ break;
default:
result = NULL;
break;
segment. Check this after matching against the section headers
so we don't warn on debuginfo file (which have NOBITS .dynamic
sections). */
- if (dynamic_addr + dynamic_size >= filedata->file_size)
+ if (dynamic_addr > filedata->file_size
+ || dynamic_size > filedata->file_size - dynamic_addr)
{
error (_("the dynamic segment offset + size exceeds the size of the file\n"));
dynamic_addr = dynamic_size = 0;
for (rp = rela; rp < rela + nrelas; ++rp)
{
- relname = elf_ia64_reloc_type (get_reloc_type (filedata, rp->r_info));
- sym = aux->symtab + get_reloc_symindex (rp->r_info);
+ unsigned int sym_ndx;
+ unsigned int r_type = get_reloc_type (filedata, rp->r_info);
+ relname = elf_ia64_reloc_type (r_type);
/* PR 17531: file: 9fa67536. */
if (relname == NULL)
{
- warn (_("Skipping unknown relocation type: %u\n"),
- get_reloc_type (filedata, rp->r_info));
+ warn (_("Skipping unknown relocation type: %u\n"), r_type);
continue;
}
continue;
}
+ sym_ndx = get_reloc_symindex (rp->r_info);
+ if (sym_ndx >= aux->nsyms)
+ {
+ warn (_("Skipping reloc with invalid symbol index: %u\n"),
+ sym_ndx);
+ continue;
+ }
+ sym = aux->symtab + sym_ndx;
+
switch (rp->r_offset / eh_addr_size % 3)
{
case 0:
for (rp = rela; rp < rela + nrelas; ++rp)
{
- relname = elf_hppa_reloc_type (get_reloc_type (filedata, rp->r_info));
- sym = aux->symtab + get_reloc_symindex (rp->r_info);
+ unsigned int sym_ndx;
+ unsigned int r_type = get_reloc_type (filedata, rp->r_info);
+ relname = elf_hppa_reloc_type (r_type);
+
+ if (relname == NULL)
+ {
+ warn (_("Skipping unknown relocation type: %u\n"), r_type);
+ continue;
+ }
/* R_PARISC_SEGREL32 or R_PARISC_SEGREL64. */
if (! const_strneq (relname, "R_PARISC_SEGREL"))
{
- warn (_("Skipping unexpected relocation type %s\n"), relname);
+ warn (_("Skipping unexpected relocation type: %s\n"), relname);
continue;
}
i = rp->r_offset / unw_ent_size;
+ if (i >= aux->table_len)
+ {
+ warn (_("Skipping reloc with overlarge offset: %lx\n"), i);
+ continue;
+ }
+
+ sym_ndx = get_reloc_symindex (rp->r_info);
+ if (sym_ndx >= aux->nsyms)
+ {
+ warn (_("Skipping reloc with invalid symbol index: %u\n"),
+ sym_ndx);
+ continue;
+ }
+ sym = aux->symtab + sym_ndx;
switch ((rp->r_offset % unw_ent_size) / 4)
{
}
printf (_("pop frame {"));
- reg = nregs - 1;
- for (i = i * 2; i > 0; i--)
+ if (nregs == 0)
+ {
+ printf (_("*corrupt* - no registers specified"));
+ }
+ else
{
- if (regpos[reg].offset == i - 1)
+ reg = nregs - 1;
+ for (i = i * 2; i > 0; i--)
{
- name = tic6x_unwind_regnames[regpos[reg].reg];
- if (reg > 0)
- reg--;
- }
- else
- name = _("[pad]");
+ if (regpos[reg].offset == i - 1)
+ {
+ name = tic6x_unwind_regnames[regpos[reg].reg];
+ if (reg > 0)
+ reg--;
+ }
+ else
+ name = _("[pad]");
- fputs (name, stdout);
- if (i > 1)
- printf (", ");
+ fputs (name, stdout);
+ if (i > 1)
+ printf (", ");
+ }
}
printf ("}");
printable_section_name (filedata, section), chdr.ch_type);
return FALSE;
}
- else if (chdr.ch_addralign != section->sh_addralign)
- {
- warn (_("compressed section '%s' is corrupted\n"),
- printable_section_name (filedata, section));
- return FALSE;
- }
uncompressed_size = chdr.ch_size;
start += compression_header_size;
new_size -= compression_header_size;
printable_section_name (filedata, section), chdr.ch_type);
return FALSE;
}
- else if (chdr.ch_addralign != section->sh_addralign)
- {
- warn (_("compressed section '%s' is corrupted\n"),
- printable_section_name (filedata, section));
- return FALSE;
- }
uncompressed_size = chdr.ch_size;
start += compression_header_size;
new_size -= compression_header_size;
section->name, chdr.ch_type);
return FALSE;
}
- else if (chdr.ch_addralign != sec->sh_addralign)
- {
- warn (_("compressed section '%s' is corrupted\n"),
- section->name);
- return FALSE;
- }
uncompressed_size = chdr.ch_size;
start += compression_header_size;
size -= compression_header_size;
return p;
}
+struct riscv_attr_tag_t {
+ const char *name;
+ int tag;
+};
+
+static struct riscv_attr_tag_t riscv_attr_tag[] =
+{
+#define T(tag) {"Tag_RISCV_" #tag, Tag_RISCV_##tag}
+ T(arch),
+ T(priv_spec),
+ T(priv_spec_minor),
+ T(priv_spec_revision),
+ T(unaligned_access),
+ T(stack_align),
+#undef T
+};
+
+static unsigned char *
+display_riscv_attribute (unsigned char *p,
+ const unsigned char * const end)
+{
+ unsigned int len;
+ int val;
+ int tag;
+ struct riscv_attr_tag_t *attr = NULL;
+ unsigned i;
+
+ tag = read_uleb128 (p, &len, end);
+ p += len;
+
+ /* Find the name of attribute. */
+ for (i = 0; i < ARRAY_SIZE (riscv_attr_tag); i++)
+ {
+ if (riscv_attr_tag[i].tag == tag)
+ {
+ attr = &riscv_attr_tag[i];
+ break;
+ }
+ }
+
+ if (attr)
+ printf (" %s: ", attr->name);
+ else
+ return display_tag_value (tag, p, end);
+
+ switch (tag)
+ {
+ case Tag_RISCV_priv_spec:
+ case Tag_RISCV_priv_spec_minor:
+ case Tag_RISCV_priv_spec_revision:
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (_("%d\n"), val);
+ break;
+ case Tag_RISCV_unaligned_access:
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ switch (val)
+ {
+ case 0:
+ printf (_("No unaligned access\n"));
+ break;
+ case 1:
+ printf (_("Unaligned access\n"));
+ break;
+ }
+ break;
+ case Tag_RISCV_stack_align:
+ val = read_uleb128 (p, &len, end);
+ p += len;
+ printf (_("%d-bytes\n"), val);
+ break;
+ case Tag_RISCV_arch:
+ p = display_tag_value (-1, p, end);
+ break;
+ default:
+ return display_tag_value (tag, p, end);
+ }
+
+ return p;
+}
+
static bfd_boolean
process_attributes (Filedata * filedata,
const char * public_name,
static void
decode_x86_isa (unsigned int bitmask)
{
- if (bitmask == GNU_PROPERTY_X86_UINT32_VALID)
+ if (!bitmask)
{
printf (_("<None>"));
return;
}
- else
- bitmask &= ~GNU_PROPERTY_X86_UINT32_VALID;
while (bitmask)
{
static void
decode_x86_feature_1 (unsigned int bitmask)
{
- if (bitmask == GNU_PROPERTY_X86_UINT32_VALID)
+ if (!bitmask)
{
printf (_("<None>"));
return;
}
- else
- bitmask &= ~GNU_PROPERTY_X86_UINT32_VALID;
while (bitmask)
{
static void
decode_x86_feature_2 (unsigned int bitmask)
{
- if (bitmask == GNU_PROPERTY_X86_UINT32_VALID)
+ if (!bitmask)
{
printf (_("<None>"));
return;
}
- else
- bitmask &= ~GNU_PROPERTY_X86_UINT32_VALID;
while (bitmask)
{
unsigned int bitmask;
if (datasz == 4)
- {
- bitmask = byte_get (ptr, 4);
- if ((filedata->file_header.e_type == ET_EXEC
- || filedata->file_header.e_type == ET_DYN)
- && !(bitmask & GNU_PROPERTY_X86_UINT32_VALID))
- printf ("Invalid ");
- }
+ bitmask = byte_get (ptr, 4);
else
bitmask = 0;
one version of Linux (RedHat 6.0) generates corefiles that don't
comply with the ELF spec by failing to include the null byte in
namesz. */
- if (inote.namedata[inote.namesz - 1] != '\0')
+ if (inote.namesz > 0 && inote.namedata[inote.namesz - 1] != '\0')
{
if ((size_t) (inote.descdata - inote.namedata) == inote.namesz)
{
display_msp430x_attribute,
display_generic_attribute);
+ case EM_RISCV:
+ return process_attributes (filedata, "riscv", SHT_RISCV_ATTRIBUTES,
+ display_riscv_attribute,
+ display_generic_attribute);
+
case EM_NDS32:
return process_nds32_specific (filedata);
/* Read the next archive header. */
if (fseek (filedata->handle, arch.next_arhdr_offset, SEEK_SET) != 0)
{
- error (_("%s: failed to seek to next archive header\n"), filedata->file_name);
+ error (_("%s: failed to seek to next archive header\n"), arch.file_name);
return FALSE;
}
got = fread (&arch.arhdr, 1, sizeof arch.arhdr, filedata->handle);
{
if (got == 0)
break;
- error (_("%s: failed to read archive header\n"), filedata->file_name);
+ /* PR 24049 - we cannot use filedata->file_name as this will
+ have already been freed. */
+ error (_("%s: failed to read archive header\n"), arch.file_name);
+
ret = FALSE;
break;
}
name = get_archive_member_name (&arch, &nested_arch);
if (name == NULL)
{
- error (_("%s: bad archive file name\n"), filedata->file_name);
+ error (_("%s: bad archive file name\n"), arch.file_name);
ret = FALSE;
break;
}
qualified_name = make_qualified_name (&arch, &nested_arch, name);
if (qualified_name == NULL)
{
- error (_("%s: bad archive file name\n"), filedata->file_name);
+ error (_("%s: bad archive file name\n"), arch.file_name);
ret = FALSE;
break;
}
if (nested_arch.file == NULL)
{
error (_("%s: contains corrupt thin archive: %s\n"),
- filedata->file_name, name);
+ qualified_name, name);
ret = FALSE;
break;
}