xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/sanitizer_common/sanitizer_unwind_win.cc (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 //===-- sanitizer_unwind_win.cc -------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 /// Sanitizer unwind Windows specific functions.
9 //
10 //===----------------------------------------------------------------------===//
11 
12 #include "sanitizer_platform.h"
13 #if SANITIZER_WINDOWS
14 
15 #define WIN32_LEAN_AND_MEAN
16 #define NOGDI
17 #include <windows.h>
18 
19 #include "sanitizer_dbghelp.h"  // for StackWalk64
20 #include "sanitizer_stacktrace.h"
21 #include "sanitizer_symbolizer.h"  // for InitializeDbgHelpIfNeeded
22 
23 using namespace __sanitizer;
24 
25 #if !SANITIZER_GO
SlowUnwindStack(uptr pc,u32 max_depth)26 void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) {
27   CHECK_GE(max_depth, 2);
28   // FIXME: CaptureStackBackTrace might be too slow for us.
29   // FIXME: Compare with StackWalk64.
30   // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
31   size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax),
32     (void **)&trace_buffer[0], 0);
33   if (size == 0)
34     return;
35 
36   // Skip the RTL frames by searching for the PC in the stacktrace.
37   uptr pc_location = LocatePcInTrace(pc);
38   PopStackFrames(pc_location);
39 }
40 
SlowUnwindStackWithContext(uptr pc,void * context,u32 max_depth)41 void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
42   u32 max_depth) {
43   CONTEXT ctx = *(CONTEXT *)context;
44   STACKFRAME64 stack_frame;
45   memset(&stack_frame, 0, sizeof(stack_frame));
46 
47   InitializeDbgHelpIfNeeded();
48 
49   size = 0;
50 #if defined(_WIN64)
51   int machine_type = IMAGE_FILE_MACHINE_AMD64;
52   stack_frame.AddrPC.Offset = ctx.Rip;
53   stack_frame.AddrFrame.Offset = ctx.Rbp;
54   stack_frame.AddrStack.Offset = ctx.Rsp;
55 #else
56   int machine_type = IMAGE_FILE_MACHINE_I386;
57   stack_frame.AddrPC.Offset = ctx.Eip;
58   stack_frame.AddrFrame.Offset = ctx.Ebp;
59   stack_frame.AddrStack.Offset = ctx.Esp;
60 #endif
61   stack_frame.AddrPC.Mode = AddrModeFlat;
62   stack_frame.AddrFrame.Mode = AddrModeFlat;
63   stack_frame.AddrStack.Mode = AddrModeFlat;
64   while (StackWalk64(machine_type, GetCurrentProcess(), GetCurrentThread(),
65     &stack_frame, &ctx, NULL, SymFunctionTableAccess64,
66     SymGetModuleBase64, NULL) &&
67     size < Min(max_depth, kStackTraceMax)) {
68     trace_buffer[size++] = (uptr)stack_frame.AddrPC.Offset;
69   }
70 }
71 #endif  // #if !SANITIZER_GO
72 
73 #endif  // SANITIZER_WINDOWS
74