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
);
42 void BufferedStackTrace::UnwindSlow(uptr pc
, void *context
, u32 max_depth
) {
44 CHECK_GE(max_depth
, 2);
45 CONTEXT ctx
= *(CONTEXT
*)context
;
46 STACKFRAME64 stack_frame
;
47 memset(&stack_frame
, 0, sizeof(stack_frame
));
49 InitializeDbgHelpIfNeeded();
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
;
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
;
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
;
73 #endif // #if !SANITIZER_GO
75 #endif // SANITIZER_WINDOWS