106 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9/// Sanitizer unwind Windows specific functions.10//11//===----------------------------------------------------------------------===//12 13#include "sanitizer_platform.h"14#if SANITIZER_WINDOWS15 16#define WIN32_LEAN_AND_MEAN17#define NOGDI18#include <windows.h>19 20#include "sanitizer_dbghelp.h" // for StackWalk6421#include "sanitizer_stacktrace.h"22#include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded23 24using namespace __sanitizer;25 26#if !SANITIZER_GO27void 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.inc32 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 the42 // stacktrace might be incorrect.43 trace_buffer[0] = pc;44}45 46#ifdef __clang__47#pragma clang diagnostic push48#pragma clang diagnostic ignored "-Wframe-larger-than="49#endif50void 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_WINDOWS6461# if SANITIZER_ARM6462 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# else67 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# endif72# else73# if SANITIZER_ARM74 int machine_type = IMAGE_FILE_MACHINE_ARM;75 stack_frame.AddrPC.Offset = ctx.Pc;76 stack_frame.AddrFrame.Offset = ctx.R11;77 stack_frame.AddrStack.Offset = ctx.Sp;78# elif SANITIZER_MIPS3279 int machine_type = IMAGE_FILE_MACHINE_R4000;80 stack_frame.AddrPC.Offset = ctx.Fir;81 stack_frame.AddrFrame.Offset = ctx.IntS8;82 stack_frame.AddrStack.Offset = ctx.IntSp;83# else84 int machine_type = IMAGE_FILE_MACHINE_I386;85 stack_frame.AddrPC.Offset = ctx.Eip;86 stack_frame.AddrFrame.Offset = ctx.Ebp;87 stack_frame.AddrStack.Offset = ctx.Esp;88# endif89# endif90 stack_frame.AddrPC.Mode = AddrModeFlat;91 stack_frame.AddrFrame.Mode = AddrModeFlat;92 stack_frame.AddrStack.Mode = AddrModeFlat;93 while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),94 &stack_frame, &ctx, NULL, SymFunctionTableAccess64,95 SymGetModuleBase64, NULL) &&96 size < Min(max_depth, kStackTraceMax)) {97 trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;98 }99}100# ifdef __clang__101# pragma clang diagnostic pop102# endif103# endif // #if !SANITIZER_GO104 105#endif // SANITIZER_WINDOWS106