This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]