summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac24
-rw-r--r--src/gallium/Automake.inc1
-rw-r--r--src/gallium/auxiliary/util/u_debug_stack.c91
-rw-r--r--src/gallium/auxiliary/util/u_debug_stack.h15
4 files changed, 129 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 70885fb9a6b..016e38fb599 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1025,6 +1025,30 @@ AC_SUBST([LLVM_LIBS])
AC_SUBST([LLVM_LDFLAGS])
AC_SUBST([LLVM_INCLUDEDIR])
+dnl
+dnl libunwind
+dnl
+AC_ARG_ENABLE([libunwind],
+ [AS_HELP_STRING([--enable-libunwind],
+ [Use libunwind for backtracing (default: auto)])],
+ [LIBUNWIND="$enableval"],
+ [LIBUNWIND="auto"])
+
+PKG_CHECK_MODULES(LIBUNWIND, libunwind, [HAVE_LIBUNWIND=yes], [HAVE_LIBUNWIND=no])
+if test "x$LIBUNWIND" = "xauto"; then
+ LIBUNWIND="$HAVE_LIBUNWIND"
+fi
+
+if test "x$LIBUNWIND" = "xyes"; then
+ if test "x$HAVE_LIBUNWIND" != "xyes"; then
+ AC_MSG_ERROR([libunwind requested but not installed.])
+ fi
+ AC_DEFINE(HAVE_LIBUNWIND, 1, [Have libunwind support])
+fi
+
+AM_CONDITIONAL(HAVE_LIBUNWIND, [test "x$LIBUNWIND" = xyes])
+
+
dnl Options for APIs
AC_ARG_ENABLE([opengl],
[AS_HELP_STRING([--disable-opengl],
diff --git a/src/gallium/Automake.inc b/src/gallium/Automake.inc
index a01fa540531..48b5a440674 100644
--- a/src/gallium/Automake.inc
+++ b/src/gallium/Automake.inc
@@ -46,6 +46,7 @@ GALLIUM_TARGET_CFLAGS = \
GALLIUM_COMMON_LIB_DEPS = \
-lm \
+ $(LIBUNWIND_LIBS) \
$(LIBSENSORS_LIBS) \
$(CLOCK_LIB) \
$(PTHREAD_LIBS) \
diff --git a/src/gallium/auxiliary/util/u_debug_stack.c b/src/gallium/auxiliary/util/u_debug_stack.c
index f941234de20..cf05f13ddd0 100644
--- a/src/gallium/auxiliary/util/u_debug_stack.c
+++ b/src/gallium/auxiliary/util/u_debug_stack.c
@@ -36,6 +36,95 @@
#include "u_debug_symbol.h"
#include "u_debug_stack.h"
+#if defined(HAVE_LIBUNWIND)
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+
+void
+debug_backtrace_capture(struct debug_stack_frame *backtrace,
+ unsigned start_frame,
+ unsigned nr_frames)
+{
+ unw_cursor_t cursor;
+ unw_context_t context;
+ unw_proc_info_t pip;
+ unsigned i = 0;
+ int ret;
+
+ pip.unwind_info = NULL;
+
+ unw_getcontext(&context);
+ unw_init_local(&cursor, &context);
+
+ while ((start_frame > 0) && (unw_step(&cursor) > 0))
+ start_frame--;
+
+ while (unw_step(&cursor) > 0) {
+ char procname[256];
+ const char *filename;
+ unw_word_t off;
+ Dl_info dlinfo;
+
+ unw_get_proc_info(&cursor, &pip);
+
+ ret = unw_get_proc_name(&cursor, procname, 256, &off);
+ if (ret && ret != -UNW_ENOMEM) {
+ procname[0] = '?';
+ procname[1] = 0;
+ }
+
+ if (dladdr((void *)(uintptr_t)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
+ *dlinfo.dli_fname)
+ filename = dlinfo.dli_fname;
+ else
+ filename = "?";
+
+ snprintf(backtrace[i].buf, sizeof(backtrace[i].buf),
+ "%u: %s (%s%s+0x%x) [%p]", i, filename, procname,
+ ret == -UNW_ENOMEM ? "..." : "", (int)off,
+ (void *)(uintptr_t)(pip.start_ip + off));
+
+ i++;
+ }
+
+ while (i < nr_frames) {
+ backtrace[i].buf[0] = '\0';
+ i++;
+ }
+}
+
+void
+debug_backtrace_dump(const struct debug_stack_frame *backtrace,
+ unsigned nr_frames)
+{
+ unsigned i;
+
+ for (i = 0; i < nr_frames; ++i) {
+ if (backtrace[i].buf[0] == '\0')
+ break;
+ debug_printf("\t%s\n", backtrace[i].buf);
+ }
+}
+
+void
+debug_backtrace_print(FILE *f,
+ const struct debug_stack_frame *backtrace,
+ unsigned nr_frames)
+{
+ unsigned i;
+
+ for (i = 0; i < nr_frames; ++i) {
+ if (backtrace[i].buf[0] == '\0')
+ break;
+ fprintf(f, "\t%s\n", backtrace[i].buf);
+ }
+}
+
+#else /* ! HAVE_LIBUNWIND */
+
#if defined(PIPE_OS_WINDOWS)
#include <windows.h>
#endif
@@ -179,3 +268,5 @@ debug_backtrace_print(FILE *f,
fprintf(f, "%s\n", symbol);
}
}
+
+#endif /* HAVE_LIBUNWIND */
diff --git a/src/gallium/auxiliary/util/u_debug_stack.h b/src/gallium/auxiliary/util/u_debug_stack.h
index 04eba08f89a..0effcbe5259 100644
--- a/src/gallium/auxiliary/util/u_debug_stack.h
+++ b/src/gallium/auxiliary/util/u_debug_stack.h
@@ -30,6 +30,11 @@
#include <stdio.h>
+#ifdef HAVE_LIBUNWIND
+#define UNW_LOCAL_ONLY
+#include <libunwind.h>
+#endif
+
/**
* @file
* Stack backtracing.
@@ -46,15 +51,21 @@ extern "C" {
/**
* Represent a frame from a stack backtrace.
*
- * XXX: Do not change this.
+#if defined(PIPE_OS_WINDOWS) && !defined(HAVE_LIBUNWIND)
+ * XXX: Do not change this. (passed to Windows' CaptureStackBackTrace())
+#endif
*
* TODO: This should be refactored as a void * typedef.
*/
struct debug_stack_frame
{
+#ifdef HAVE_LIBUNWIND
+ char buf[128];
+#else
const void *function;
+#endif
};
-
+
void
debug_backtrace_capture(struct debug_stack_frame *backtrace,