summaryrefslogtreecommitdiffstats
path: root/src/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/readelf.c')
-rw-r--r--src/readelf.c153
1 files changed, 107 insertions, 46 deletions
diff --git a/src/readelf.c b/src/readelf.c
index 90a14061..c8c9851b 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -910,7 +910,6 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
if (ehdr == NULL)
{
- elf_error:
error (0, 0, gettext ("cannot read ELF header: %s"), elf_errmsg (-1));
return;
}
@@ -953,7 +952,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
{
/* Read the file afresh. */
off_t aroff = elf_getaroff (elf);
- pure_elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+ pure_elf = dwelf_elf_begin (fd);
if (aroff > 0)
{
/* Archive member. */
@@ -963,7 +962,10 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
pure_elf = armem;
}
if (pure_elf == NULL)
- goto elf_error;
+ {
+ error (0, 0, gettext ("cannot read ELF: %s"), elf_errmsg (-1));
+ return;
+ }
pure_ebl = ebl_openbackend (pure_elf);
if (pure_ebl == NULL)
goto ebl_error;
@@ -1535,9 +1537,12 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
static const char *
-section_name (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr)
+section_name (Ebl *ebl, GElf_Shdr *shdr)
{
- return elf_strptr (ebl->elf, ehdr->e_shstrndx, shdr->sh_name) ?: "???";
+ size_t shstrndx;
+ if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
+ return "???";
+ return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
}
@@ -5008,7 +5013,7 @@ listptr_cu (struct listptr_table *table, size_t *idxp,
static void
print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
const size_t sh_size = (dbg->sectiondata[IDX_debug_abbrev] ?
@@ -5016,7 +5021,7 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
" [ Code]\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
Dwarf_Off offset = 0;
@@ -5086,7 +5091,7 @@ print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
if (shdr->sh_size == 0)
@@ -5334,7 +5339,7 @@ print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
"\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
cnt),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset, cnt);
/* Compute floor(log16(cnt)). */
@@ -5395,7 +5400,7 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
const unsigned char *readp = data->d_buf;
@@ -5411,7 +5416,7 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
+ elf_ndxscn (scn), section_name (ebl, shdr));
return;
}
@@ -5555,13 +5560,14 @@ split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
/* Print content of DWARF .debug_rnglists section. */
static void
print_debug_rnglists_section (Dwfl_Module *dwflmod,
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg __attribute__((unused)))
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
Elf_Data *data =(dbg->sectiondata[IDX_debug_rnglists]
@@ -5586,7 +5592,7 @@ print_debug_rnglists_section (Dwfl_Module *dwflmod,
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
+ elf_ndxscn (scn), section_name (ebl, shdr));
return;
}
@@ -5946,7 +5952,7 @@ print_debug_ranges_section (Dwfl_Module *dwflmod,
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
sort_listptr (&known_rangelistptr, "rangelistptr");
@@ -6603,18 +6609,24 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
ptrdiff_t start = readp - (unsigned char *) data->d_buf;
const unsigned char *const cieend = readp + unit_length;
- if (unlikely (cieend > dataend || readp + 8 > dataend))
+ if (unlikely (cieend > dataend))
goto invalid_data;
Dwarf_Off cie_id;
if (length == 4)
{
+ if (unlikely (cieend - readp < 4))
+ goto invalid_data;
cie_id = read_4ubyte_unaligned_inc (dbg, readp);
if (!is_eh_frame && cie_id == DW_CIE_ID_32)
cie_id = DW_CIE_ID_64;
}
else
- cie_id = read_8ubyte_unaligned_inc (dbg, readp);
+ {
+ if (unlikely (cieend - readp < 8))
+ goto invalid_data;
+ cie_id = read_8ubyte_unaligned_inc (dbg, readp);
+ }
uint_fast8_t version = 2;
unsigned int code_alignment_factor;
@@ -6626,6 +6638,8 @@ print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
{
+ if (unlikely (cieend - readp < 2))
+ goto invalid_data;
version = *readp++;
const char *const augmentation = (const char *) readp;
readp = memchr (readp, '\0', cieend - readp);
@@ -7532,12 +7546,12 @@ attr_callback (Dwarf_Attribute *attrp, void *arg)
static void
print_debug_units (Dwfl_Module *dwflmod,
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg, bool debug_types)
{
const bool silent = !(print_debug_sections & section_info) && !debug_types;
- const char *secname = section_name (ebl, ehdr, shdr);
+ const char *secname = section_name (ebl, shdr);
if (!silent)
printf (gettext ("\
@@ -7834,12 +7848,13 @@ print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
static void
-print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
size_t address_size
@@ -8188,7 +8203,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
if (shdr->sh_size == 0)
@@ -8225,7 +8240,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
+ elf_ndxscn (scn), section_name (ebl, shdr));
return;
}
unit_length = read_8ubyte_unaligned_inc (dbg, linep);
@@ -8352,7 +8367,7 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
error (0, 0,
gettext ("invalid data at offset %tu in section [%zu] '%s'"),
linep - (const unsigned char *) data->d_buf,
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
+ elf_ndxscn (scn), section_name (ebl, shdr));
linep = lineendp;
continue;
}
@@ -8852,13 +8867,14 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
static void
print_debug_loclists_section (Dwfl_Module *dwflmod,
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
Elf_Data *data = (dbg->sectiondata[IDX_debug_loclists]
@@ -8883,7 +8899,7 @@ print_debug_loclists_section (Dwfl_Module *dwflmod,
{
invalid_data:
error (0, 0, gettext ("invalid data in section [%zu] '%s'"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr));
+ elf_ndxscn (scn), section_name (ebl, shdr));
return;
}
@@ -9294,7 +9310,7 @@ print_debug_loc_section (Dwfl_Module *dwflmod,
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
sort_listptr (&known_locsptr, "loclistptr");
@@ -9533,12 +9549,13 @@ mac_compare (const void *p1, const void *p2)
static void
print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
putc_unlocked ('\n', stdout);
@@ -9698,17 +9715,17 @@ print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
static void
print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
putc_unlocked ('\n', stdout);
- Elf_Data *data = (dbg->sectiondata[IDX_debug_macro]
- ?: elf_rawdata (scn, NULL));
+ Elf_Data *data = elf_getdata (scn, NULL);
if (unlikely (data == NULL))
{
error (0, 0, gettext ("cannot get macro information section data: %s"),
@@ -9777,7 +9794,33 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
if (readp + 1 > readendp)
goto invalid_data;
const unsigned char flag = *readp++;
- printf (gettext (" Flag: 0x%" PRIx8 "\n"), flag);
+ printf (gettext (" Flag: 0x%" PRIx8), flag);
+ if (flag != 0)
+ {
+ printf (" (");
+ if ((flag & 0x01) != 0)
+ {
+ printf ("offset_size");
+ if ((flag & 0xFE) != 0)
+ printf (", ");
+ }
+ if ((flag & 0x02) != 0)
+ {
+ printf ("debug_line_offset");
+ if ((flag & 0xFC) != 0)
+ printf (", ");
+ }
+ if ((flag & 0x04) != 0)
+ {
+ printf ("operands_table");
+ if ((flag & 0xF8) != 0)
+ printf (", ");
+ }
+ if ((flag & 0xF8) != 0)
+ printf ("unknown");
+ printf (")");
+ }
+ printf ("\n");
unsigned int offset_len = (flag & 0x01) ? 8 : 4;
printf (gettext (" Offset length: %" PRIu8 "\n"), offset_len);
@@ -10059,11 +10102,12 @@ print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
/* Print the known exported symbols in the DWARF section '.debug_pubnames'. */
static void
print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
int n = 0;
@@ -10073,7 +10117,8 @@ print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
/* Print the content of the DWARF string section '.debug_str'. */
static void
print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr,
Dwarf *dbg __attribute__ ((unused)))
{
@@ -10093,7 +10138,7 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
printf (gettext ("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
" %*s String\n"),
elf_ndxscn (scn),
- section_name (ebl, ehdr, shdr), (uint64_t) shdr->sh_offset,
+ section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
/* TRANS: the debugstr| prefix makes the string unique. */
digits + 2, sgettext ("debugstr|Offset"));
@@ -10117,12 +10162,13 @@ print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
static void
print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
- Ebl *ebl, GElf_Ehdr *ehdr,
+ Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\
\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset);
if (shdr->sh_size == 0)
@@ -10586,12 +10632,13 @@ print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
*/
static void
-print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
+ GElf_Ehdr *ehdr __attribute__ ((unused)),
Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
{
printf (gettext ("\nGDB section [%2zu] '%s' at offset %#" PRIx64
" contains %" PRId64 " bytes :\n"),
- elf_ndxscn (scn), section_name (ebl, ehdr, shdr),
+ elf_ndxscn (scn), section_name (ebl, shdr),
(uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
Elf_Data *data = elf_rawdata (scn, NULL);
@@ -12150,14 +12197,26 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
const char *desc = data->d_buf + desc_offset;
+ /* GNU Build Attributes are weird, they store most of their data
+ into the owner name field. Extract just the owner name
+ prefix here, then use the rest later as data. */
+ bool is_gnu_build_attr
+ = strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
+ strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0;
+ const char *print_name = (is_gnu_build_attr
+ ? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
+ size_t print_namesz = (is_gnu_build_attr
+ ? strlen (print_name) : nhdr.n_namesz);
+
char buf[100];
char buf2[100];
printf (gettext (" %-13.*s %9" PRId32 " %s\n"),
- (int) nhdr.n_namesz, name, nhdr.n_descsz,
+ (int) print_namesz, print_name, nhdr.n_descsz,
ehdr->e_type == ET_CORE
? ebl_core_note_type_name (ebl, nhdr.n_type,
buf, sizeof (buf))
: ebl_object_note_type_name (ebl, name, nhdr.n_type,
+ nhdr.n_descsz,
buf2, sizeof (buf2)));
/* Filter out invalid entries. */
@@ -12193,7 +12252,8 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
handle_core_note (ebl, &nhdr, name, desc);
}
else
- ebl_object_note (ebl, name, nhdr.n_type, nhdr.n_descsz, desc);
+ ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
+ nhdr.n_descsz, desc);
}
}
@@ -12259,7 +12319,8 @@ handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
handle_notes_data (ebl, ehdr, phdr->p_offset,
elf_getdata_rawchunk (ebl->elf,
phdr->p_offset, phdr->p_filesz,
- ELF_T_NHDR));
+ (phdr->p_align == 8
+ ? ELF_T_NHDR8 : ELF_T_NHDR)));
}
}