[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#946606: libc-bin: catchsegv does not handle backtraces with parentheses



Dear Maintainer,
while I was at it, I attempted to change the output to
deliver the before mentioned information for addr2line too.

Attached is a improved patch, that would now output following:

Backtrace:
 [0x55f317f9175b] main at /usr/share/doc/libsoxr-dev/examples/3-options-input-fn.c:79 (discriminator 4) /tmp/tmp.sSrfzsTKpn/3-options-input-fn(+0x175b)
 [0x7fd67920fbbb] __libc_start_main at /root/source/glibc/try1/glibc-2.29/csu/../csu/libc-start.c:342 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xeb,+0x26bbb)
 [0x55f317f911ba] _start at ??:? /tmp/tmp.sSrfzsTKpn/3-options-input-fn(+0x11ba)

At the end there is another small change to add the build-ids
of the in the backtrace involved binaries to the output.

Kind regards,
Bernhard
>From cb1fdbd4e5a7fbeb1de27b72a7945a0b4789d251 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <bernhardu@mailbox.org>
Date: Wed, 11 Dec 2019 19:56:39 +0100
Subject: Make catchsegv work again after format changed and add build-ids.

https://sourceware.org/bugzilla/show_bug.cgi?id=21830
---
 debug/backtracesymsfd.c | 32 +++++++++++++++++++++++++-
 debug/catchsegv.sh      | 51 ++++++++++++++++++++++++++++++++---------
 2 files changed, 71 insertions(+), 12 deletions(-)

diff --git a/debug/backtracesymsfd.c b/debug/backtracesymsfd.c
index 5751d62f..9bc058fb 100644
--- a/debug/backtracesymsfd.c
+++ b/debug/backtracesymsfd.c
@@ -35,13 +35,14 @@
 void
 __backtrace_symbols_fd (void *const *array, int size, int fd)
 {
-  struct iovec iov[9];
+  struct iovec iov[12];
   int cnt;
 
   for (cnt = 0; cnt < size; ++cnt)
     {
       char buf[WORD_WIDTH];
       char buf2[WORD_WIDTH];
+      char buf3[WORD_WIDTH];
       Dl_info info;
       struct link_map *map;
       size_t last = 0;
@@ -96,6 +97,35 @@ __backtrace_symbols_fd (void *const *array, int size, int fd)
 				   - (char *) iov[last].iov_base);
 	      ++last;
 
+	      /* Even when we have a symbol name, print the file offset to
+	         make processing in addr2line possible. */
+	      if (info.dli_sname != NULL)
+		{
+		  iov[last].iov_base = (void *) ",";
+		  iov[last].iov_len = 1;
+		  ++last;
+
+		  if (array[cnt] >= (void *) map->l_addr)
+		    {
+		      iov[last].iov_base = (void *) "+0x";
+		      diff = array[cnt] - (void *) map->l_addr;
+		    }
+		  else
+		    {
+		      iov[last].iov_base = (void *) "-0x";
+		      diff = (void *) map->l_addr - array[cnt];
+		    }
+		  iov[last].iov_len = 3;
+		  ++last;
+
+		  iov[last].iov_base = _itoa_word ((unsigned long int) diff,
+		                                   &buf3[WORD_WIDTH], 16, 0);
+		  iov[last].iov_len = (&buf3[WORD_WIDTH]
+		                       - (char *) iov[last].iov_base);
+		  ++last;
+
+		}
+
 	      iov[last].iov_base = (void *) ")";
 	      iov[last].iov_len = 1;
 	      ++last;
diff --git a/debug/catchsegv.sh b/debug/catchsegv.sh
index 245c100f..8d8a38f0 100755
--- a/debug/catchsegv.sh
+++ b/debug/catchsegv.sh
@@ -52,6 +52,7 @@ Written by Ulrich Drepper.'
 fi
 
 segv_output=`mktemp ${TMPDIR:-/tmp}/segv_output.XXXXXX` || exit
+used_libs=`mktemp ${TMPDIR:-/tmp}/used_libs.XXXXXX` || exit
 
 # Redirect stderr to avoid termination message from shell.
 (exec 3>&2 2>/dev/null
@@ -87,21 +88,49 @@ if test -s "$segv_output"; then
   sed '/Backtrace/q' "$segv_output"
   sed '1,/Backtrace/d' "$segv_output" |
   (while read line; do
-     line=`echo $line | sed "s@^$prog\\(\\[.*\\)@\1@"`
      case "$line" in
-       \[*) addr=`echo "$line" | sed 's/^\[\(.*\)\]$/\1/'`
-	    complete=`addr2line -f -e "$prog" $addr 2>/dev/null`
-	    if test $? -eq 0; then
-	      echo "`echo "$complete"|sed 'N;s/\(.*\)\n\(.*\)/\2(\1)/;'`$line"
-	    else
-	      echo "$line"
-	    fi
-	    ;;
-	 *) echo "$line"
-	    ;;
+       *\(*\)\[*\])
+         lib=`echo $line  | sed "s@^\(.*\)(\(.*\))\[\(.*\)\]\\$@\1@"`
+         offs=`echo $line | sed "s@^\(.*\)(\(.*\))\[\(.*\)\]\\$@\2@"`
+         addr=`echo $line | sed "s@^\(.*\)(\(.*\))\[\(.*\)\]\\$@\3@"`
+         func=""
+         case "$offs" in
+           *,*) func=`echo $offs | sed "s@\(.*\),\(.*\)\\$@\1,@"`
+                offs=`echo $offs | sed "s@\(.*\),\(.*\)\\$@\2@"`
+                ;;
+         esac
+         case "$offs" in
+           +*) case "$prog" in
+                 */$lib)
+                   lib="$prog"
+                   ;;
+               esac
+               complete=`addr2line -p -i -f -e "$lib" $offs 2>/dev/null`
+               if test $? -eq 0; then
+                 echo " [$addr] $complete $lib($func$offs)"
+               else
+                 echo " $line"
+               fi
+               ;;
+           *) echo " $line"
+              ;;
+         esac
+         echo "$lib" >> "$used_libs"
+         ;;
+        *) echo "$line"
+           ;;
      esac
    done)
 fi
 rm -f "$segv_output"
 
+objdumptest=`objdump --version 2>/dev/null`
+if test $? -eq 0; then
+  echo "\nBuild-IDs:"
+  sort -u /tmp/used_libs.kUDu9V | while read lib; do
+    objdump -s -j .note.gnu.build-id "$lib"
+  done
+fi
+rm -f "$used_libs"
+
 exit $exval
-- 
2.24.0


Reply to: