diff options
Diffstat (limited to 'src/readelf.c')
-rw-r--r-- | src/readelf.c | 153 |
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))); } } |