gallium/util: libunwind support
It's kinda sad that (a) we don't have debug_backtrace support on !X86 and that (b) we re-invent our own crude backtrace support in the first place. If available, use libunwind instead. The backtrace format is based on what xserver and weston use, since it is nice not to have to figure out a different format. Signed-off-by: Rob Clark <robdclark@gmail.com> Acked-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
This commit is contained in:
parent
c3c884c49c
commit
70c272004f
24
configure.ac
24
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],
|
||||
|
|
|
@ -46,6 +46,7 @@ GALLIUM_TARGET_CFLAGS = \
|
|||
|
||||
GALLIUM_COMMON_LIB_DEPS = \
|
||||
-lm \
|
||||
$(LIBUNWIND_LIBS) \
|
||||
$(LIBSENSORS_LIBS) \
|
||||
$(CLOCK_LIB) \
|
||||
$(PTHREAD_LIBS) \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue