diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/Automake.inc | 1 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_debug_stack.c | 91 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_debug_stack.h | 15 |
3 files changed, 105 insertions, 2 deletions
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, |