u_debug_symbol: add support for getting symbol names from glibc
authorLuca Barbieri <luca@luca-barbieri.com>
Tue, 17 Aug 2010 22:39:49 +0000 (00:39 +0200)
committerLuca Barbieri <luca@luca-barbieri.com>
Fri, 20 Aug 2010 16:18:28 +0000 (18:18 +0200)
src/gallium/auxiliary/util/u_debug_symbol.c
src/gallium/tools/addr2line.sh [new file with mode: 0755]

index 7147bbc32b874a6ad7c5c6b9ed304bee04f5bad2..ebea517f90e414e046f0488573e3b6933d604f3a 100644 (file)
@@ -143,6 +143,23 @@ debug_symbol_name_imagehlp(const void *addr, char* buf, unsigned size)
 }
 #endif
 
 }
 #endif
 
+#ifdef __GLIBC__
+#include <execinfo.h>
+
+/* This can only provide dynamic symbols, or binary offsets into a file.
+ *
+ * To fix this, post-process the output with tools/addr2line.sh
+ */
+static INLINE void
+debug_symbol_name_glibc(const void *addr, char* buf, unsigned size)
+{
+   char** syms = backtrace_symbols((void**)&addr, 1);
+   strncpy(buf, syms[0], size);
+   buf[size - 1] = 0;
+   free(syms);
+}
+#endif
+
 void
 debug_symbol_name(const void *addr, char* buf, unsigned size)
 {
 void
 debug_symbol_name(const void *addr, char* buf, unsigned size)
 {
@@ -152,6 +169,12 @@ debug_symbol_name(const void *addr, char* buf, unsigned size)
       return;
 #endif
 
       return;
 #endif
 
+#ifdef __GLIBC__
+   debug_symbol_name_glibc(addr, buf, size);
+   if(buf[0])
+      return;
+#endif
+
    util_snprintf(buf, size, "%p", addr);
    buf[size - 1] = 0;
 }
    util_snprintf(buf, size, "%p", addr);
    buf[size - 1] = 0;
 }
diff --git a/src/gallium/tools/addr2line.sh b/src/gallium/tools/addr2line.sh
new file mode 100755 (executable)
index 0000000..34dec14
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+# This script processes symbols output by Gallium using glibc to human-readable function names
+
+lastbin=
+i=-1
+dir="$(mktemp -d)"
+input="$1"
+
+# Gather all unique addresses for each binary
+sed -nre 's|([^ ]*/[^ ]*)\(\+0x([^)]*).*|\1 \2|p' "$input"|sort|uniq|while read bin addr; do
+       if test "$lastbin" != "$bin"; then
+               ((++i))
+               lastbin="$bin"
+               echo "$bin" > "$dir/$i.addrs.bin"
+       fi
+       echo "$addr" >> "$dir/$i.addrs"
+done
+
+# Construct a sed script to convert hex address to human readable form, and apply it
+for i in "$dir"/*.addrs; do
+       bin="$(<"$i.bin")"
+       addr2line -p -e "$bin" -a -f < "$i"|sed -nre 's@^0x0*([^:]*): ([^?]*)$@s|'"$bin"'(+0x\1)|\2|g@gp'
+       rm -f "$i" "$i.bin"
+done|sed -f - "$input"
+
+rmdir "$dir"