This is the mail archive of the
elfutils-devel@sourceware.org
mailing list for the elfutils project.
[PATCH 4/5] addr2line: Add demangler support.
- From: Mark Wielaard <mjw at redhat dot com>
- To: elfutils-devel at lists dot fedorahosted dot org
- Date: Wed, 20 May 2015 16:35:46 +0200
- Subject: [PATCH 4/5] 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 <mjw@redhat.com>
---
NEWS | 1 +
src/ChangeLog | 15 ++++++++
src/Makefile.am | 2 +-
src/addr2line.c | 48 ++++++++++++++++++++---
tests/ChangeLog | 6 +++
tests/Makefile.am | 2 +
tests/run-addr2line-i-demangle-test.sh | 69 ++++++++++++++++++++++++++++++++++
7 files changed, 136 insertions(+), 7 deletions(-)
create mode 100755 tests/run-addr2line-i-demangle-test.sh
diff --git a/NEWS b/NEWS
index 6d81e59..46ff872 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ Version 0.162
libdw: Install new header elfutils/known-dwarf.h.
addr2line: 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 127e601..fe6f6f1 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,20 @@
2015-05-20 Mark Wielaard <mjw@redhat.com>
+ * 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 <mjw@redhat.com>
+
* addr2line.c (argp_option): Add "addresses", 'a'.
(print_addresses): New static bool.
(parse_opt): Set print_addresses.
diff --git a/src/Makefile.am b/src/Makefile.am
index ab5364f..58cbe76 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 4416c7a..3f64011 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 d3a0e4b..30ed5f5 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,11 @@
2015-05-20 Mark Wielaard <mjw@redhat.com>
+ * 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 <mjw@redhat.com>
+
* run-addr2line-test.sh: Add -a test variants.
* run-addr2line-i-test.sh: Likewise.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index fdbf5bf..55241c7 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 0000000..e709acf
--- /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 <http://www.gnu.org/licenses/>.
+
+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
--
1.8.3.1