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] addr2line: Support -i, --inlines output option.


Show all source locations that caused inline expansion of subroutines
at the given address. This can easily be supported by using libdw
dwarf_getscopes_die which will give all nested inlined subroutines.
When -f, --functions is given also show the function names where the
subroutines were inlines.

The output matches that of binutils addr2line --inlines.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 src/ChangeLog                 |    9 +++
 src/addr2line.c               |  140 ++++++++++++++++++++++++++++++++++------
 tests/ChangeLog               |    8 ++
 tests/Makefile.am             |    6 +-
 tests/run-addr2line-i-test.sh |  145 +++++++++++++++++++++++++++++++++++++++++
 tests/testfile-inlines.bz2    |  Bin 0 -> 2815 bytes
 6 files changed, 286 insertions(+), 22 deletions(-)
 create mode 100755 tests/run-addr2line-i-test.sh
 create mode 100755 tests/testfile-inlines.bz2

diff --git a/src/ChangeLog b/src/ChangeLog
index eacadbc..6788087 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
+2013-08-13  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (options): Add "inlines", 'i'.
+	(show_inlines): New bool.
+	(parse_opt): Handle 'i'.
+	(print_diesym): New static function.
+	(print_src): New function taking code from...
+	(handle_address): here. Call print_src. Print inlines.
+
 2013-08-12  Mark Wielaard  <mjw@redhat.com>
 
 	* addr2line.c (main): If there is a newline char at end of buf,
diff --git a/src/addr2line.c b/src/addr2line.c
index f2bc325..82e80b1 100644
--- a/src/addr2line.c
+++ b/src/addr2line.c
@@ -1,5 +1,5 @@
 /* Locate source files and line information for given addresses
-   Copyright (C) 2005-2010, 2012 Red Hat, Inc.
+   Copyright (C) 2005-2010, 2012, 2013 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2005.
 
@@ -64,6 +64,9 @@ static const struct argp_option options[] =
   { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
   { "section", 'j', "NAME", 0,
     N_("Treat addresses as offsets relative to NAME section."), 0 },
+  { "inlines", 'i', NULL, 0,
+    N_("Show all source locations that caused inline expansion of subroutines at the address."),
+    0 },
 
   { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
   /* Unsupported options.  */
@@ -114,6 +117,9 @@ static bool show_symbols;
 /* If non-null, take address parameters as relative to named section.  */
 static const char *just_section;
 
+/* True if all inlined subroutines of the current address should be shown.  */
+static bool show_inlines;
+
 
 int
 main (int argc, char *argv[])
@@ -232,6 +238,10 @@ parse_opt (int key, char *arg, struct argp_state *state)
       just_section = arg;
       break;
 
+    case 'i':
+      show_inlines = true;
+      break;
+
     default:
       return ARGP_ERR_UNKNOWN;
     }
@@ -351,6 +361,23 @@ print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
     printf ("%s+%#" PRIx64 "\n", name, addr - s.st_value);
 }
 
+static void
+print_diesym (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) ?: "??";
+
+  puts (name);
+}
+
 static int
 see_one_module (Dwfl_Module *mod,
 		void **userdata __attribute__ ((unused)),
@@ -442,6 +469,30 @@ adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
   return false;
 }
 
+static void
+print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu)
+{
+  const char *comp_dir = "";
+  const char *comp_dir_sep = "";
+
+  if (only_basenames)
+    src = basename (src);
+  else if (use_comp_dir && src[0] != '/')
+    {
+      Dwarf_Attribute attr;
+      comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr));
+      if (comp_dir != NULL)
+	comp_dir_sep = "/";
+    }
+
+  if (linecol != 0)
+    printf ("%s%s%s:%d:%d",
+	    comp_dir, comp_dir_sep, src, lineno, linecol);
+  else
+    printf ("%s%s%s:%d",
+	    comp_dir, comp_dir_sep, src, lineno);
+}
+
 static int
 handle_address (const char *string, Dwfl *dwfl)
 {
@@ -510,28 +561,11 @@ handle_address (const char *string, Dwfl *dwfl)
 
   const char *src;
   int lineno, linecol;
+
   if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
 					    NULL, NULL)) != NULL)
     {
-      const char *comp_dir = "";
-      const char *comp_dir_sep = "";
-
-      if (only_basenames)
-	src = basename (src);
-      else if (use_comp_dir && src[0] != '/')
-	{
-	  comp_dir = dwfl_line_comp_dir (line);
-	  if (comp_dir != NULL)
-	    comp_dir_sep = "/";
-	}
-
-      if (linecol != 0)
-	printf ("%s%s%s:%d:%d",
-		comp_dir, comp_dir_sep, src, lineno, linecol);
-      else
-	printf ("%s%s%s:%d",
-		comp_dir, comp_dir_sep, src, lineno);
-
+      print_src (src, lineno, linecol, dwfl_linecu (line));
       if (show_flags)
 	{
 	  Dwarf_Addr bias;
@@ -565,6 +599,72 @@ handle_address (const char *string, Dwfl *dwfl)
   else
     puts ("??:0");
 
+  if (show_inlines)
+    {
+      Dwarf_Addr bias = 0;
+      Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
+
+      Dwarf_Die *scopes;
+      int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
+      if (nscopes < 0)
+	return 1;
+
+      if (nscopes > 0)
+	{
+	  Dwarf_Die subroutine;
+	  Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]);
+	  dwarf_offdie (dwfl_module_getdwarf (mod, &bias),
+			dieoff, &subroutine);
+	  free (scopes);
+
+	  nscopes = dwarf_getscopes_die (&subroutine, &scopes);
+	  if (nscopes > 1)
+	    {
+	      Dwarf_Die cu;
+	      Dwarf_Files *files;
+	      if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL
+		  && dwarf_getsrcfiles (cudie, &files, NULL) == 0)
+		{
+		  for (int i = 0; i < nscopes - 1; i++)
+		    {
+		      Dwarf_Word val;
+		      Dwarf_Attribute attr;
+		      Dwarf_Die *die = &scopes[i];
+		      if (dwarf_tag (die) != DW_TAG_inlined_subroutine)
+			continue;
+
+		      if (show_functions)
+			print_diesym (&scopes[i + 1]);
+
+		      src = NULL;
+		      lineno = 0;
+		      linecol = 0;
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file,
+						       &attr), &val) == 0)
+			src = dwarf_filesrc (files, val, NULL, NULL);
+
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
+						       &attr), &val) == 0)
+			lineno = val;
+
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
+						       &attr), &val) == 0)
+			linecol = val;
+
+		      if (src != NULL)
+			{
+			  print_src (src, lineno, linecol, &cu);
+			  putchar ('\n');
+			}
+		      else
+			puts ("??:0");
+		    }
+		}
+	    }
+	}
+      free (scopes);
+    }
+
   return 0;
 }
 
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 3475d7b..9808ce7 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,11 @@
+2013-08-13  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-i-test.sh: New test.
+	* testfile-inlines.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add run-addr2line-i-test.sh and
+	testfile-inlines.bz2.
+	(TESTS): Add run-addr2line-i-test.sh.
+
 2013-08-12  Mark Wielaard  <mjw@redhat.com>
 
 	* run-addr2line-test.sh: New test.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ac99e3e..9aa06a6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -88,7 +88,8 @@ TESTS = run-arextract.sh run-arsymtest.sh newfile test-nlist \
 	run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \
 	run-test-archive64.sh run-readelf-vmcoreinfo.sh \
 	run-readelf-mixed-corenote.sh run-dwfllines.sh \
