1353944Sdim//===-- sanitizer_unwind_win.cpp ------------------------------------------===// 2353944Sdim// 3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353944Sdim// See https://llvm.org/LICENSE.txt for license information. 5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353944Sdim// 7353944Sdim//===----------------------------------------------------------------------===// 8353944Sdim// 9353944Sdim/// Sanitizer unwind Windows specific functions. 10353944Sdim// 11353944Sdim//===----------------------------------------------------------------------===// 12353944Sdim 13353944Sdim#include "sanitizer_platform.h" 14353944Sdim#if SANITIZER_WINDOWS 15353944Sdim 16353944Sdim#define WIN32_LEAN_AND_MEAN 17353944Sdim#define NOGDI 18353944Sdim#include <windows.h> 19353944Sdim 20353944Sdim#include "sanitizer_dbghelp.h" // for StackWalk64 21353944Sdim#include "sanitizer_stacktrace.h" 22353944Sdim#include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded 23353944Sdim 24353944Sdimusing namespace __sanitizer; 25353944Sdim 26353944Sdim#if !SANITIZER_GO 27353944Sdimvoid BufferedStackTrace::UnwindSlow(uptr pc, u32 max_depth) { 28353944Sdim CHECK_GE(max_depth, 2); 29353944Sdim // FIXME: CaptureStackBackTrace might be too slow for us. 30353944Sdim // FIXME: Compare with StackWalk64. 31353944Sdim // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc 32353944Sdim size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax), 33353944Sdim (void **)&trace_buffer[0], 0); 34353944Sdim if (size == 0) 35353944Sdim return; 36353944Sdim 37353944Sdim // Skip the RTL frames by searching for the PC in the stacktrace. 38353944Sdim uptr pc_location = LocatePcInTrace(pc); 39353944Sdim PopStackFrames(pc_location); 40353944Sdim} 41353944Sdim 42353944Sdimvoid BufferedStackTrace::UnwindSlow(uptr pc, void *context, u32 max_depth) { 43353944Sdim CHECK(context); 44353944Sdim CHECK_GE(max_depth, 2); 45353944Sdim CONTEXT ctx = *(CONTEXT *)context; 46353944Sdim STACKFRAME64 stack_frame; 47353944Sdim memset(&stack_frame, 0, sizeof(stack_frame)); 48353944Sdim 49353944Sdim InitializeDbgHelpIfNeeded(); 50353944Sdim 51353944Sdim size = 0; 52353944Sdim#if defined(_WIN64) 53353944Sdim int machine_type = IMAGE_FILE_MACHINE_AMD64; 54353944Sdim stack_frame.AddrPC.Offset = ctx.Rip; 55353944Sdim stack_frame.AddrFrame.Offset = ctx.Rbp; 56353944Sdim stack_frame.AddrStack.Offset = ctx.Rsp; 57353944Sdim#else 58353944Sdim int machine_type = IMAGE_FILE_MACHINE_I386; 59353944Sdim stack_frame.AddrPC.Offset = ctx.Eip; 60353944Sdim stack_frame.AddrFrame.Offset = ctx.Ebp; 61353944Sdim stack_frame.AddrStack.Offset = ctx.Esp; 62353944Sdim#endif 63353944Sdim stack_frame.AddrPC.Mode = AddrModeFlat; 64353944Sdim stack_frame.AddrFrame.Mode = AddrModeFlat; 65353944Sdim stack_frame.AddrStack.Mode = AddrModeFlat; 66353944Sdim while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(), 67353944Sdim &stack_frame, &ctx, NULL, SymFunctionTableAccess64, 68353944Sdim SymGetModuleBase64, NULL) && 69353944Sdim size < Min(max_depth, kStackTraceMax)) { 70353944Sdim trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset; 71353944Sdim } 72353944Sdim} 73353944Sdim#endif // #if !SANITIZER_GO 74353944Sdim 75353944Sdim#endif // SANITIZER_WINDOWS 76