1 //===-- sanitizer_unwind_win.cpp ------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 /// Sanitizer unwind Windows specific functions.
11 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
16 #define WIN32_LEAN_AND_MEAN
20 #include "sanitizer_dbghelp.h" // for StackWalk64
21 #include "sanitizer_stacktrace.h"
22 #include "sanitizer_symbolizer.h" // for InitializeDbgHelpIfNeeded
24 using namespace __sanitizer
;
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);
37 // Skip the RTL frames by searching for the PC in the stacktrace.
38 uptr pc_location
= LocatePcInTrace(pc
);
39 PopStackFrames(pc_location
);
41 // Replace the first frame with the PC because the frame in the
42 // stacktrace might be incorrect.
47 #pragma clang diagnostic push
48 #pragma clang diagnostic ignored "-Wframe-larger-than="
50 void BufferedStackTrace::UnwindSlow(uptr pc
, void *context
, u32 max_depth
) {
52 CHECK_GE(max_depth
, 2);
53 CONTEXT ctx
= *(CONTEXT
*)context
;
54 STACKFRAME64 stack_frame
;
55 memset(&stack_frame
, 0, sizeof(stack_frame
));
57 InitializeDbgHelpIfNeeded();
60 # if SANITIZER_WINDOWS64
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
;
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
;
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
;
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
;
89 # pragma clang diagnostic pop
91 # endif // #if !SANITIZER_GO
93 #endif // SANITIZER_WINDOWS