diff options
| -rw-r--r-- | libdw/ChangeLog | 6 | ||||
| -rw-r--r-- | libdw/dwarf_getsrc_die.c | 46 | ||||
| -rw-r--r-- | tests/Makefile.am | 10 | ||||
| -rw-r--r-- | tests/getsrc_die.c | 72 | ||||
| -rwxr-xr-x | tests/run-getsrc-die.sh | 51 |
5 files changed, 157 insertions, 28 deletions
diff --git a/libdw/ChangeLog b/libdw/ChangeLog index 78c92cfa..d377937f 100644 --- a/libdw/ChangeLog +++ b/libdw/ChangeLog @@ -1,3 +1,9 @@ +2014-12-24 Mark Wielaard <[email protected]> + + * dwarf_getsrc_die.c (dwarf_getsrc_die): Return the last line record + smaller than or equal to addr, rather than returning immediately on + a match. + 2015-01-07 Mark Wielaard <[email protected]> * cfi.h (struct Dwarf_CFI_s): Add search_table_len. diff --git a/libdw/dwarf_getsrc_die.c b/libdw/dwarf_getsrc_die.c index 1914cdf7..a95179ff 100644 --- a/libdw/dwarf_getsrc_die.c +++ b/libdw/dwarf_getsrc_die.c @@ -1,5 +1,5 @@ /* Find line information for address. - Copyright (C) 2004, 2005 Red Hat, Inc. + Copyright (C) 2004, 2005, 2014 Red Hat, Inc. This file is part of elfutils. Written by Ulrich Drepper <[email protected]>, 2004. @@ -45,32 +45,28 @@ dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr) return NULL; /* The lines are sorted by address, so we can use binary search. */ - size_t l = 0, u = nlines; - while (l < u) - { - size_t idx = (l + u) / 2; - if (addr < lines->info[idx].addr) - u = idx; - else if (addr > lines->info[idx].addr || lines->info[idx].end_sequence) - l = idx + 1; - else - return &lines->info[idx]; - } - if (nlines > 0) - assert (lines->info[nlines - 1].end_sequence); - - /* If none were equal, the closest one below is what we want. We - never want the last one, because it's the end-sequence marker - with an address at the high bound of the CU's code. If the debug - information is faulty and no end-sequence marker is present, we - still ignore it. */ - if (u > 0 && u < nlines && addr > lines->info[u - 1].addr) { - while (lines->info[u - 1].end_sequence && u > 0) - --u; - if (u > 0) - return &lines->info[u - 1]; + size_t l = 0, u = nlines - 1; + while (l < u) + { + size_t idx = u - (u - l) / 2; + Dwarf_Line *line = &lines->info[idx]; + if (addr < line->addr) + u = idx - 1; + else + l = idx; + } + + /* This is guaranteed for us by libdw read_srclines. */ + assert (lines->info[nlines - 1].end_sequence); + + /* The last line which is less than or equal to addr is what we + want, unless it is the end_sequence which is after the + current line sequence. */ + Dwarf_Line *line = &lines->info[l]; + if (! line->end_sequence && line->addr <= addr) + return &lines->info[l]; } __libdw_seterrno (DWARF_E_ADDR_OUTOFRANGE); diff --git a/tests/Makefile.am b/tests/Makefile.am index 14adebd5..cbc1eb2f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -50,7 +50,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ test-elf_cntl_gelf_getshdr dwflsyms dwfllines \ dwfl-report-elf-align varlocs backtrace backtrace-child \ backtrace-data backtrace-dwarf debuglink debugaltlink \ - buildid deleted deleted-lib.so aggregate_size vdsosyms + buildid deleted deleted-lib.so aggregate_size vdsosyms \ + getsrc_die asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -111,7 +112,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-backtrace-core-aarch64.sh \ run-backtrace-demangle.sh run-stack-d-test.sh run-stack-i-test.sh \ run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh \ - run-linkmap-cut.sh run-aggregate-size.sh vdsosyms run-readelf-A.sh + run-linkmap-cut.sh run-aggregate-size.sh vdsosyms run-readelf-A.sh \ + run-getsrc-die.sh if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -281,7 +283,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-aggregate-size.sh testfile-sizes1.o.bz2 testfile-sizes2.o.bz2 \ testfile-sizes3.o.bz2 \ run-readelf-A.sh testfileppc32attrs.o.bz2 \ - testfile-debug-types.bz2 + testfile-debug-types.bz2 \ + run-getsrc-die.sh if USE_VALGRIND valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no' @@ -421,6 +424,7 @@ deleted_lib_so_LDFLAGS = -shared -rdynamic deleted_lib_so_CFLAGS = -fPIC -fasynchronous-unwind-tables aggregate_size_LDADD = $(libdw) $(libelf) vdsosyms_LDADD = $(libdw) $(libelf) +getsrc_die_LDADD = $(libdw) $(libelf) if GCOV check: check-am coverage diff --git a/tests/getsrc_die.c b/tests/getsrc_die.c new file mode 100644 index 00000000..055aede0 --- /dev/null +++ b/tests/getsrc_die.c @@ -0,0 +1,72 @@ +/* Copyright (C) 2014 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 <errno.h> +#include <error.h> +#include <fcntl.h> +#include <inttypes.h> +#include <libelf.h> +#include ELFUTILS_HEADER(dw) +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + + +int +main (int argc, char *argv[]) +{ + /* file addr+ */ + int fd = open (argv[1], O_RDONLY); + Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); + if (dbg == NULL) + error (-1, 0, "dwarf_begin (%s): %s\n", argv[1], dwarf_errmsg (-1)); + + for (int i = 2; i < argc; i++) + { + Dwarf_Addr addr; + char *endptr; + Dwarf_Die cudie; + Dwarf_Line *line; + + errno = 0; + addr = strtoull (argv[i], &endptr, 16); + if (errno != 0) + error (-1, errno, "Cannot parrse '%s'", argv[1]); + + if (dwarf_addrdie (dbg, addr, &cudie) == NULL) + error (-1, 0, "dwarf_addrdie (%s): %s", argv[i], dwarf_errmsg (-1)); + + line = dwarf_getsrc_die (&cudie, addr); + if (line == NULL) + error (-1, 0, "dwarf_getsrc_die (%s): %s", argv[i], dwarf_errmsg (-1)); + + const char *f = dwarf_linesrc (line, NULL, NULL); + int l; + if (dwarf_lineno (line, &l) != 0) + l = 0; + + printf ("%s:%d\n", f ?: "???", l); + } + + dwarf_end (dbg); + close (fd); + + return 0; +} diff --git a/tests/run-getsrc-die.sh b/tests/run-getsrc-die.sh new file mode 100755 index 00000000..4da16e7a --- /dev/null +++ b/tests/run-getsrc-die.sh @@ -0,0 +1,51 @@ +#! /bin/sh +# Copyright (C) 2014 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 + +# See run-addr2line-test.sh run-addr2line-i-test.sh run-addr2line-i-lex-test.sh +# Output/files/lines matched should equal what is done through addr2line +# which uses dwfl_module_getsrc. This test uses dwarf_addrdie and +# dwarf_getsrc_die +testfiles testfile testfile-inlines testfile-lex-inlines + +testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile 0x08048468 0x0804845c <<\EOF +/home/drepper/gnu/new-bu/build/ttt/f.c:3 +/home/drepper/gnu/new-bu/build/ttt/b.c:4 +EOF + +testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f1 0x00000000000005f2 <<\EOF +/tmp/x.cpp:5 +/tmp/x.cpp:6 +/tmp/x.cpp:10 +/tmp/x.cpp:11 +/tmp/x.cpp:5 +/tmp/x.cpp:10 +/tmp/x.cpp:5 +/tmp/x.cpp:10 +/tmp/x.cpp:10 +/tmp/x.cpp:5 +EOF + +testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-lex-inlines 0x0000000000000680 0x0000000000000681 0x0000000000000690 0x0000000000000691 <<\EOF +/tmp/x.cpp:5 +/tmp/x.cpp:5 +/tmp/x.cpp:5 +/tmp/x.cpp:5 +EOF + +exit 0 |
