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.
46 void BufferedStackTrace::UnwindSlow(uptr pc
, void *context
, u32 max_depth
) {
48 CHECK_GE(max_depth
, 2);
49 CONTEXT ctx
= *(CONTEXT
*)context
;
50 STACKFRAME64 stack_frame
;
51 memset(&stack_frame
, 0, sizeof(stack_frame
));
53 InitializeDbgHelpIfNeeded();
57 int machine_type
= IMAGE_FILE_MACHINE_AMD64
;
58 stack_frame
.AddrPC
.Offset
= ctx
.Rip
;
59 stack_frame
.AddrFrame
.Offset
= ctx
.Rbp
;
60 stack_frame
.AddrStack
.Offset
= ctx
.Rsp
;
62 int machine_type
= IMAGE_FILE_MACHINE_I386
;
63 stack_frame
.AddrPC
.Offset
= ctx
.Eip
;
64 stack_frame
.AddrFrame
.Offset
= ctx
.Ebp
;
65 stack_frame
.AddrStack
.Offset
= ctx
.Esp
;
67 stack_frame
.AddrPC
.Mode
= AddrModeFlat
;
68 stack_frame
.AddrFrame
.Mode
= AddrModeFlat
;
69 stack_frame
.AddrStack
.Mode
= AddrModeFlat
;
70 while (StackWalk64(machine_type
, GetCurrentProcess(), GetCurrentThread(),
71 &stack_frame
, &ctx
, NULL
, SymFunctionTableAccess64
,
72 SymGetModuleBase64
, NULL
) &&
73 size
< Min(max_depth
, kStackTraceMax
)) {
74 trace_buffer
[size
++] = (uptr
)stack_frame
.AddrPC
.Offset
;
77 #endif // #if !SANITIZER_GO
79 #endif // SANITIZER_WINDOWS