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