1 //===-- sanitizer_unwind_win.cpp ------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// Sanitizer unwind Windows specific functions. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_platform.h" 14 #if SANITIZER_WINDOWS 15 16 #define WIN32_LEAN_AND_MEAN 17 #define NOGDI 18 #include <windows.h> 19 20 #include "sanitizer_dbghelp.h" // for StackWalk64 21 #include "sanitizer_stacktrace.h" 22 #include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded 23 24 using namespace __sanitizer; 25 26 #if !SANITIZER_GO 27 void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { 28 CHECK_GE(max_depth, 2); 29 // FIXME: CaptureStackBackTrace might be too slow for us. 30 // FIXME: Compare with StackWalk64. 31 // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 32 size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax), 33 (void **)&trace_buffer[0], 0); 34 if (size == 0) 35 return; 36 37 // Skip the RTL frames by searching for the PC in the stacktrace. 38 uptr pc_location = LocatePcInTrace(pc); 39 PopStackFrames(pc_location); 40 } 41 42 void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { 43 CHECK(context); 44 CHECK_GE(max_depth, 2); 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