diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | src/ChangeLog | 10 | ||||
-rw-r--r-- | src/stack.c | 56 | ||||
-rw-r--r-- | tests/ChangeLog | 9 | ||||
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rwxr-xr-x | tests/run-stack-d-test.sh | 112 | ||||
-rwxr-xr-x | tests/testfiledwarfinlines.bz2 | bin | 0 -> 4225 bytes | |||
-rw-r--r-- | tests/testfiledwarfinlines.core.bz2 | bin | 0 -> 39713 bytes |
9 files changed, 196 insertions, 5 deletions
@@ -1,3 +1,7 @@ +2014-01-20 Mark Wielaard <mjw@redhat.com> + + * NEWS (Version 0.159): New. Add stack -d. + 2014-01-03 Mark Wielaard <mjw@redhat.com> * configure.ac: Set version to 0.158. @@ -1,3 +1,7 @@ +Version 0.159 + +stack: New option -d, --debugname to lookup DWARF debuginfo name for frame. + Version 0.158 libdwfl: dwfl_core_file_report has new parameter executable. diff --git a/src/ChangeLog b/src/ChangeLog index 57be0bb3..143d73cc 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,5 +1,15 @@ 2014-01-20 Mark Wielaard <mjw@redhat.com> + * stack.c (show_debugname): New static boolean. + (die_name): New function. + (print_frames): If show_debugname is true set symname to the + first function-like DIE with a name in scope for the address in + the debuginfo. + (parse_opt): Handle '-d'. + (main): Add 'd' to options. + +2014-01-20 Mark Wielaard <mjw@redhat.com> + * addr2line.c (handle_address): Initialize scopes to NULL. 2014-01-17 Roland McGrath <roland@redhat.com> diff --git a/src/stack.c b/src/stack.c index 275be08c..ae0ef126 100644 --- a/src/stack.c +++ b/src/stack.c @@ -28,6 +28,7 @@ #include <fcntl.h> #include ELFUTILS_HEADER(dwfl) +#include <dwarf.h> #include <system.h> /* Name and version of program. */ @@ -49,6 +50,7 @@ static bool show_one_tid = false; static bool show_quiet = false; static bool show_raw = false; static bool show_modules = false; +static bool show_debugname = false; static int maxframes = 2048; @@ -192,6 +194,23 @@ frame_callback (Dwfl_Frame *state, void *arg) return DWARF_CB_OK; } +static const char* +die_name (Dwarf_Die *die) +{ + Dwarf_Attribute attr; + const char *name; + name = dwarf_formstring (dwarf_attr_integrate (die, + DW_AT_MIPS_linkage_name, + &attr) + ?: dwarf_attr_integrate (die, + DW_AT_linkage_name, + &attr)); + if (name == NULL) + name = dwarf_diename (die); + + return name; +} + static void print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what) { @@ -209,7 +228,31 @@ print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what) Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted); const char *symname = NULL; if (mod && ! show_quiet) - symname = dwfl_module_addrname (mod, pc_adjusted); + { + if (show_debugname) + { + Dwarf_Addr bias = 0; + Dwarf_Die *cudie = dwfl_module_addrdie (mod, pc_adjusted, &bias); + Dwarf_Die *scopes = NULL; + int nscopes = dwarf_getscopes (cudie, pc_adjusted - bias, + &scopes); + + /* Find the first function-like DIE with a name in scope. */ + for (int i = 0; symname == NULL && i < nscopes; i++) + { + Dwarf_Die *scope = &scopes[i]; + int tag = dwarf_tag (scope); + if (tag == DW_TAG_subprogram + || tag == DW_TAG_inlined_subroutine + || tag == DW_TAG_entry_point) + symname = die_name (scope); + } + free (scopes); + } + + if (symname == NULL) + symname = dwfl_module_addrname (mod, pc_adjusted); + } int width = get_addr_width (mod); printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc); @@ -382,8 +425,12 @@ parse_opt (int key, char *arg __attribute__ ((unused)), show_activation = true; break; + case 'd': + show_debugname = true; + break; + case 'v': - show_activation = show_source = show_module = true; + show_activation = show_source = show_module = show_debugname = true; break; case 'b': @@ -506,12 +553,15 @@ main (int argc, char **argv) { NULL, 0, NULL, 0, N_("Output selection options:"), 0 }, { "activation", 'a', NULL, 0, N_("Additionally show frame activation"), 0 }, + { "debugname", 'd', NULL, 0, + N_("Additionally try to lookup DWARF debuginfo name for frame address"), + 0 }, { "module", 'm', NULL, 0, N_("Additionally show module file information"), 0 }, { "source", 's', NULL, 0, N_("Additionally show source file information"), 0 }, { "verbose", 'v', NULL, 0, - N_("Show all additional information (activation, module and source)"), 0 }, + N_("Show all additional information (activation, debugname, module and source)"), 0 }, { "quiet", 'q', NULL, 0, N_("Do not resolve address to function symbol name"), 0 }, { "raw", 'r', NULL, 0, diff --git a/tests/ChangeLog b/tests/ChangeLog index 733d8e61..70b05510 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,12 @@ +2014-01-20 Mark Wielaard <mjw@redhat.com> + + * Makefile.am (TESTS): Add run-stack-d-test.sh. + (EXTRA_DIST): Add run-stack-d-test.sh, testfiledwarfinlines.bz2 + testfiledwarfinlines.core.bz2. + * run-stack-d-test.sh: New test. + * testfiledwarfinlines.bz2: New test file. + * testfiledwarfinlines.core.bz2: Likewise. + 2014-01-16 Mark Wielaard <mjw@redhat.com> * run-nm-self.sh: Don't use testrun_on_self_quiet but just testrun diff --git a/tests/Makefile.am b/tests/Makefile.am index 1253574d..35f6e87e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -108,7 +108,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-backtrace-native-core-biarch.sh run-backtrace-core-x86_64.sh \ run-backtrace-core-i386.sh run-backtrace-core-ppc.sh \ run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \ - run-backtrace-demangle.sh + run-backtrace-demangle.sh run-stack-d-test.sh if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -264,7 +264,9 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \ run-backtrace-demangle.sh testfile-backtrace-demangle.bz2 \ testfile-backtrace-demangle.cc \ - testfile-backtrace-demangle.core.bz2 + testfile-backtrace-demangle.core.bz2 \ + run-stack-d-test.sh \ + testfiledwarfinlines.bz2 testfiledwarfinlines.core.bz2 if USE_VALGRIND valgrind_cmd='valgrind -q --error-exitcode=1 --run-libc-freeres=no' diff --git a/tests/run-stack-d-test.sh b/tests/run-stack-d-test.sh new file mode 100755 index 00000000..040c2fa9 --- /dev/null +++ b/tests/run-stack-d-test.sh @@ -0,0 +1,112 @@ +#! /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 + +# // g++ dwarfinlines.cpp -g -o testfiledwarfinlines -O2 +# int +# fubar (int x) +# { +# __asm__ ( "nop" ::: ); +# return 42 / x - 2; +# } +# +# void foobar (int z1, int z2) +# { +# __asm__ ( "nop" ::: ); +# int x = z1 + z2; +# while (z1 + x + 1 != 42) +# x = fubar (z1 + z2 + x); +# } +# +# void bar (int z) +# { +# int a, b; +# a = b = z / 2; +# foobar(a, b); +# } +# +# void foo (int x) +# { +# if (x > 0) +# bar(x - 2); +# } +# +# void fu (int y) +# { +# __asm__ ( "nop" ::: ); +# foo (y + 1); +# } +# +# int +# main (int argc, char **argv) +# { +# fu (argc); +# } +testfiles testfiledwarfinlines testfiledwarfinlines.core + +# Depending on whether we are running make check or make installcheck +# the actual binary name under test might be different. It is used in +# the error message, which we also try to match. +if test "$elfutils_testrun" = "installed"; then +STACKCMD=${bindir}/`program_transform stack` +else +STACKCMD=${abs_top_builddir}/src/stack +fi + +# Without -d the top function comes out as fu. +testrun_compare ${abs_top_builddir}/src/stack -n 2 -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF +PID 13654 - core +TID 13654: +#0 0x00000000004006c8 fu(int) +#1 0x00000000004004c5 main +$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited) +EOF + +# But when asking for source we see it is actually on line 6. +# (Which is in function fubar, not fu). +testrun_compare ${abs_top_builddir}/src/stack -n 2 -s -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF +PID 13654 - core +TID 13654: +#0 0x00000000004006c8 fu(int) + /home/mark/src/tests/dwarfinlines.cpp:6 +#1 0x00000000004004c5 main + /home/mark/src/tests/dwarfinlines.cpp:39 +$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited) +EOF + +# So with --debugname we get the function correct as fubar. +testrun_compare ${abs_top_builddir}/src/stack -n 2 -d -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF +PID 13654 - core +TID 13654: +#0 0x00000000004006c8 fubar +#1 0x00000000004004c5 main +$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited) +EOF + +# Which now matches the source line (again 6 of course). +testrun_compare ${abs_top_builddir}/src/stack -n 2 -s -d -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF +PID 13654 - core +TID 13654: +#0 0x00000000004006c8 fubar + /home/mark/src/tests/dwarfinlines.cpp:6 +#1 0x00000000004004c5 main + /home/mark/src/tests/dwarfinlines.cpp:39 +$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited) +EOF + +exit 0 diff --git a/tests/testfiledwarfinlines.bz2 b/tests/testfiledwarfinlines.bz2 Binary files differnew file mode 100755 index 00000000..db14f816 --- /dev/null +++ b/tests/testfiledwarfinlines.bz2 diff --git a/tests/testfiledwarfinlines.core.bz2 b/tests/testfiledwarfinlines.core.bz2 Binary files differnew file mode 100644 index 00000000..2299e1e7 --- /dev/null +++ b/tests/testfiledwarfinlines.core.bz2 |