//===-- sanitizer_unwind_win.cpp ------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// Sanitizer unwind Windows specific functions. // //===----------------------------------------------------------------------===// #include "sanitizer_platform.h" #if SANITIZER_WINDOWS #define WIN32_LEAN_AND_MEAN #define NOGDI #include #include "sanitizer_dbghelp.h" // for StackWalk64 #include "sanitizer_stacktrace.h" #include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded using namespace __sanitizer; #if !SANITIZER_GO void BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { CHECK_GE(max_depth, 2); // FIXME: CaptureStackBackTrace might be too slow for us. // FIXME: Compare with StackWalk64. // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax), (void **)&trace_buffer[0], 0); if (size == 0) return; // Skip the RTL frames by searching for the PC in the stacktrace. uptr pc_location = LocatePcInTrace(pc); PopStackFrames(pc_location); // Replace the first frame with the PC because the frame in the // stacktrace might be incorrect. trace_buffer[0] = pc; } #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wframe-larger-than=" #endif void BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { CHECK(context); CHECK_GE(max_depth, 2); CONTEXT ctx = *(CONTEXT *)context; STACKFRAME64 stack_frame; memset(&stack_frame, 0, sizeof(stack_frame)); InitializeDbgHelpIfNeeded(); size = 0; # if SANITIZER_WINDOWS64 # if SANITIZER_ARM64 int machine_type = IMAGE_FILE_MACHINE_ARM64; stack_frame.AddrPC.Offset = ctx.Pc; stack_frame.AddrFrame.Offset = ctx.Fp; stack_frame.AddrStack.Offset = ctx.Sp; # else int machine_type = IMAGE_FILE_MACHINE_AMD64; stack_frame.AddrPC.Offset = ctx.Rip; stack_frame.AddrFrame.Offset = ctx.Rbp; stack_frame.AddrStack.Offset = ctx.Rsp; # endif # else # if SANITIZER_ARM int machine_type = IMAGE_FILE_MACHINE_ARM; stack_frame.AddrPC.Offset = ctx.Pc; stack_frame.AddrFrame.Offset = ctx.R11; stack_frame.AddrStack.Offset = ctx.Sp; # else int machine_type = IMAGE_FILE_MACHINE_I386; stack_frame.AddrPC.Offset = ctx.Eip; stack_frame.AddrFrame.Offset = ctx.Ebp; stack_frame.AddrStack.Offset = ctx.Esp; # endif # endif stack_frame.AddrPC.Mode = AddrModeFlat; stack_frame.AddrFrame.Mode = AddrModeFlat; stack_frame.AddrStack.Mode = AddrModeFlat; while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), &stack_frame, &ctx, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL) && size < Min(max_depth, kStackTraceMax)) { trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; } } # ifdef __clang__ # pragma clang diagnostic pop # endif # endif // #if !SANITIZER_GO #endif // SANITIZER_WINDOWS