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 SANITIZER_WINDOWS64 61 # if SANITIZER_ARM64 62 int machine_type = IMAGE_FILE_MACHINE_ARM64; 63 stack_frame.AddrPC.Offset = ctx.Pc; 64 stack_frame.AddrFrame.Offset = ctx.Fp; 65 stack_frame.AddrStack.Offset = ctx.Sp; 66 # else 67 int machine_type = IMAGE_FILE_MACHINE_AMD64; 68 stack_frame.AddrPC.Offset = ctx.Rip; 69 stack_frame.AddrFrame.Offset = ctx.Rbp; 70 stack_frame.AddrStack.Offset = ctx.Rsp; 71 # endif 72 # else 73 int machine_type = IMAGE_FILE_MACHINE_I386; 74 stack_frame.AddrPC.Offset = ctx.Eip; 75 stack_frame.AddrFrame.Offset = ctx.Ebp; 76 stack_frame.AddrStack.Offset = ctx.Esp; 77 # endif 78 stack_frame.AddrPC.Mode = AddrModeFlat; 79 stack_frame.AddrFrame.Mode = AddrModeFlat; 80 stack_frame.AddrStack.Mode = AddrModeFlat; 81 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), 82 &stack_frame, &ctx, NULL, SymFunctionTableAccess64, 83 SymGetModuleBase64, NULL) && 84 size < Min(max_depth, kStackTraceMax)) { 85 trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; 86 } 87 } 88 # ifdef __clang__ 89 # pragma clang diagnostic pop 90 # endif 91 # endif // #if !SANITIZER_GO 92 93 #endif // SANITIZER_WINDOWS 94