diff options
author | José Fonseca <[email protected]> | 2013-06-24 13:37:45 +0100 |
---|---|---|
committer | José Fonseca <[email protected]> | 2013-06-25 18:41:59 +0100 |
commit | a26f834a39063b68466db62b154c6fe817f06008 (patch) | |
tree | 6b57eee487e7f4c0a885511f03e9b452ed50fa95 | |
parent | 29dacd98038efa5b5056464167cb30290c41a090 (diff) |
util/debug: Make debug_backtrace_capture work for 64bit windows.
Rely on Windows' CaptureStackBackTrace to do the grunt work.
Reviewed-by: Brian Paul <[email protected]>
-rw-r--r-- | src/gallium/auxiliary/util/u_debug_stack.c | 56 | ||||
-rw-r--r-- | src/gallium/auxiliary/util/u_debug_stack.h | 7 |
2 files changed, 61 insertions, 2 deletions
diff --git a/src/gallium/auxiliary/util/u_debug_stack.c b/src/gallium/auxiliary/util/u_debug_stack.c index 50a248a979f..68961d3510e 100644 --- a/src/gallium/auxiliary/util/u_debug_stack.c +++ b/src/gallium/auxiliary/util/u_debug_stack.c @@ -36,7 +36,17 @@ #include "u_debug_symbol.h" #include "u_debug_stack.h" +#if defined(PIPE_OS_WINDOWS) +#include <windows.h> +#endif + +/** + * Capture stack backtrace. + * + * NOTE: The implementation of this function is quite big, but it is important not to + * break it down in smaller functions to avoid adding new frames to the calling stack. + */ void debug_backtrace_capture(struct debug_stack_frame *backtrace, unsigned start_frame, @@ -45,8 +55,50 @@ debug_backtrace_capture(struct debug_stack_frame *backtrace, const void **frame_pointer = NULL; unsigned i = 0; - if(!nr_frames) + if (!nr_frames) { return; + } + + /* + * On Windows try obtaining the stack backtrace via CaptureStackBackTrace. + * + * It works reliably both for x86 for x86_64. + */ +#if defined(PIPE_OS_WINDOWS) + { + typedef USHORT (WINAPI *PFNCAPTURESTACKBACKTRACE)(ULONG, ULONG, PVOID *, PULONG); + static PFNCAPTURESTACKBACKTRACE pfnCaptureStackBackTrace = NULL; + + if (!pfnCaptureStackBackTrace) { + static HMODULE hModule = NULL; + if (!hModule) { + hModule = LoadLibraryA("kernel32"); + assert(hModule); + } + if (hModule) { + pfnCaptureStackBackTrace = (PFNCAPTURESTACKBACKTRACE)GetProcAddress(hModule, + "RtlCaptureStackBackTrace"); + } + } + if (pfnCaptureStackBackTrace) { + /* + * Skip this (debug_backtrace_capture) function's frame. + */ + + start_frame += 1; + + assert(start_frame + nr_frames < 63); + i = pfnCaptureStackBackTrace(start_frame, nr_frames, (PVOID *) &backtrace->function, NULL); + + /* Pad remaing requested frames with NULL */ + while (i < nr_frames) { + backtrace[i++].function = NULL; + } + + return; + } + } +#endif #if defined(PIPE_CC_GCC) frame_pointer = ((const void **)__builtin_frame_address(1)); @@ -86,7 +138,7 @@ debug_backtrace_capture(struct debug_stack_frame *backtrace, #else (void) frame_pointer; #endif - + while(nr_frames) { backtrace[i++].function = NULL; --nr_frames; diff --git a/src/gallium/auxiliary/util/u_debug_stack.h b/src/gallium/auxiliary/util/u_debug_stack.h index f50f04e0f7b..b1848ddefa8 100644 --- a/src/gallium/auxiliary/util/u_debug_stack.h +++ b/src/gallium/auxiliary/util/u_debug_stack.h @@ -42,6 +42,13 @@ extern "C" { #endif +/** + * Represent a frame from a stack backtrace. + * + * XXX: Do not change this. + * + * TODO: This should be refactored as a void * typedef. + */ struct debug_stack_frame { const void *function; |