Hi, On Thu, 2013-03-21 at 17:09 +0100, Mark Wielaard wrote: > The above seems to be "correct" according to the DWARF spec. You have to > skip till the next table based on table header length field. But on the > buggy (?) .debug_aranges I am looking at not skipping the padding is the > right thing. This is also what dwarf_getaranges does. So maybe that is > correct? But it also isn't what binutils readelf and dwz seem to do... > > I'll try to figure out what is going on.
Found it. It was a bug in GCC: http://gcc.gnu.org/ml/gcc-patches/2013-03/msg00827.html Based on that I kept the code as it is and removed the comment. I am undecided whether to "fix" the dwarf_getaranges code to do the same (in normal cases the length and terminator for the table match up, so it shouldn't matter). I still like to add this "raw" .debug_aranges reader in readelf because I think it is useful to have. Using dwarf_getaranges does too much (especially the sorting of addresses). Cheers, Mark
commit ab51506feab195ac9e668356332d7fbf859bfa7d Author: Mark Wielaard <[email protected]> Date: Thu Mar 21 11:04:53 2013 +0100 readelf: Display raw .debug_aranges. Don't use libdw dwarf_getaranges. Signed-off-by: Mark Wielaard <[email protected]> diff --git a/src/ChangeLog b/src/ChangeLog index a641d33..2588c9e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2013-03-21 Mark Wielaard <[email protected]> + + * readelf.c (print_debug_aranges_section): Reimplement. + 2013-03-19 Mark Wielaard <[email protected]> * readelf.c (print_gdb_index_section): Free format_dwarf_addr results. diff --git a/src/readelf.c b/src/readelf.c index 1412bed..dfe2a6e 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -4326,61 +4326,155 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } -/* Print content of DWARF .debug_aranges section. We fortunately do - not have to know a bit about the structure of the section, libdwarf - takes care of it. */ +/* Print content of DWARF .debug_aranges section. */ static void print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { - Dwarf_Aranges *aranges; - size_t cnt; - if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0)) + Elf_Data *data = elf_rawdata (scn, NULL); + + if (unlikely (data == NULL)) { error (0, 0, gettext ("cannot get .debug_aranges content: %s"), - dwarf_errmsg (-1)); + elf_errmsg (-1)); return; } - printf (ngettext ("\ -\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n", - "\ -\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n", - cnt), + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), elf_ndxscn (scn), section_name (ebl, ehdr, shdr), - (uint64_t) shdr->sh_offset, cnt); + (uint64_t) shdr->sh_offset); - /* Compute floor(log16(cnt)). */ - size_t tmp = cnt; - int digits = 1; - while (tmp >= 16) - { - ++digits; - tmp >>= 4; - } + const unsigned char *readp = data->d_buf; + const unsigned char *readendp = readp + data->d_size; - for (size_t n = 0; n < cnt; ++n) + while (readp < readendp) { - Dwarf_Arange *runp = dwarf_onearange (aranges, n); - if (unlikely (runp == NULL)) + const unsigned char *hdrstart = readp; + size_t start_offset = hdrstart - (const unsigned char *) data->d_buf; + + printf (gettext ("\nTable at offset %Zu:\n"), start_offset); + if (readp + 4 > readendp) { - printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1)); + invalid_data: + error (0, 0, gettext ("invalid data in section [%zu] '%s'"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr)); return; } - Dwarf_Addr start; - Dwarf_Word length; - Dwarf_Off offset; + Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp); + unsigned int length_bytes = 4; + if (length == DWARF3_LENGTH_64_BIT) + { + if (readp + 8 > readendp) + goto invalid_data; + length = read_8ubyte_unaligned_inc (dbg, readp); + length_bytes = 8; + } + + const unsigned char *nexthdr = readp + length; + printf (gettext ("\n Length: %6" PRIu64 "\n"), + (uint64_t) length); + + if (nexthdr > readendp) + goto invalid_data; + + if (length == 0) + continue; + + if (readp + 2 > readendp) + goto invalid_data; + uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp); + printf (gettext (" DWARF version: %6" PRIuFAST16 "\n"), + version); + if (version != 2) + { + error (0, 0, gettext ("unsupported aranges version")); + goto next_table; + } - if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0)) - printf (gettext (" [%*zu] ???\n"), digits, n); + Dwarf_Word offset; + if (readp + length_bytes > readendp) + goto invalid_data; + if (length_bytes == 8) + offset = read_8ubyte_unaligned_inc (dbg, readp); else - printf (gettext (" [%*zu] start: %0#*" PRIx64 - ", length: %5" PRIu64 ", CU DIE offset: %6" - PRId64 "\n"), - digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18, - (uint64_t) start, (uint64_t) length, (int64_t) offset); + offset = read_4ubyte_unaligned_inc (dbg, readp); + printf (gettext (" CU offset: %6" PRIx64 "\n"), + (uint64_t) offset); + + if (readp + 1 > readendp) + goto invalid_data; + unsigned int address_size = *readp++; + printf (gettext (" Address size: %6" PRIu64 "\n"), + (uint64_t) address_size); + if (address_size != 4 && address_size != 8) + { + error (0, 0, gettext ("unsupported address size")); + goto next_table; + } + + unsigned int segment_size = *readp++; + printf (gettext (" Segment size: %6" PRIu64 "\n\n"), + (uint64_t) segment_size); + if (segment_size != 0 && segment_size != 4 && segment_size != 8) + { + error (0, 0, gettext ("unsupported segment size")); + goto next_table; + } + + /* Round the address to the next multiple of 2*address_size. */ + readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size))) + % (2 * address_size)); + + while (readp < nexthdr) + { + Dwarf_Word range_address; + Dwarf_Word range_length; + Dwarf_Word segment = 0; + if (readp + 2 * address_size + segment_size > readendp) + goto invalid_data; + if (address_size == 4) + { + range_address = read_4ubyte_unaligned_inc (dbg, readp); + range_length = read_4ubyte_unaligned_inc (dbg, readp); + } + else + { + range_address = read_8ubyte_unaligned_inc (dbg, readp); + range_length = read_8ubyte_unaligned_inc (dbg, readp); + } + + if (segment_size == 4) + segment = read_4ubyte_unaligned_inc (dbg, readp); + else if (segment_size == 8) + segment = read_8ubyte_unaligned_inc (dbg, readp); + + if (range_address == 0 && range_length == 0 && segment == 0) + break; + + char *b = format_dwarf_addr (dwflmod, address_size, range_address, + range_address); + char *e = format_dwarf_addr (dwflmod, address_size, + range_address + range_length - 1, + range_length); + if (segment_size != 0) + printf (gettext (" %s..%s (%" PRIx64 ")\n"), b, e, + (uint64_t) segment); + else + printf (gettext (" %s..%s\n"), b, e); + free (b); + free (e); + } + + next_table: + if (readp != nexthdr) + { + size_t padding = nexthdr - readp; + printf (gettext (" %Zu padding bytes\n"), padding); + readp = nexthdr; + } } }
_______________________________________________ elfutils-devel mailing list [email protected] https://lists.fedorahosted.org/mailman/listinfo/elfutils-devel
