summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcin Slusarz <marcin.slusarz@gmail.com>2013-02-21 09:02:44 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2013-02-26 07:59:53 +1000
commite21e183059df5975e7086850d1931edb2c1bbd06 (patch)
treea59c4a290183410c0c15bcd37826f842ca030ab6
parente27b2e61632b220ddc36d0d0387581a9f4774f21 (diff)
os: use libunwind to generate backtraces
Libunwind generates backtraces much more reliably than glibc's "backtrace". Before: 0: /opt/xserver/bin/X (0x400000+0x18ce36) [0x58ce36] 1: /opt/xserver/bin/X (xorg_backtrace+0x9) [0x58d119] 2: /opt/xserver/bin/X (0x400000+0x190d69) [0x590d69] 3: /lib64/libpthread.so.0 (0x7fb904268000+0x10a90) [0x7fb904278a90] 4: /lib64/libc.so.6 (ioctl+0x7) [0x7fb902fbf987] 5: /usr/lib64/libdrm.so.2 (drmIoctl+0x28) [0x7fb90405ffa8] 6: /usr/lib64/libdrm.so.2 (drmCommandWrite+0x1b) [0x7fb90406235b] 7: /usr/lib64/libdrm_nouveau.so.2 (nouveau_bo_wait+0x89) [0x7fb902009719] 8: /opt/xserver/lib/xorg/modules/drivers/nouveau_drv.so (0x7fb90220e000+0x76f3) [0x7fb9022156f3] 9: /opt/xserver/lib/xorg/modules/libexa.so (0x7fb9019c7000+0xbae0) [0x7fb9019d2ae0] 10: /opt/xserver/bin/X (0x400000+0x17d2b3) [0x57d2b3] 11: /opt/xserver/bin/X (0x400000+0xc9930) [0x4c9930] 12: /opt/xserver/bin/X (0x400000+0x3a81a) [0x43a81a] 13: /opt/xserver/bin/X (0x400000+0x3d6a1) [0x43d6a1] 14: /opt/xserver/bin/X (0x400000+0x2c2ca) [0x42c2ca] 15: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x7fb902f019b5] 16: /opt/xserver/bin/X (0x400000+0x2c60d) [0x42c60d] 17: ?? [0x0] After: 0: /opt/xserver/bin/X (OsSigHandler+0x39) [0x590d69] 1: /lib64/libpthread.so.0 (__restore_rt+0x0) [0x7fb904278a8f] 2: /lib64/libc.so.6 (ioctl+0x7) [0x7fb902fbf987] 3: /usr/lib64/libdrm.so.2 (drmIoctl+0x28) [0x7fb90405ffa8] 4: /usr/lib64/libdrm.so.2 (drmCommandWrite+0x1b) [0x7fb90406235b] 5: /usr/lib64/libdrm_nouveau.so.2 (nouveau_bo_wait+0x89) [0x7fb902009719] 6: /opt/xserver/lib/xorg/modules/drivers/nouveau_drv.so (nouveau_exa_download_from_screen+0x1a3) [0x7fb9022156f3] 7: /opt/xserver/lib/xorg/modules/libexa.so (exaGetImage+0x1f0) [0x7fb9019d2ae0] 8: /opt/xserver/bin/X (miSpriteGetImage+0x173) [0x57d2b3] 9: /opt/xserver/bin/X (compGetImage+0xb0) [0x4c9930] 10: /opt/xserver/bin/X (ProcGetImage+0x55a) [0x43a81a] 11: /opt/xserver/bin/X (Dispatch+0x341) [0x43d6a1] 12: /opt/xserver/bin/X (main+0x3ba) [0x42c2ca] 13: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x7fb902f019b5] 14: /opt/xserver/bin/X (_start+0x29) [0x42c60d] 15: ? (?+0x29) [0x29] Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Tested-by: Knut Petersen <knut.petersen@t-online.de>
-rw-r--r--configure.ac9
-rw-r--r--include/dix-config.h.in3
-rw-r--r--os/Makefile.am5
-rw-r--r--os/backtrace.c75
4 files changed, 91 insertions, 1 deletions
diff --git a/configure.ac b/configure.ac
index 53335b1d1..8b9cbc913 100644
--- a/configure.ac
+++ b/configure.ac
@@ -308,6 +308,13 @@ AC_CHECK_HEADER([execinfo.h],[
])]
)
+PKG_CHECK_MODULES(LIBUNWIND, libunwind, [HAVE_LIBUNWIND=yes], [HAVE_LIBUNWIND=no])
+if test "x$HAVE_LIBUNWIND" = xyes; then
+ AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
+fi
+AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$HAVE_LIBUNWIND" = xyes])
+
+
dnl ---------------------------------------------------------------------------
dnl Bus options and CPU capabilities. Replaces logic in
dnl hw/xfree86/os-support/bus/Makefile.am, among others.
@@ -1336,7 +1343,7 @@ AC_DEFINE(BIGREQS, 1, [Support BigRequests extension])
if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then
DIX_LIB='$(top_builddir)/dix/dix.O'
- OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS)'
+ OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS) $(DLOPEN_LIBS) $(LIBUNWIND_LIBS)'
else
DIX_LIB='$(top_builddir)/dix/libdix.la'
OS_LIB='$(top_builddir)/os/libos.la'
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index e1cb9eb51..a643dfcc8 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -60,6 +60,9 @@
/* Has backtrace support */
#undef HAVE_BACKTRACE
+/* Has libunwind support */
+#undef HAVE_LIBUNWIND
+
/* Define to 1 if you have the <byteswap.h> header file. */
#undef HAVE_BYTESWAP_H
diff --git a/os/Makefile.am b/os/Makefile.am
index 88914852f..364b6da2d 100644
--- a/os/Makefile.am
+++ b/os/Makefile.am
@@ -34,6 +34,11 @@ if XDMCP
libos_la_SOURCES += $(XDMCP_SRCS)
endif
+if HAVE_LIBUNWIND
+AM_CFLAGS += $(LIBUNWIND_CFLAGS)
+libos_la_LIBADD += $(LIBUNWIND_LIBS)
+endif
+
EXTRA_DIST = $(SECURERPC_SRCS) $(XDMCP_SRCS)
if SPECIAL_DTRACE_OBJECTS
diff --git a/os/backtrace.c b/os/backtrace.c
index daac60cf6..426f9b15b 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -30,6 +30,80 @@
#include <errno.h>
#include <string.h>
+#ifdef HAVE_LIBUNWIND
+
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+
+void
+xorg_backtrace(void)
+{
+ unw_cursor_t cursor;
+ unw_context_t context;
+ unw_word_t off;
+ unw_proc_info_t pip;
+ int ret, i = 0;
+ char procname[256];
+ const char *filename;
+ Dl_info dlinfo;
+
+ pip.unwind_info = NULL;
+ ret = unw_getcontext(&context);
+ if (ret) {
+ ErrorFSigSafe("unw_getcontext failed: %s [%d]\n", unw_strerror(ret),
+ ret);
+ return;
+ }
+
+ ret = unw_init_local(&cursor, &context);
+ if (ret) {
+ ErrorFSigSafe("unw_init_local failed: %s [%d]\n", unw_strerror(ret),
+ ret);
+ return;
+ }
+
+ ErrorFSigSafe("\n");
+ ErrorFSigSafe("Backtrace:\n");
+ ret = unw_step(&cursor);
+ while (ret > 0) {
+ ret = unw_get_proc_info(&cursor, &pip);
+ if (ret) {
+ ErrorFSigSafe("unw_get_proc_info failed: %s [%d]\n",
+ unw_strerror(ret), ret);
+ break;
+ }
+
+ ret = unw_get_proc_name(&cursor, procname, 256, &off);
+ if (ret && ret != -UNW_ENOMEM) {
+ if (ret != -UNW_EUNSPEC)
+ ErrorFSigSafe("unw_get_proc_name failed: %s [%d]\n",
+ unw_strerror(ret), ret);
+ procname[0] = '?';
+ procname[1] = 0;
+ }
+
+ if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
+ *dlinfo.dli_fname)
+ filename = dlinfo.dli_fname;
+ else
+ filename = "?";
+
+ ErrorFSigSafe("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
+ ret == -UNW_ENOMEM ? "..." : "", (int)off,
+ (void *)(pip.start_ip + off));
+
+ ret = unw_step(&cursor);
+ if (ret < 0)
+ ErrorFSigSafe("unw_step failed: %s [%d]\n", unw_strerror(ret), ret);
+ }
+ ErrorFSigSafe("\n");
+}
+#else /* HAVE_LIBUNWIND */
#ifdef HAVE_BACKTRACE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -246,3 +320,4 @@ xorg_backtrace(void)
#endif
#endif
+#endif