From: Mark Wielaard Date: Wed, 20 May 2015 09:52:27 +0000 (+0200) Subject: addr2line: Add demangler support. X-Git-Tag: elfutils-0.162~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cd2da6c37b468c7ac66d2edcd83f8bcbaeb793ec;p=thirdparty%2Felfutils.git addr2line: Add demangler support. Makes the -C, --demangle option visible and implements it (ignoring the demangle style argument). Adds a new test with sample output. Signed-off-by: Mark Wielaard --- diff --git a/NEWS b/NEWS index 88d622ada..6304d88d0 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ libdw: Install new header elfutils/known-dwarf.h. addr2line: Input addresses are now always interpreted as hexadecimal numbers, never as octal or decimal numbers. New option -a, --addresses to print address before each entry. + New option -C, --demangle to show demangled symbols. Version 0.161 diff --git a/src/ChangeLog b/src/ChangeLog index 127e60132..fe6f6f16e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2015-05-20 Mark Wielaard + + * Makefile.am (addr2line_LDADD): Add demanglelib. + * addr2line.c (argp_option): Move demangle under output format. + (demangle): New static bool. + (demangle_buffer_len): New static size_t. + (demangle_buffer): New static char *. + (main): free demangle_buffer. + (parse_opt): Set demangle. + (symname): New static function. + (get_diename): Use symname. + (print_dwarf_function): Likewise. + (print_addrsym): Likewise. + (handle_address): Likewise. + 2015-05-20 Mark Wielaard * addr2line.c (argp_option): Add "addresses", 'a'. diff --git a/src/Makefile.am b/src/Makefile.am index ab5364fe7..58cbe7640 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -102,7 +102,7 @@ endif ld_LDFLAGS = -rdynamic elflint_LDADD = $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl findtextrel_LDADD = $(libdw) $(libelf) $(argp_LDADD) -addr2line_LDADD = $(libdw) $(libelf) $(argp_LDADD) +addr2line_LDADD = $(libdw) $(libelf) $(argp_LDADD) $(demanglelib) elfcmp_LDADD = $(libebl) $(libelf) $(argp_LDADD) -ldl objdump_LDADD = $(libasm) $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl ranlib_LDADD = libar.a $(libelf) $(libeu) $(argp_LDADD) diff --git a/src/addr2line.c b/src/addr2line.c index 720a087ee..786afd344 100644 --- a/src/addr2line.c +++ b/src/addr2line.c @@ -70,11 +70,12 @@ static const struct argp_option options[] = { "inlines", 'i', NULL, 0, N_("Show all source locations that caused inline expansion of subroutines at the address."), 0 }, + { "demangle", 'C', "ARG", OPTION_ARG_OPTIONAL, + N_("Show demangled symbols (ARG is always ignored)"), 0 }, { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 }, /* Unsupported options. */ { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 }, - { "demangle", 'C', "ARG", OPTION_HIDDEN | OPTION_ARG_OPTIONAL, NULL, 0 }, { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 }, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -128,6 +129,13 @@ static const char *just_section; /* True if all inlined subroutines of the current address should be shown. */ static bool show_inlines; +/* True if all names need to be demangled. */ +static bool demangle; + +#ifdef USE_DEMANGLE +static size_t demangle_buffer_len = 0; +static char *demangle_buffer = NULL; +#endif int main (int argc, char *argv[]) @@ -185,6 +193,11 @@ main (int argc, char *argv[]) } dwfl_end (dwfl); + +#ifdef USE_DEMANGLE + free (demangle_buffer); +#endif + return result; } @@ -220,7 +233,7 @@ parse_opt (int key, char *arg, struct argp_state *state) case 'b': case 'C': case OPT_DEMANGLER: - /* Ignored for compatibility. */ + demangle = true; break; case 's': @@ -262,6 +275,22 @@ parse_opt (int key, char *arg, struct argp_state *state) return 0; } +static const char * +symname (const char *name) +{ +#ifdef USE_DEMANGLE + // Require GNU v3 ABI by the "_Z" prefix. + if (demangle && name[0] == '_' && name[1] == 'Z') + { + int status = -1; + char *dsymname = __cxa_demangle (name, demangle_buffer, + &demangle_buffer_len, &status); + if (status == 0) + name = demangle_buffer = dsymname; + } +#endif + return name; +} static const char * get_diename (Dwarf_Die *die) @@ -299,7 +328,7 @@ print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr) const char *name = get_diename (&scopes[i]); if (name == NULL) return false; - puts (name); + puts (symname (name)); return true; } @@ -308,7 +337,7 @@ print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr) const char *name = get_diename (&scopes[i]); if (name == NULL) return false; - printf ("%s inlined", name); + printf ("%s inlined", symname (name)); Dwarf_Files *files; if (dwarf_getsrcfiles (cudie, &files, NULL) == 0) @@ -389,6 +418,7 @@ print_addrsym (Dwfl_Module *mod, GElf_Addr addr) } else { + name = symname (name); if (off == 0) printf ("%s", name); else @@ -623,7 +653,13 @@ handle_address (const char *string, Dwfl *dwfl) /* First determine the function name. Use the DWARF information if possible. */ if (! print_dwarf_function (mod, addr) && !show_symbols) - puts (dwfl_module_addrname (mod, addr) ?: "??"); + { + const char *name = dwfl_module_addrname (mod, addr); + if (name != NULL) + puts (symname (name)); + else + puts ("??"); + } } if (show_symbols) @@ -718,7 +754,7 @@ handle_address (const char *string, Dwfl *dwfl) || tag == DW_TAG_entry_point || tag == DW_TAG_subprogram) { - puts (get_diename (parent)); + puts (symname (get_diename (parent))); break; } } diff --git a/tests/ChangeLog b/tests/ChangeLog index d3a0e4b0a..30ed5f590 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,9 @@ +2015-05-20 Mark Wielaard + + * run-addr2line-i-demangle-test.sh: New test. + * Makefile.am (TESTS): Add run-addr2line-i-demangle-test.sh. + (EXTRA_DIST): Likewise. + 2015-05-20 Mark Wielaard * run-addr2line-test.sh: Add -a test variants. diff --git a/tests/Makefile.am b/tests/Makefile.am index fdbf5bf29..55241c7d1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -104,6 +104,7 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \ run-readelf-mixed-corenote.sh run-dwfllines.sh \ run-dwfl-report-elf-align.sh run-addr2line-test.sh \ run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \ + run-addr2line-i-demangle-test.sh \ run-varlocs.sh run-funcretval.sh \ run-backtrace-native.sh run-backtrace-data.sh run-backtrace-dwarf.sh \ run-backtrace-native-biarch.sh run-backtrace-native-core.sh \ @@ -254,6 +255,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ test-core.exec.bz2 run-addr2line-test.sh \ run-addr2line-i-test.sh testfile-inlines.bz2 \ run-addr2line-i-lex-test.sh testfile-lex-inlines.bz2 \ + run-addr2line-i-demangle-test.sh \ testfileppc32.bz2 testfileppc64.bz2 \ testfiles390.bz2 testfiles390x.bz2 \ testfilearm.bz2 testfileaarch64.bz2 \ diff --git a/tests/run-addr2line-i-demangle-test.sh b/tests/run-addr2line-i-demangle-test.sh new file mode 100755 index 000000000..e709acfaf --- /dev/null +++ b/tests/run-addr2line-i-demangle-test.sh @@ -0,0 +1,69 @@ +#! /bin/sh +# Copyright (C) 2015 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 . + +if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then + exit 77 +fi + +. $srcdir/test-subr.sh + +# See run-addr2line-i-test.sh for how to generate test files. +testfiles testfile-inlines + +# All together now plus (demangled) function names. +testrun_compare ${abs_top_builddir}/src/addr2line -C -f -i -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF +foobar +/tmp/x.cpp:5 +foobar +/tmp/x.cpp:6 +fubar +/tmp/x.cpp:10 +fubar +/tmp/x.cpp:11 +foobar inlined at /tmp/x.cpp:15 in bar() +/tmp/x.cpp:5 +bar +/tmp/x.cpp:15 +fubar inlined at /tmp/x.cpp:20 in baz() +/tmp/x.cpp:10 +baz +/tmp/x.cpp:20 +foobar inlined at /tmp/x.cpp:15 in foo() +/tmp/x.cpp:5 +bar +/tmp/x.cpp:15 +foo() +/tmp/x.cpp:25 +fubar inlined at /tmp/x.cpp:20 in foo() +/tmp/x.cpp:10 +baz +/tmp/x.cpp:20 +foo() +/tmp/x.cpp:26 +fu() +/tmp/x.cpp:31 +fubar inlined at /tmp/x.cpp:32 in fu() +/tmp/x.cpp:10 +fu() +/tmp/x.cpp:32 +foobar inlined at /tmp/x.cpp:33 in fu() +/tmp/x.cpp:5 +fu() +/tmp/x.cpp:33 +EOF + +exit 0