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: