From: Mark Wielaard Date: Mon, 25 Mar 2013 13:48:06 +0000 (+0100) Subject: readelf: Add --debug-dump=decodedline support. X-Git-Tag: elfutils-0.156~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1a09420a120dc7b71574f433d9c4929a80873ce3;p=thirdparty%2Felfutils.git readelf: Add --debug-dump=decodedline support. Use libdw to decode the .debug_line section and print address table view when --debug-dump=decodedline is given. Signed-off-by: Mark Wielaard --- diff --git a/src/ChangeLog b/src/ChangeLog index 30d186056..ec6561121 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2013-03-25 Mark Wielaard + + * 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 * readelf.c (argp_option): Add decodedaranges. diff --git a/src/readelf.c b/src/readelf.c index 7252d724f..d9527c6da 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) @@ -5898,10 +5906,96 @@ 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 4e630398a..85ed67827 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 000000000..f0e491d69 --- /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 . + +. $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 < + [ 3c] advance line by constant 15 to 16 + [ 3e] copy + [ 3f] special opcode 159: address+10 = 0x80482fa , line+1 = 17 + [ 40] special opcode 117: address+7 = 0x8048301 , line+1 = 18 + [ 41] advance line by constant -9 to 9 + [ 43] special opcode 200: address+13 = 0x804830e , line+0 = 9 + [ 44] special opcode 48: address+2 = 0x8048310 , line+2 = 11 + [ 45] special opcode 58: address+3 = 0x8048313 , line-2 = 9 + [ 46] special opcode 48: address+2 = 0x8048315 , line+2 = 11 + [ 47] special opcode 44: address+2 = 0x8048317 , line-2 = 9 + [ 48] advance line by constant 13 to 22 + [ 4a] special opcode 46: address+2 = 0x8048319 , line+0 = 22 + [ 4b] advance line by constant -13 to 9 + [ 4d] special opcode 60: address+3 = 0x804831c , line+0 = 9 + [ 4e] advance line by constant 12 to 21 + [ 50] special opcode 60: address+3 = 0x804831f , line+0 = 21 + [ 51] special opcode 61: address+3 = 0x8048322 , 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 + [ 84] advance line by constant 12 to 13 + [ 86] copy + [ 87] special opcode 19: address+0 = 0x8048330 , 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 + [ 94] advance line by constant 18 to 19 + [ 96] copy + [ 97] special opcode 19: address+0 = 0x8048440 , line+1 = 20 + [ 98] advance line by constant -12 to 8 + [ 9a] special opcode 200: address+13 = 0x804844d , line+0 = 8 + [ 9b] advance line by constant 14 to 22 + [ 9d] special opcode 74: address+4 = 0x8048451 , 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 + [ df] advance line by constant 12 to 13 + [ e1] copy + [ e2] special opcode 19: address+0 = 0x8048340 , 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 + [ ef] advance line by constant 18 to 19 + [ f1] copy + [ f2] special opcode 74: address+4 = 0x8048464 , line+0 = 19 + [ f3] special opcode 75: address+4 = 0x8048468 , line+1 = 20 + [ f4] extended opcode 4: set discriminator to 1 + [ f8] special opcode 78: address+4 = 0x804846c , line+4 = 24 + [ f9] special opcode 187: address+12 = 0x8048478 , line+1 = 25 + [ fa] special opcode 87: address+5 = 0x804847d , line-1 = 24 + [ fb] special opcode 61: address+3 = 0x8048480 , line+1 = 25 + [ fc] special opcode 101: address+6 = 0x8048486 , line-1 = 24 + [ fd] special opcode 61: address+3 = 0x8048489 , line+1 = 25 + [ fe] special opcode 87: address+5 = 0x804848e , line-1 = 24 + [ ff] advance line by constant -16 to 8 + [ 101] special opcode 46: address+2 = 0x8048490 , line+0 = 8 + [ 102] advance line by constant 20 to 28 + [ 104] special opcode 186: address+12 = 0x804849c , line+0 = 28 + [ 105] advance line by constant -20 to 8 + [ 107] special opcode 88: address+5 = 0x80484a1 , line+0 = 8 + [ 108] advance line by constant 13 to 21 + [ 10a] advance address by constant 17 to 0x80484b2 + [ 10b] special opcode 32: address+1 = 0x80484b3 , 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
+ 17:0 S 0 0 0 0x080482fa + 18:0 S 0 0 0 0x08048301 + 9:0 S 0 0 0 0x0804830e + 11:0 S 0 0 0 0x08048310 + 9:0 S 0 0 0 0x08048313 + 11:0 S 0 0 0 0x08048315 + 9:0 S 0 0 0 0x08048317 + 22:0 S 0 0 0 0x08048319 + 9:0 S 0 0 0 0x0804831c + 21:0 S 0 0 0 0x0804831f + 22:0 S 0 0 0 0x08048322 + 22:0 S * 0 0 0 0x08048323 + + 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 + 14:0 S 0 0 0 0x08048330 + 14:0 S * 0 0 0 0x0804833a + + 19:0 S 0 0 0 0x08048440 + 20:0 S 0 0 0 0x08048440 + 8:0 S 0 0 0 0x0804844d + 22:0 S 0 0 0 0x08048451 + 22:0 S * 0 0 0 0x08048451 + + 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 + 14:0 S 0 0 0 0x08048340 + 14:0 S * 0 0 0 0x0804834a + + 19:0 S 0 0 0 0x08048460 + 19:0 S 0 0 0 0x08048464 + 20:0 S 0 0 0 0x08048468 + 24:0 S 1 0 0 0x0804846c + 25:0 S 0 0 0 0x08048478 + 24:0 S 0 0 0 0x0804847d + 25:0 S 0 0 0 0x08048480 + 24:0 S 0 0 0 0x08048486 + 25:0 S 0 0 0 0x08048489 + 24:0 S 0 0 0 0x0804848e + 8:0 S 0 0 0 0x08048490 + 28:0 S 0 0 0 0x0804849c + 8:0 S 0 0 0 0x080484a1 + 21:0 S 0 0 0 0x080484b3 + 21:0 S * 0 0 0 0x080484bb + +EOF + +exit 0