1 //===-- sanitizer_unwind_win.cc -------------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 /// Sanitizer unwind Windows specific functions. 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include "sanitizer_platform.h" 13 #if SANITIZER_WINDOWS 14 15 #define WIN32_LEAN_AND_MEAN 16 #define NOGDI 17 #include <windows.h> 18 19 #include "sanitizer_dbghelp.h" // for StackWalk64 20 #include "sanitizer_stacktrace.h" 21 #include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded 22 23 using namespace __sanitizer; 24 25 #if !SANITIZER_GO 26 void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) { 27 CHECK_GE(max_depth, 2); 28 // FIXME: CaptureStackBackTrace might be too slow for us. 29 // FIXME: Compare with StackWalk64. 30 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 31 size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax), 32 (void **)&trace_buffer[0], 0); 33 if (size == 0) 34 return; 35 36 // Skip the RTL frames by searching for the PC in the stacktrace. 37 uptr pc_location = LocatePcInTrace(pc); 38 PopStackFrames(pc_location); 39 } 40 41 void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context, 42 u32 max_depth) { 43 CONTEXT ctx = *(CONTEXT *)context; 44 STACKFRAME64 stack_frame; 45 memset(&stack_frame, 0, sizeof(stack_frame)); 46 47 InitializeDbgHelpIfNeeded(); 48 49 size = 0; 50 #if defined(_WIN64) 51 int machine_type = IMAGE_FILE_MACHINE_AMD64; 52 stack_frame.AddrPC.Offset = ctx.Rip; 53 stack_frame.AddrFrame.Offset = ctx.Rbp; 54 stack_frame.AddrStack.Offset = ctx.Rsp; 55 #else 56 int machine_type = IMAGE_FILE_MACHINE_I386; 57 stack_frame.AddrPC.Offset = ctx.Eip; 58 stack_frame.AddrFrame.Offset = ctx.Ebp; 59 stack_frame.AddrStack.Offset = ctx.Esp; 60 #endif 61 stack_frame.AddrPC.Mode = AddrModeFlat; 62 stack_frame.AddrFrame.Mode = AddrModeFlat; 63 stack_frame.AddrStack.Mode = AddrModeFlat; 64 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), 65 &stack_frame, &ctx, NULL, SymFunctionTableAccess64, 66 SymGetModuleBase64, NULL) && 67 size < Min(max_depth, kStackTraceMax)) { 68 trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; 69 } 70 } 71 #endif // #if !SANITIZER_GO 72 73 #endif // SANITIZER_WINDOWS 74