-	run-dwfl-report-elf-align.sh run-addr2line-test.sh
+	run-dwfl-report-elf-align.sh run-addr2line-test.sh \
+	run-addr2line-i-test.sh
 
 if !STANDALONE
 check_PROGRAMS += msg_tst md5-sha1-test
@@ -200,7 +201,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     run-dwfllines.sh run-dwfl-report-elf-align.sh \
 	     testfile-dwfl-report-elf-align-shlib.so.bz2 \
 	     testfilenolines.bz2 test-core-lib.so.bz2 test-core.core.bz2 \
-	     test-core.exec.bz2 run-addr2line-test.sh
+	     test-core.exec.bz2 run-addr2line-test.sh \
+	     run-addr2line-i-test.sh testfile-inlines.bz2
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no'
diff --git a/tests/run-addr2line-i-test.sh b/tests/run-addr2line-i-test.sh
new file mode 100755
index 0000000..e98adda
--- /dev/null
+++ b/tests/run-addr2line-i-test.sh
@@ -0,0 +1,145 @@
+#! /bin/sh
+# Copyright (C) 2013 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++ x.cpp -g -fPIC -olibx.so -shared -O3 -fvisibility=hidden
+#
+# void foobar()
+# {
+#   __asm__ ( "nop" ::: );
+# }
+#
+# void fubar()
+# {
+#   __asm__ ( "nop" ::: );
+# }
+#
+# void bar()
+# {
+#   foobar();
+# }
+#
+# void baz()
+# {
+#   fubar();
+# }
+#
+# void foo()
+# {
+#   bar();
+#   baz();
+# }
+#
+# void fu()
+# {
+#   __asm__ ( "nop" ::: );
+#   fubar();
+#   foobar();
+# }
+
+testfiles testfile-inlines
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005a0 <<\EOF
+/tmp/x.cpp:5
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005a1 <<\EOF
+/tmp/x.cpp:6
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005b0 <<\EOF
+/tmp/x.cpp:10
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005b1 <<\EOF
+/tmp/x.cpp:11
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005c0 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:15
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005d0 <<\EOF
+/tmp/x.cpp:10
+/tmp/x.cpp:20
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005e0 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:15
+/tmp/x.cpp:25
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005e1 <<\EOF
+/tmp/x.cpp:10
+/tmp/x.cpp:20
+/tmp/x.cpp:26
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005f1 <<\EOF
+/tmp/x.cpp:10
+/tmp/x.cpp:32
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005f2 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:33
+EOF
+
+# All together now (plus function names).
+testrun_compare ${abs_top_builddir}/src/addr2line -f -i -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 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 _Z3barv
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+fubar inlined at /tmp/x.cpp:20 in _Z3bazv
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+foobar inlined at /tmp/x.cpp:15 in _Z3foov
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+_Z3foov
+/tmp/x.cpp:25
+fubar inlined at /tmp/x.cpp:20 in _Z3foov
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+_Z3foov
+/tmp/x.cpp:26
+fubar inlined at /tmp/x.cpp:32 in _Z2fuv
+/tmp/x.cpp:10
+_Z2fuv
+/tmp/x.cpp:32
+foobar inlined at /tmp/x.cpp:33 in _Z2fuv
+/tmp/x.cpp:5
+_Z2fuv
+/tmp/x.cpp:33
+EOF
+
+exit 0
diff --git a/tests/testfile-inlines.bz2 b/tests/testfile-inlines.bz2
new file mode 100755
index 0000000000000000000000000000000000000000..6a0c7c5749b94cc9bbdba8c5f0b49082fdca29ca
GIT binary patch
literal 2815
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
R&HDTNUC9*TLPO*m5k%+r(a)sj`m

literal 0
HcmV?d00001

-- 
1.7.1


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