dwfl_getsrclines would always fail, even when lines were found. dwarf_decl_file, and other functions relying on srcfiles or srclines would fail for DIEs in partial_units because stmt_lists on partial_units were ignored.
Note that dwz contained a bug which makes things fail in __libdw_formptr for DW_AT_stmt_list with a bogus DW_FORM even with these fixes. https://bugzilla.redhat.com/show_bug.cgi?id=919755
Signed-off-by: Mark Wielaard mjw@redhat.com --- libdw/ChangeLog | 5 ++ libdw/dwarf_getsrcfiles.c | 5 +- libdw/dwarf_getsrclines.c | 5 +- libdwfl/ChangeLog | 4 ++ libdwfl/dwfl_getsrclines.c | 4 +- tests/ChangeLog | 8 +++ tests/Makefile.am | 8 ++- tests/dwfllines.c | 164 +++++++++++++++++++++++++++++++++++++++++++++ tests/run-dwfllines.sh | 88 ++++++++++++++++++++++++ 9 files changed, 282 insertions(+), 9 deletions(-) create mode 100644 tests/dwfllines.c create mode 100755 tests/run-dwfllines.sh
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 2900ef6..16acf5c 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,8 @@ +2013-03-12 Mark Wielaard mjw@redhat.com + + * dwarf_getsrcfiles.c (dwarf_getsrcfiles): Allow DW_TAG_partial_unit. + * dwarf_getsrclines.c (dwarf_getsrclines): Likewise. + 2013-02-15 Mark Wielaard mjw@redhat.com
* dwarf_formstring.c (dwarf_formstring): Check dbg_ret->sectiondata, diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c index d026820..4bfc34b 100644 --- a/libdw/dwarf_getsrcfiles.c +++ b/libdw/dwarf_getsrcfiles.c @@ -1,5 +1,5 @@ /* Return source file information of CU. - Copyright (C) 2004, 2005 Red Hat, Inc. + Copyright (C) 2004, 2005, 2013 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper drepper@redhat.com, 2004.
@@ -40,7 +40,8 @@ int dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles) { if (unlikely (cudie == NULL - || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit)) + || (INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit + && INTUSE(dwarf_tag) (cudie) != DW_TAG_partial_unit))) return -1;
int res = -1; diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c index 0758023..c24aebb 100644 --- a/libdw/dwarf_getsrclines.c +++ b/libdw/dwarf_getsrclines.c @@ -1,5 +1,5 @@ /* Return line number information of CU. - Copyright (C) 2004-2010 Red Hat, Inc. + Copyright (C) 2004-2010, 2013 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper drepper@redhat.com, 2004.
@@ -69,7 +69,8 @@ int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) { if (unlikely (cudie == NULL - || INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit)) + || (INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit + && INTUSE(dwarf_tag) (cudie) != DW_TAG_partial_unit))) return -1;
int res = -1; diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 78139ba..15a6c9c 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,7 @@ +2013-03-12 Mark Wielaard mjw@redhat.com + + * dwfl_getsrclines.c (dwfl_getsrclines): Return 0 on success. + 2013-02-22 Mark Wielaard mjw@redhat.com
* open.c (__libdw_gunzip,__libdw_bunzip2,__libdw_unlzma): Define diff --git a/libdwfl/dwfl_getsrclines.c b/libdwfl/dwfl_getsrclines.c index cc8cb7c..bdfcf5c 100644 --- a/libdwfl/dwfl_getsrclines.c +++ b/libdwfl/dwfl_getsrclines.c @@ -1,5 +1,5 @@ /* Fetch source line information for CU. - Copyright (C) 2005 Red Hat, Inc. + Copyright (C) 2005, 2013 Red Hat, Inc. This file is part of elfutils.
This file is free software; you can redistribute it and/or modify @@ -44,5 +44,5 @@ dwfl_getsrclines (Dwarf_Die *cudie, size_t *nlines) }
*nlines = cu->die.cu->lines->nlines; - return -1; + return 0; } diff --git a/tests/ChangeLog b/tests/ChangeLog index d181cd5..ca06a55 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,11 @@ +2013-03-12 Mark Wielaard mjw@redhat.com + + * run-dwfllines.sh: New test. + * dwfllines.c: New test program. + * Makefile.am (TESTS): Add run-dwfllines.sh. + (EXTRA_DIST): Likewise. + (dwfllines_LDADD): New variable. + 2013-02-22 Mark Wielaard mjw@redhat.com
* Makefile.am (TESTS): Remove run-readelf-s.sh and run-dwflsyms.sh. diff --git a/tests/Makefile.am b/tests/Makefile.am index 63184f8..a5f7a8c 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -51,7 +51,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ dwfl-bug-getmodules dwarf-getmacros addrcfi \ test-flag-nobits dwarf-getstring rerequest_tag \ alldts md5-sha1-test typeiter low_high_pc \ - test-elf_cntl_gelf_getshdr dwflsyms + test-elf_cntl_gelf_getshdr dwflsyms dwfllines asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9
@@ -85,7 +85,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-d.sh run-readelf-gdb_index.sh run-unstrip-n.sh \ run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \ run-test-archive64.sh run-readelf-vmcoreinfo.sh \ - run-readelf-mixed-corenote.sh + run-readelf-mixed-corenote.sh run-dwfllines.sh
if !STANDALONE check_PROGRAMS += msg_tst md5-sha1-test @@ -192,7 +192,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-readelf-mixed-corenote.sh testfile63.bz2 testfile64.bz2 \ testfile65.bz2 testfile67.bz2 testfile68.bz2 \ testfile69.core.bz2 testfile69.so.bz2 \ - testfile70.core.bz2 testfile70.exec.bz2 + testfile70.core.bz2 testfile70.exec.bz2 \ + run-dwfllines.sh
if USE_VALGRIND valgrind_cmd="valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no" @@ -300,6 +301,7 @@ typeiter_LDADD = $(libdw) $(libelf) $(libmudflap) low_high_pc_LDADD = $(libdw) $(libelf) $(libmudflap) test_elf_cntl_gelf_getshdr_LDADD = $(libelf) $(libmudflap) dwflsyms_LDADD = $(libdw) $(libelf) $(libmudflap) +dwfllines_LDADD = $(libdw) $(libelf) $(libmudflap)
if GCOV check: check-am coverage diff --git a/tests/dwfllines.c b/tests/dwfllines.c new file mode 100644 index 0000000..90379dd --- /dev/null +++ b/tests/dwfllines.c @@ -0,0 +1,164 @@ +/* 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/. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <inttypes.h> +#include <assert.h> +#include ELFUTILS_HEADER(dw) +#include ELFUTILS_HEADER(dwfl) +#include <dwarf.h> +#include <argp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <error.h> + +int +main (int argc, char *argv[]) +{ + int cnt; + + Dwfl *dwfl = NULL; + (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &cnt, &dwfl); + assert (dwfl != NULL); + + Dwarf_Die *cu = NULL; + Dwarf_Addr bias; + do + { + cu = dwfl_nextcu (dwfl, cu, &bias); + if (cu != NULL) + { + Dwfl_Module *mod = dwfl_cumodule (cu); + const char *modname = (dwfl_module_info (mod, NULL, NULL, NULL, + NULL, NULL, NULL, NULL) + ?: "<unknown>"); + const char *cuname = (dwarf_diename (cu) ?: "<unknown>"); + + printf ("mod: %s CU: [%" PRIx64 "] %s\n", modname, + dwarf_dieoffset (cu), cuname); + + size_t lines; + if (dwfl_getsrclines (cu, &lines) != 0) + continue; // No lines... + + for (size_t i = 0; i < lines; i++) + { + Dwfl_Line *line = dwfl_onesrcline (cu, i); + + Dwarf_Addr addr; + int lineno; + int colno; + Dwarf_Word mtime; + Dwarf_Word length; + const char *src = dwfl_lineinfo (line, &addr, &lineno, &colno, + &mtime, &length); + + Dwarf_Addr dw_bias; + Dwarf_Line *dw_line = dwfl_dwarf_line (line, &dw_bias); + assert (bias == dw_bias); + + Dwarf_Addr dw_addr; + if (dwarf_lineaddr (dw_line, &dw_addr) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineaddr: %s", + dwarf_errmsg (-1)); + assert (addr == dw_addr + dw_bias); + + unsigned int dw_op_index; + if (dwarf_lineop_index (dw_line, &dw_op_index) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineop_index: %s", + dwarf_errmsg (-1)); + + int dw_lineno; + if (dwarf_lineno (dw_line, &dw_lineno) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineno: %s", + dwarf_errmsg (-1)); + assert (lineno == dw_lineno); + + int dw_colno; + if (dwarf_linecol (dw_line, &dw_colno) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineno: %s", + dwarf_errmsg (-1)); + assert (colno == dw_colno); + + bool begin; + if (dwarf_linebeginstatement (dw_line, &begin) != 0) + error (EXIT_FAILURE, 0, "dwarf_linebeginstatement: %s", + dwarf_errmsg (-1)); + + bool end; + if (dwarf_lineendsequence (dw_line, &end) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineendsequence: %s", + dwarf_errmsg (-1)); + + bool pend; + if (dwarf_lineprologueend (dw_line, &pend) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineprologueend: %s", + dwarf_errmsg (-1)); + + bool ebegin; + if (dwarf_lineepiloguebegin (dw_line, &ebegin) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineepiloguebegin: %s", + dwarf_errmsg (-1)); + + bool block; + if (dwarf_lineblock (dw_line, &block) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineblock: %s", + dwarf_errmsg (-1)); + + unsigned int isa; + if (dwarf_lineisa (dw_line, &isa) != 0) + error (EXIT_FAILURE, 0, "dwarf_lineisa: %s", + dwarf_errmsg (-1)); + + unsigned int disc; + if (dwarf_linediscriminator (dw_line, &disc) != 0) + error (EXIT_FAILURE, 0, "dwarf_linediscriminator: %s", + dwarf_errmsg (-1)); + + const char *dw_src; + Dwarf_Word dw_mtime; + Dwarf_Word dw_length; + dw_src = dwarf_linesrc (dw_line, &dw_mtime, &dw_length); + assert (strcmp (src, dw_src) == 0); + assert (mtime == dw_mtime); + assert (length == dw_length); + + printf ("%zd %#" PRIx64 " %s:%d:%d\n" + " time: %#" PRIX64 ", len: %" PRIu64 + ", idx: %d, b: %d, e: %d" + ", pe: %d, eb: %d, block: %d" + ", isa: %d, disc: %d\n", + i, addr, src, lineno, colno, mtime, length, + dw_op_index, begin, end, pend, ebegin, block, isa, disc); + + Dwarf_Die *linecu = dwfl_linecu (line); + assert (cu == linecu); + + Dwfl_Module *linemod = dwfl_linemodule (line); + assert (mod == linemod); + } + } + } + while (cu != NULL); + + dwfl_end (dwfl); + + return 0; +} diff --git a/tests/run-dwfllines.sh b/tests/run-dwfllines.sh new file mode 100755 index 0000000..df7d16f --- /dev/null +++ b/tests/run-dwfllines.sh @@ -0,0 +1,88 @@ +#! /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 + +testfiles testfile testfile2 + +testrun_compare ./dwfllines -e testfile <<\EOF +mod: CU: [b] m.c +0 0x804842c /home/drepper/gnu/new-bu/build/ttt/m.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +1 0x8048432 /home/drepper/gnu/new-bu/build/ttt/m.c:6:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +2 0x804844d /home/drepper/gnu/new-bu/build/ttt/m.c:7:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +3 0x8048458 /home/drepper/gnu/new-bu/build/ttt/m.c:8:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +4 0x804845a /home/drepper/gnu/new-bu/build/ttt/m.c:8:0 + time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +mod: CU: [ca] b.c +0 0x804845c /home/drepper/gnu/new-bu/build/ttt/b.c:4:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +1 0x804845f /home/drepper/gnu/new-bu/build/ttt/b.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +2 0x8048464 /home/drepper/gnu/new-bu/build/ttt/b.c:6:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +3 0x8048466 /home/drepper/gnu/new-bu/build/ttt/b.c:6:0 + time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +mod: CU: [15fc] f.c +0 0x8048468 /home/drepper/gnu/new-bu/build/ttt/f.c:3:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +1 0x804846b /home/drepper/gnu/new-bu/build/ttt/f.c:4:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +2 0x8048470 /home/drepper/gnu/new-bu/build/ttt/f.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +3 0x8048472 /home/drepper/gnu/new-bu/build/ttt/f.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +EOF + +testrun_compare ./dwfllines -e testfile2 <<\EOF +mod: CU: [b] b.c +0 0x10000470 /shoggoth/drepper/b.c:4:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +1 0x1000047c /shoggoth/drepper/b.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +2 0x10000480 /shoggoth/drepper/b.c:6:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +3 0x10000490 /shoggoth/drepper/b.c:6:0 + time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +mod: CU: [97d] f.c +0 0x10000490 /shoggoth/drepper/f.c:3:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +1 0x1000049c /shoggoth/drepper/f.c:4:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +2 0x100004a0 /shoggoth/drepper/f.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +3 0x100004b0 /shoggoth/drepper/f.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +mod: CU: [9e4] m.c +0 0x100004b0 /shoggoth/drepper/m.c:5:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +1 0x100004cc /shoggoth/drepper/m.c:6:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +2 0x100004e8 /shoggoth/drepper/m.c:7:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +3 0x100004f4 /shoggoth/drepper/m.c:8:0 + time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +4 0x10000514 /shoggoth/drepper/m.c:8:0 + time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0 +EOF + +testrun_on_self_quiet ./dwfllines -e + +exit 0
On Tue, 2013-03-12 at 12:30 +0100, Mark Wielaard wrote:
dwfl_getsrclines would always fail, even when lines were found. dwarf_decl_file, and other functions relying on srcfiles or srclines would fail for DIEs in partial_units because stmt_lists on partial_units were ignored.
I pushed this to master.
Cheers,
Mark
elfutils-devel@lists.fedorahosted.org