Hi,
I was chasing a anomaly with .debug_aranges and found the eu-readelf --debug-dump=aranges output not very helpful. It uses libdw dwarf_getaranges which hides lots of details and sorts the addresses. Not helpful if you are trying to see why something might be wrong. binutils readelf also wasn't a big help because it errored out before displaying anything. So I implemented a "raw" .debug_aranges for eu-readelf. The output is as follows:
Table at offset 560:
Length: 60 DWARF version: 2 CU offset: 2bb78 Address size: 8 Segment size: 0
0x000000000043c3c0 <expr_unwind>..0x000000000043e0b1 <evalexp+0xe1> 0x000000000041bba4 <_is_arithop>..0x000000000041bbee <_is_arithop+0x4a>
This did allow me to find what the issue was. But I am not sure yet what the root cause is. The following comment in the new code summarizes what is happening:
+ next_table: + if (readp != nexthdr) + { + size_t padding = nexthdr - readp; + printf (gettext (" %Zu padding bytes\n"), padding); + // To skip, or not to skip, that is the question... + // dwarf_getaranges doesn't skip, it assumes that after + // seeing the terminator sequence there must be another + // table and ignores the length field. Strangely enough + // that seems to be the right thing sometimes... + readp = nexthdr; + }
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. Meanwhile comments on the code welcome.
Thanks,
Mark
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
Mark Wielaard mjw@redhat.com writes:
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).
Elfutils already implements some byte-reading in cases where our Dwarf interfaces are too high-level, so this is in line with that.
BTW, dwarflint already contains much of this low-level stuff, and if we ever revive it, there might be an opportunity for sharing some of that code.
Thanks, PM
On Fri, Mar 22, 2013 at 03:20:51PM +0100, Petr Machata wrote:
Elfutils already implements some byte-reading in cases where our Dwarf interfaces are too high-level, so this is in line with that.
BTW, dwarflint already contains much of this low-level stuff, and if we ever revive it, there might be an opportunity for sharing some of that code.
Yes, that was my thinking too. I am mostly using eu-readelf as an way to see the raw-DWARF without interpreting its meaning. The only difference with a low-level structural DWARF-lint tool would be that I think readelf can be a little linient and doesn't have to warn or error out on suspicious looking DWARF.
Cheers,
Mark
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'm not really clear on what change you are considering.
Looking at the (v4) spec there is no real indication why it has both length and terminator. The length in the header is the form common to all the sections, which has the feature that you can decode just the header to skip to the next set without decoding this one. A consumer that wanted to be lazy could process only the sets for particular CUs of interest. But I can't really see a reason why any consumer would want to examine .debug_aranges at all when it already had particular CUs in mind. Regardless, I don't see anything in the spec that would suggest it's permissible for there to be any bytes after a terminator entry in the range indicated by the length field.
On Fri, Mar 22, 2013 at 01:55:58PM -0700, Roland McGrath wrote:
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'm not really clear on what change you are considering.
[...] Regardless, I don't see anything in the spec that would suggest it's permissible for there to be any bytes after a terminator entry in the range indicated by the length field.
Right. I won't change a thing for dwarf_getaranges then.
Thanks,
Mark
I think it's a sound plan to have an independent raw-data decoder in readelf. It's not clear to me from what you showed whether the output text formatting looks different from the old one (aside from contents differing by being unsorted). If it looks a lot different, then perhaps it should be a separate option --debug-info=rawaranges (akin to binutils readelf's line vs decodedline). But OTOH perhaps nobody ever looks at the existing dumps at all, so just changing the meaning of --debug-info=aranges is fine. I'm just not really sure.
On Fri, Mar 22, 2013 at 01:41:42PM -0700, Roland McGrath wrote:
I think it's a sound plan to have an independent raw-data decoder in readelf. It's not clear to me from what you showed whether the output text formatting looks different from the old one (aside from contents differing by being unsorted). If it looks a lot different, then perhaps it should be a separate option --debug-info=rawaranges (akin to binutils readelf's line vs decodedline). But OTOH perhaps nobody ever looks at the existing dumps at all, so just changing the meaning of --debug-info=aranges is fine. I'm just not really sure.
O, --debug-dump=decodedline is nice. I like to have that for eu-readelf too. Would be really useful in a case I was just looking at where the "raw" .debug_line encoding is really odd/slightly bogus.
I don't think anybody was using the old --debug-dump=aranges output. We also didn't have any tests relying on its output. I am not sure the decoded version is that useful, but we could resurrect it as --debug-dump=decodedaranges. If only so one can see what libdw would make of the raw input.
So --debug-dump=aranges will give the raw output:
DWARF section [27] '.debug_aranges' at offset 0x1044:
Table at offset 0:
Length: 28 DWARF version: 2 CU offset: 0 Address size: 4 Segment size: 0
0x080482f0 <main>..0x08048323 <main+0x33>
Table at offset 32:
Length: 36 DWARF version: 2 CU offset: 136 Address size: 4 Segment size: 0
0x08048440 <bar>..0x08048451 <bar+0x11> 0x08048330 <nobar>..0x0804833a <nobar+0xa>
Table at offset 72:
Length: 36 DWARF version: 2 CU offset: 1d1 Address size: 4 Segment size: 0
0x08048460 <baz>..0x080484bb <baz+0x5b> 0x08048340 <nobaz>..0x0804834a <nobaz+0xa>
And --debug-dump=decodedaranges will give what we used to give:
DWARF section [27] '.debug_aranges' at offset 0x1044 contains 5 entries: [0] start: 0x080482f0, length: 52, CU DIE offset: 11 [1] start: 0x08048330, length: 11, CU DIE offset: 321 [2] start: 0x08048340, length: 11, CU DIE offset: 476 [3] start: 0x08048440, length: 18, CU DIE offset: 321 [4] start: 0x08048460, length: 92, CU DIE offset: 476
So you get a sorted list of addresses instead of addresses grouped per CU, and DIE offsets instead of CU offsets.
I'll also implement --debug-dump=decodedline.
Cheers,
Mark
Display "raw" .debug_aranges by default. Only use libdw parsing when --debug-dump=decodedaranges is given.
Signed-off-by: Mark Wielaard mjw@redhat.com --- src/ChangeLog | 9 +++ src/readelf.c | 177 +++++++++++++++++++++++++++++++++++++++++-- tests/ChangeLog | 7 ++ tests/Makefile.am | 2 + tests/run-readelf-aranges.sh | 161 +++++++++++++++++++++++++++++++++++++++ tests/testfilefoobarbaz.bz2 | Bin 0 -> 3974 bytes 6 files changed, 351 insertions(+), 5 deletions(-) create mode 100755 tests/run-readelf-aranges.sh create mode 100755 tests/testfilefoobarbaz.bz2
diff --git a/src/ChangeLog b/src/ChangeLog index a641d33..f4ab342 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2013-03-25 Mark Wielaard mjw@redhat.com + + * readelf.c (argp_option): Add decodedaranges. + (decodedaranges): New boolean initialized to false. + (parse_opt): Set decodedaranges when arg is decodedaranges. + (print_debug_aranges_section): Reimplemented and original + implementation renamed to... + (print_decoded_aranges_section): this. + 2013-03-19 Mark Wielaard mjw@redhat.com
* readelf.c (print_gdb_index_section): Free format_dwarf_addr results. diff --git a/src/readelf.c b/src/readelf.c index 1412bed..032f152 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -94,8 +94,8 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 }, { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, N_("Display DWARF section content. SECTION can be one of abbrev, " - "aranges, frame, gdb_index, info, loc, line, ranges, pubnames, str, " - "macinfo, macro or exception"), 0 }, + "aranges, decodedaranges, frame, gdb_index, info, loc, line, ranges, " + "pubnames, str, macinfo, macro or exception"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, @@ -183,6 +183,9 @@ static bool print_address_names = true; /* True if we should print raw values instead of relativized addresses. */ static bool print_unresolved_addresses = false;
+/* True if we should print the .debug_aranges section using libdw. */ +static bool decodedaranges = false; + /* Select printing of debugging sections. */ static enum section_e { @@ -391,6 +394,11 @@ parse_opt (int key, char *arg, print_debug_sections |= section_abbrev; else if (strcmp (arg, "aranges") == 0) print_debug_sections |= section_aranges; + else if (strcmp (arg, "decodedaranges") == 0) + { + print_debug_sections |= section_aranges; + decodedaranges = true; + } else if (strcmp (arg, "ranges") == 0) { print_debug_sections |= section_ranges; @@ -4330,9 +4338,8 @@ print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)), not have to know a bit about the structure of the section, libdwarf takes care of it. */ static void -print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), - Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, - GElf_Shdr *shdr, Dwarf *dbg) +print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, + GElf_Shdr *shdr, Dwarf *dbg) { Dwarf_Aranges *aranges; size_t cnt; @@ -4384,6 +4391,166 @@ print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)), } }
+ +/* 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) +{ + if (decodedaranges) + { + print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg); + return; + } + + Elf_Data *data = elf_rawdata (scn, NULL); + + if (unlikely (data == NULL)) + { + error (0, 0, gettext ("cannot get .debug_aranges content: %s"), + elf_errmsg (-1)); + return; + } + + printf (gettext ("\ +\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr), + (uint64_t) shdr->sh_offset); + + const unsigned char *readp = data->d_buf; + const unsigned char *readendp = readp + data->d_size; + + while (readp < readendp) + { + 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) + { + invalid_data: + error (0, 0, gettext ("invalid data in section [%zu] '%s'"), + elf_ndxscn (scn), section_name (ebl, ehdr, shdr)); + return; + } + + 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; + } + + Dwarf_Word offset; + if (readp + length_bytes > readendp) + goto invalid_data; + if (length_bytes == 8) + offset = read_8ubyte_unaligned_inc (dbg, readp); + else + 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; + } + } +} + + /* Print content of DWARF .debug_ranges section. */ static void print_debug_ranges_section (Dwfl_Module *dwflmod, diff --git a/tests/ChangeLog b/tests/ChangeLog index 62b589d..fa98f98 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,10 @@ +2013-03-25 Mark Wielaard mjw@redhat.com + + * run-readelf-aranges.sh: New test. + * testfilefoobarbaz.bz2: New test file. + * Makefile.am (TESTS): Add run-readelf-aranges.sh. + (EXTRA_DIST): Add run-readelf-aranges.sh and testfilefoobarbaz.bz2. + 2013-03-20 Jan Kratochvil jan.kratochvil@redhat.com
* Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align. diff --git a/tests/Makefile.am b/tests/Makefile.am index 9b0bbf1..4e63039 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -75,6 +75,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \ run-readelf-test4.sh run-readelf-twofiles.sh \ run-readelf-macro.sh run-readelf-loc.sh \ + run-readelf-aranges.sh \ run-native-test.sh run-bug1-test.sh \ dwfl-bug-addr-overflow run-addrname-test.sh \ dwfl-bug-fd-leak dwfl-bug-report \ @@ -157,6 +158,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile49.bz2 testfile50.bz2 testfile51.bz2 \ run-readelf-macro.sh testfilemacro.bz2 \ run-readelf-loc.sh testfileloc.bz2 \ + run-readelf-aranges.sh testfilefoobarbaz.bz2 \ run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \ testfile_multi.dwz.bz2 testfile_multi_main.bz2 \ testfile-dwzstr.bz2 testfile-dwzstr.multi.bz2 \ diff --git a/tests/run-readelf-aranges.sh b/tests/run-readelf-aranges.sh new file mode 100755 index 0000000..a610fca --- /dev/null +++ b/tests/run-readelf-aranges.sh @@ -0,0 +1,161 @@ +#! /bin/sh +# Copyright (C) 2013 Red Hat, Inc. +# This file is part of elfutils. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +. $srcdir/test-subr.sh + +# Tests readelf --debug-dump=aranges and --debug-dump=decodedaranges +# +# - foobarbaz.h +# +# int bar (); +# int baz (int i); +# +# - bar.c +# +# #include "foobarbaz.h" +# +# static int bi; +# +# static int +# barbaz (int i) +# { +# return i * 2 - 1; +# } +# +# __attribute__ ((constructor)) void +# nobar () +# { +# bi = 1; +# } +# +# int +# bar () +# { +# bi++; +# return barbaz (bi); +# } +# +# - foo.c +# +# include "foobarbaz.h" +# +# static int fi = 0; +# +# static int +# foo (int i, int j) +# { +# if (i > j) +# return i - j + fi; +# else +# return (2 * j) - i + fi; +# } +# +# int +# main (int argc, char **argv) +# { +# int a = bar (); +# int b = baz (a + argc); +# int r = foo (a, b) - 1; +# +# return r - 48; +# } +# +# - baz.c +# include "foobarbaz.h" +# +# static int bj; +# +# static int +# bazbaz (int j) +# { +# return bj * j - bar (); +# } +# +# __attribute__ ((constructor)) void +# nobaz () +# { +# bj = 1; +# } +# +# int +# baz (int i) +# { +# if (i < 0) +# return bazbaz (i); +# else +# { +# while (i-- > 0) +# bj += bar (); +# } +# return bazbaz (i); +# } +# +# gcc -g -O2 -m32 -c baz.c +# gcc -g -O2 -m32 -c bar.c +# gcc -g -O2 -m32 -c foo.c +# gcc -g -O2 -m32 -o testfilefoobarbaz foo.o bar.o baz.o + +testfiles testfilefoobarbaz + +testrun_compare ../src/readelf --debug-dump=aranges testfilefoobarbaz <<EOF + +DWARF section [27] '.debug_aranges' at offset 0x1044: + +Table at offset 0: + + Length: 28 + DWARF version: 2 + CU offset: 0 + Address size: 4 + Segment size: 0 + + 0x080482f0 <main>..0x08048323 <main+0x33> + +Table at offset 32: + + Length: 36 + DWARF version: 2 + CU offset: 136 + Address size: 4 + Segment size: 0 + + 0x08048440 <bar>..0x08048451 <bar+0x11> + 0x08048330 <nobar>..0x0804833a <nobar+0xa> + +Table at offset 72: + + Length: 36 + DWARF version: 2 + CU offset: 1d1 + Address size: 4 + Segment size: 0 + + 0x08048460 <baz>..0x080484bb <baz+0x5b> + 0x08048340 <nobaz>..0x0804834a <nobaz+0xa> +EOF + +testrun_compare ../src/readelf --debug-dump=decodedaranges testfilefoobarbaz <<\EOF + +DWARF section [27] '.debug_aranges' at offset 0x1044 contains 5 entries: + [0] start: 0x080482f0, length: 52, CU DIE offset: 11 + [1] start: 0x08048330, length: 11, CU DIE offset: 321 + [2] start: 0x08048340, length: 11, CU DIE offset: 476 + [3] start: 0x08048440, length: 18, CU DIE offset: 321 + [4] start: 0x08048460, length: 92, CU DIE offset: 476 +EOF + +exit 0 diff --git a/tests/testfilefoobarbaz.bz2 b/tests/testfilefoobarbaz.bz2 new file mode 100755 index 0000000000000000000000000000000000000000..0e721ffe6f55010f1527bda088b4d579280d67b5 GIT binary patch literal 3974 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
literal 0 HcmV?d00001
Use libdw to decode the .debug_line section and print address table view when --debug-dump=decodedline is given.
Signed-off-by: Mark Wielaard mjw@redhat.com --- src/ChangeLog | 9 ++ src/readelf.c | 98 +++++++++++++++++- tests/Makefile.am | 4 +- tests/run-readelf-line.sh | 259 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 366 insertions(+), 4 deletions(-) create mode 100755 tests/run-readelf-line.sh
diff --git a/src/ChangeLog b/src/ChangeLog index f4ab342..625bbdb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,14 @@ 2013-03-25 Mark Wielaard mjw@redhat.com
+ * readelf.c (argp_options): Add decodedline. + (decodedline): New boolean initialized to false. + (parse_opt): Set decodedline when arg is decodedline. + (print_decoded_line_section): New function. + (print_debug_line_section): Call print_decoded_line_section when + decodedline is true. + +2013-03-25 Mark Wielaard mjw@redhat.com + * readelf.c (argp_option): Add decodedaranges. (decodedaranges): New boolean initialized to false. (parse_opt): Set decodedaranges when arg is decodedaranges. diff --git a/src/readelf.c b/src/readelf.c index 032f152..80bc215 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -94,8 +94,8 @@ static const struct argp_option options[] = { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 }, { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL, N_("Display DWARF section content. SECTION can be one of abbrev, " - "aranges, decodedaranges, frame, gdb_index, info, loc, line, ranges, " - "pubnames, str, macinfo, macro or exception"), 0 }, + "aranges, decodedaranges, frame, gdb_index, info, loc, line, " + "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 }, { "hex-dump", 'x', "SECTION", 0, N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 }, { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL, @@ -186,6 +186,9 @@ static bool print_unresolved_addresses = false; /* True if we should print the .debug_aranges section using libdw. */ static bool decodedaranges = false;
+/* True if we should print the .debug_aranges section using libdw. */ +static bool decodedline = false; + /* Select printing of debugging sections. */ static enum section_e { @@ -415,6 +418,11 @@ parse_opt (int key, char *arg, } else if (strcmp (arg, "line") == 0) print_debug_sections |= section_line; + else if (strcmp (arg, "decodedline") == 0) + { + print_debug_sections |= section_line; + decodedline = true; + } else if (strcmp (arg, "pubnames") == 0) print_debug_sections |= section_pubnames; else if (strcmp (arg, "str") == 0) @@ -5885,9 +5893,95 @@ 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, + 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), + (uint64_t) shdr->sh_offset); + + size_t address_size + = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8; + + Dwarf_Off cuoffset; + Dwarf_Off ncuoffset = 0; + size_t hsize; + while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize, + NULL, NULL, NULL) == 0) + { + Dwarf_Die cudie; + if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL) + continue; + + size_t nlines; + Dwarf_Lines *lines; + if (dwarf_getsrclines (&cudie, &lines, &nlines) != 0) + continue; + + printf (" CU [%" PRIx64 "] %s\n", + dwarf_dieoffset (&cudie), dwarf_diename (&cudie)); + printf (" line:col SBPE* disc isa op address" + " (Statement Block Prologue Epilogue *End)\n"); + const char *last_file = ""; + for (size_t n = 0; n < nlines; n++) + { + Dwarf_Line *line = dwarf_onesrcline (lines, n); + Dwarf_Word mtime, length; + const char *file = dwarf_linesrc (line, &mtime, &length); + if (strcmp (last_file, file) != 0) + { + printf (" %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n", + file, mtime, length); + last_file = file; + } + + int lineno, colno; + bool statement, endseq, block, prologue_end, epilogue_begin; + unsigned int lineop, isa, disc; + Dwarf_Addr address; + dwarf_lineaddr (line, &address); + dwarf_lineno (line, &lineno); + dwarf_linecol (line, &colno); + dwarf_lineop_index (line, &lineop); + dwarf_linebeginstatement (line, &statement); + dwarf_lineendsequence (line, &endseq); + dwarf_lineblock (line, &block); + dwarf_lineprologueend (line, &prologue_end); + dwarf_lineepiloguebegin (line, &epilogue_begin); + dwarf_lineisa (line, &isa); + dwarf_linediscriminator (line, &disc); + + /* End sequence is special, it is one byte past. */ + char *a = format_dwarf_addr (dwflmod, address_size, + address - (endseq ? 1 : 0), address); + printf (" %4d:%-3d %c%c%c%c%c %4d %3d %2d %s\n", + lineno, colno, + (statement ? 'S' : ' '), + (block ? 'B' : ' '), + (prologue_end ? 'P' : ' '), + (epilogue_begin ? 'E' : ' '), + (endseq ? '*' : ' '), + disc, isa, lineop, a); + free (a); + + if (endseq) + printf("\n"); + } + } +} + + +static void print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) { + if (decodedline) + { + print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg); + return; + } + printf (gettext ("\ \nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"), elf_ndxscn (scn), section_name (ebl, ehdr, shdr), diff --git a/tests/Makefile.am b/tests/Makefile.am index 4e63039..85ed678 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -75,7 +75,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \ run-readelf-test4.sh run-readelf-twofiles.sh \ run-readelf-macro.sh run-readelf-loc.sh \ - run-readelf-aranges.sh \ + run-readelf-aranges.sh run-readelf-line.sh \ run-native-test.sh run-bug1-test.sh \ dwfl-bug-addr-overflow run-addrname-test.sh \ dwfl-bug-fd-leak dwfl-bug-report \ @@ -158,7 +158,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile49.bz2 testfile50.bz2 testfile51.bz2 \ run-readelf-macro.sh testfilemacro.bz2 \ run-readelf-loc.sh testfileloc.bz2 \ - run-readelf-aranges.sh testfilefoobarbaz.bz2 \ + run-readelf-aranges.sh run-readelf-line.sh testfilefoobarbaz.bz2 \ run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \ testfile_multi.dwz.bz2 testfile_multi_main.bz2 \ testfile-dwzstr.bz2 testfile-dwzstr.multi.bz2 \ diff --git a/tests/run-readelf-line.sh b/tests/run-readelf-line.sh new file mode 100755 index 0000000..f0e491d --- /dev/null +++ b/tests/run-readelf-line.sh @@ -0,0 +1,259 @@ +#! /bin/sh +# Copyright (C) 2013 Red Hat, Inc. +# This file is part of elfutils. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# elfutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. + +. $srcdir/test-subr.sh + +# Tests readelf --debug-dump=line and --debug-dump=decodedline +# See run-readelf-aranges for testfiles. + +testfiles testfilefoobarbaz + +testrun_compare ../src/readelf --debug-dump=line testfilefoobarbaz <<EOF + +DWARF section [30] '.debug_line' at offset 0x15f6: + +Table at offset 0: + + Length: 83 + DWARF version: 2 + Prologue length: 43 + Minimum instruction length: 1 + Maximum operations per instruction: 1 + Initial value if 'is_stmt': 1 + Line base: -5 + Line range: 14 + Opcode base: 13 + +Opcodes: + [ 1] 0 arguments + [ 2] 1 argument + [ 3] 1 argument + [ 4] 1 argument + [ 5] 1 argument + [ 6] 0 arguments + [ 7] 0 arguments + [ 8] 0 arguments + [ 9] 1 argument + [10] 0 arguments + [11] 0 arguments + [12] 1 argument + +Directory table: + +File name table: + Entry Dir Time Size Name + 1 0 0 0 foo.c + 2 0 0 0 foobarbaz.h + +Line number statements: + [ 35] extended opcode 2: set address to 0x80482f0 <main> + [ 3c] advance line by constant 15 to 16 + [ 3e] copy + [ 3f] special opcode 159: address+10 = 0x80482fa <main+0xa>, line+1 = 17 + [ 40] special opcode 117: address+7 = 0x8048301 <main+0x11>, line+1 = 18 + [ 41] advance line by constant -9 to 9 + [ 43] special opcode 200: address+13 = 0x804830e <main+0x1e>, line+0 = 9 + [ 44] special opcode 48: address+2 = 0x8048310 <main+0x20>, line+2 = 11 + [ 45] special opcode 58: address+3 = 0x8048313 <main+0x23>, line-2 = 9 + [ 46] special opcode 48: address+2 = 0x8048315 <main+0x25>, line+2 = 11 + [ 47] special opcode 44: address+2 = 0x8048317 <main+0x27>, line-2 = 9 + [ 48] advance line by constant 13 to 22 + [ 4a] special opcode 46: address+2 = 0x8048319 <main+0x29>, line+0 = 22 + [ 4b] advance line by constant -13 to 9 + [ 4d] special opcode 60: address+3 = 0x804831c <main+0x2c>, line+0 = 9 + [ 4e] advance line by constant 12 to 21 + [ 50] special opcode 60: address+3 = 0x804831f <main+0x2f>, line+0 = 21 + [ 51] special opcode 61: address+3 = 0x8048322 <main+0x32>, line+1 = 22 + [ 52] advance address by 2 to 0x8048324 + [ 54] extended opcode 1: end of sequence + +Table at offset 87: + + Length: 72 + DWARF version: 2 + Prologue length: 28 + Minimum instruction length: 1 + Maximum operations per instruction: 1 + Initial value if 'is_stmt': 1 + Line base: -5 + Line range: 14 + Opcode base: 13 + +Opcodes: + [ 1] 0 arguments + [ 2] 1 argument + [ 3] 1 argument + [ 4] 1 argument + [ 5] 1 argument + [ 6] 0 arguments + [ 7] 0 arguments + [ 8] 0 arguments + [ 9] 1 argument + [10] 0 arguments + [11] 0 arguments + [12] 1 argument + +Directory table: + +File name table: + Entry Dir Time Size Name + 1 0 0 0 bar.c + +Line number statements: + [ 7d] extended opcode 2: set address to 0x8048330 <nobar> + [ 84] advance line by constant 12 to 13 + [ 86] copy + [ 87] special opcode 19: address+0 = 0x8048330 <nobar>, line+1 = 14 + [ 88] advance address by 11 to 0x804833b + [ 8a] extended opcode 1: end of sequence + [ 8d] extended opcode 2: set address to 0x8048440 <bar> + [ 94] advance line by constant 18 to 19 + [ 96] copy + [ 97] special opcode 19: address+0 = 0x8048440 <bar>, line+1 = 20 + [ 98] advance line by constant -12 to 8 + [ 9a] special opcode 200: address+13 = 0x804844d <bar+0xd>, line+0 = 8 + [ 9b] advance line by constant 14 to 22 + [ 9d] special opcode 74: address+4 = 0x8048451 <bar+0x11>, line+0 = 22 + [ 9e] advance address by 1 to 0x8048452 + [ a0] extended opcode 1: end of sequence + +Table at offset 163: + + Length: 106 + DWARF version: 2 + Prologue length: 43 + Minimum instruction length: 1 + Maximum operations per instruction: 1 + Initial value if 'is_stmt': 1 + Line base: -5 + Line range: 14 + Opcode base: 13 + +Opcodes: + [ 1] 0 arguments + [ 2] 1 argument + [ 3] 1 argument + [ 4] 1 argument + [ 5] 1 argument + [ 6] 0 arguments + [ 7] 0 arguments + [ 8] 0 arguments + [ 9] 1 argument + [10] 0 arguments + [11] 0 arguments + [12] 1 argument + +Directory table: + +File name table: + Entry Dir Time Size Name + 1 0 0 0 baz.c + 2 0 0 0 foobarbaz.h + +Line number statements: + [ d8] extended opcode 2: set address to 0x8048340 <nobaz> + [ df] advance line by constant 12 to 13 + [ e1] copy + [ e2] special opcode 19: address+0 = 0x8048340 <nobaz>, line+1 = 14 + [ e3] advance address by 11 to 0x804834b + [ e5] extended opcode 1: end of sequence + [ e8] extended opcode 2: set address to 0x8048460 <baz> + [ ef] advance line by constant 18 to 19 + [ f1] copy + [ f2] special opcode 74: address+4 = 0x8048464 <baz+0x4>, line+0 = 19 + [ f3] special opcode 75: address+4 = 0x8048468 <baz+0x8>, line+1 = 20 + [ f4] extended opcode 4: set discriminator to 1 + [ f8] special opcode 78: address+4 = 0x804846c <baz+0xc>, line+4 = 24 + [ f9] special opcode 187: address+12 = 0x8048478 <baz+0x18>, line+1 = 25 + [ fa] special opcode 87: address+5 = 0x804847d <baz+0x1d>, line-1 = 24 + [ fb] special opcode 61: address+3 = 0x8048480 <baz+0x20>, line+1 = 25 + [ fc] special opcode 101: address+6 = 0x8048486 <baz+0x26>, line-1 = 24 + [ fd] special opcode 61: address+3 = 0x8048489 <baz+0x29>, line+1 = 25 + [ fe] special opcode 87: address+5 = 0x804848e <baz+0x2e>, line-1 = 24 + [ ff] advance line by constant -16 to 8 + [ 101] special opcode 46: address+2 = 0x8048490 <baz+0x30>, line+0 = 8 + [ 102] advance line by constant 20 to 28 + [ 104] special opcode 186: address+12 = 0x804849c <baz+0x3c>, line+0 = 28 + [ 105] advance line by constant -20 to 8 + [ 107] special opcode 88: address+5 = 0x80484a1 <baz+0x41>, line+0 = 8 + [ 108] advance line by constant 13 to 21 + [ 10a] advance address by constant 17 to 0x80484b2 <baz+0x52> + [ 10b] special opcode 32: address+1 = 0x80484b3 <baz+0x53>, line+0 = 21 + [ 10c] advance address by 9 to 0x80484bc + [ 10e] extended opcode 1: end of sequence +EOF + +testrun_compare ../src/readelf --debug-dump=decodedline testfilefoobarbaz <<\EOF + +DWARF section [30] '.debug_line' at offset 0x15f6: + + CU [b] foo.c + line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End) + /home/mark/src/tests/foobarbaz/foo.c (mtime: 0, length: 0) + 16:0 S 0 0 0 0x080482f0 <main> + 17:0 S 0 0 0 0x080482fa <main+0xa> + 18:0 S 0 0 0 0x08048301 <main+0x11> + 9:0 S 0 0 0 0x0804830e <main+0x1e> + 11:0 S 0 0 0 0x08048310 <main+0x20> + 9:0 S 0 0 0 0x08048313 <main+0x23> + 11:0 S 0 0 0 0x08048315 <main+0x25> + 9:0 S 0 0 0 0x08048317 <main+0x27> + 22:0 S 0 0 0 0x08048319 <main+0x29> + 9:0 S 0 0 0 0x0804831c <main+0x2c> + 21:0 S 0 0 0 0x0804831f <main+0x2f> + 22:0 S 0 0 0 0x08048322 <main+0x32> + 22:0 S * 0 0 0 0x08048323 <main+0x33> + + CU [141] bar.c + line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End) + /home/mark/src/tests/foobarbaz/bar.c (mtime: 0, length: 0) + 13:0 S 0 0 0 0x08048330 <nobar> + 14:0 S 0 0 0 0x08048330 <nobar> + 14:0 S * 0 0 0 0x0804833a <nobar+0xa> + + 19:0 S 0 0 0 0x08048440 <bar> + 20:0 S 0 0 0 0x08048440 <bar> + 8:0 S 0 0 0 0x0804844d <bar+0xd> + 22:0 S 0 0 0 0x08048451 <bar+0x11> + 22:0 S * 0 0 0 0x08048451 <bar+0x11> + + CU [1dc] baz.c + line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End) + /home/mark/src/tests/foobarbaz/baz.c (mtime: 0, length: 0) + 13:0 S 0 0 0 0x08048340 <nobaz> + 14:0 S 0 0 0 0x08048340 <nobaz> + 14:0 S * 0 0 0 0x0804834a <nobaz+0xa> + + 19:0 S 0 0 0 0x08048460 <baz> + 19:0 S 0 0 0 0x08048464 <baz+0x4> + 20:0 S 0 0 0 0x08048468 <baz+0x8> + 24:0 S 1 0 0 0x0804846c <baz+0xc> + 25:0 S 0 0 0 0x08048478 <baz+0x18> + 24:0 S 0 0 0 0x0804847d <baz+0x1d> + 25:0 S 0 0 0 0x08048480 <baz+0x20> + 24:0 S 0 0 0 0x08048486 <baz+0x26> + 25:0 S 0 0 0 0x08048489 <baz+0x29> + 24:0 S 0 0 0 0x0804848e <baz+0x2e> + 8:0 S 0 0 0 0x08048490 <baz+0x30> + 28:0 S 0 0 0 0x0804849c <baz+0x3c> + 8:0 S 0 0 0 0x080484a1 <baz+0x41> + 21:0 S 0 0 0 0x080484b3 <baz+0x53> + 21:0 S * 0 0 0 0x080484bb <baz+0x5b> + +EOF + +exit 0
On Mon, Mar 25, 2013 at 03:53:59PM +0100, Mark Wielaard wrote:
Display "raw" .debug_aranges by default. Only use libdw parsing when --debug-dump=decodedaranges is given.
I pushed this, the --debug-dump=decodedline support and the new test cases to master now.
Cheers,
Mark
elfutils-devel@lists.fedorahosted.org