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
+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'.
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)
{ "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 }
};
/* 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[])
}
dwfl_end (dwfl);
+
+#ifdef USE_DEMANGLE
+ free (demangle_buffer);
+#endif
+
return result;
}
case 'b':
case 'C':
case OPT_DEMANGLER:
- /* Ignored for compatibility. */
+ demangle = true;
break;
case 's':
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)
const char *name = get_diename (&scopes[i]);
if (name == NULL)
return false;
- puts (name);
+ puts (symname (name));
return true;
}
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)
}
else
{
+ name = symname (name);
if (off == 0)
printf ("%s", name);
else
/* 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)
|| tag == DW_TAG_entry_point
|| tag == DW_TAG_subprogram)
{
- puts (get_diename (parent));
+ puts (symname (get_diename (parent)));
break;
}
}
+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-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 \
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 \
--- /dev/null
+#! /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