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 24using namespace __sanitizer; 25 26#if !SANITIZER_GO 27void 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 42void 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