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 // Replace the first frame with the PC because the frame in the 42 // stacktrace might be incorrect. 43 trace_buffer[0] = pc; 44 } 45 46 #ifdef __clang__ 47 #pragma clang diagnostic push 48 #pragma clang diagnostic ignored "-Wframe-larger-than=" 49 #endif 50 void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { 51 CHECK(context); 52 CHECK_GE(max_depth, 2); 53 CONTEXT ctx = *(CONTEXT *)context; 54 STACKFRAME64 stack_frame; 55 memset(&stack_frame, 0, sizeof(stack_frame)); 56 57 InitializeDbgHelpIfNeeded(); 58 59 size = 0; 60 #if defined(_WIN64) 61 int machine_type = IMAGE_FILE_MACHINE_AMD64; 62 stack_frame.AddrPC.Offset = ctx.Rip; 63 stack_frame.AddrFrame.Offset = ctx.Rbp; 64 stack_frame.AddrStack.Offset = ctx.Rsp; 65 #else 66 int machine_type = IMAGE_FILE_MACHINE_I386; 67 stack_frame.AddrPC.Offset = ctx.Eip; 68 stack_frame.AddrFrame.Offset = ctx.Ebp; 69 stack_frame.AddrStack.Offset = ctx.Esp; 70 #endif 71 stack_frame.AddrPC.Mode = AddrModeFlat; 72 stack_frame.AddrFrame.Mode = AddrModeFlat; 73 stack_frame.AddrStack.Mode = AddrModeFlat; 74 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), 75 &stack_frame, &ctx, NULL, SymFunctionTableAccess64, 76 SymGetModuleBase64, NULL) && 77 size < Min(max_depth, kStackTraceMax)) { 78 trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; 79 } 80 } 81 #ifdef __clang__ 82 #pragma clang diagnostic pop 83 #endif 84 #endif // #if !SANITIZER_GO 85 86 #endif // SANITIZER_WINDOWS 87