[PATCH] os: use libunwind to generate backtraces
Marcin Slusarz
marcin.slusarz at gmail.com
Sat Feb 16 07:45:54 PST 2013
Libunwind generates backtraces much more reliably than glibc's "backtrace".
Signed-off-by: Marcin Slusarz <marcin.slusarz at gmail.com>
---
configure.ac | 7 +++++
include/dix-config.h.in | 3 +++
os/Makefile.am | 5 ++++
os/backtrace.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 85 insertions(+)
diff --git a/configure.ac b/configure.ac
index 9415a54..4a292da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -309,6 +309,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.
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 578f249..5102263 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 8891485..364b6da 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 daac60c..02aeb03 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -30,6 +30,75 @@
#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: %d\n", ret);
+ return;
+ }
+
+ ret = unw_init_local(&cursor, &context);
+ if (ret) {
+ ErrorFSigSafe("unw_init_local: %d\n", 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: %d\n", 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: %d\n", 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: %d\n", ret);
+ }
+ ErrorFSigSafe("\n");
+}
+#else
#ifdef HAVE_BACKTRACE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
@@ -246,3 +315,4 @@ xorg_backtrace(void)
#endif
#endif
+#endif
--
1.8.1
More information about the xorg-devel
mailing list