summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common/sanitizer_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sanitizer_common/sanitizer_win.cc')
-rw-r--r--lib/sanitizer_common/sanitizer_win.cc30
1 files changed, 27 insertions, 3 deletions
diff --git a/lib/sanitizer_common/sanitizer_win.cc b/lib/sanitizer_common/sanitizer_win.cc
index da24df684..b7402ee51 100644
--- a/lib/sanitizer_common/sanitizer_win.cc
+++ b/lib/sanitizer_common/sanitizer_win.cc
@@ -17,9 +17,10 @@
#define WIN32_LEAN_AND_MEAN
#define NOGDI
-#include <stdlib.h>
-#include <io.h>
#include <windows.h>
+#include <dbghelp.h>
+#include <io.h>
+#include <stdlib.h>
#include "sanitizer_common.h"
#include "sanitizer_libc.h"
@@ -449,7 +450,30 @@ void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
void StackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
uptr max_depth) {
- UNREACHABLE("no signal context on windows");
+ CONTEXT ctx = *(CONTEXT *)context;
+ STACKFRAME64 stack_frame;
+ memset(&stack_frame, 0, sizeof(stack_frame));
+ size = 0;
+#if defined(_WIN64)
+ int machine_type = IMAGE_FILE_MACHINE_AMD64;
+ stack_frame.AddrPC.Offset = ctx.Rip;
+ stack_frame.AddrFrame.Offset = ctx.Rbp;
+ stack_frame.AddrStack.Offset = ctx.Rsp;
+#else
+ int machine_type = IMAGE_FILE_MACHINE_I386;
+ stack_frame.AddrPC.Offset = ctx.Eip;
+ stack_frame.AddrFrame.Offset = ctx.Ebp;
+ stack_frame.AddrStack.Offset = ctx.Esp;
+#endif
+ stack_frame.AddrPC.Mode = AddrModeFlat;
+ stack_frame.AddrFrame.Mode = AddrModeFlat;
+ stack_frame.AddrStack.Mode = AddrModeFlat;
+ while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
+ &stack_frame, &ctx, NULL, &SymFunctionTableAccess64,
+ &SymGetModuleBase64, NULL) &&
+ size < Min(max_depth, kStackTraceMax)) {
+ trace[size++] = (uptr)stack_frame.AddrPC.Offset;
+ }
}
void MaybeOpenReportFile() {