Home | History | Annotate | Line # | Download | only in sanitizer_common
      1 //===-- sanitizer_unwind_win.cc -------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 /// Sanitizer unwind Windows specific functions.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "sanitizer_platform.h"
     15 #if SANITIZER_WINDOWS
     16 
     17 #define WIN32_LEAN_AND_MEAN
     18 #define NOGDI
     19 #include <windows.h>
     20 
     21 #include "sanitizer_dbghelp.h"  // for StackWalk64
     22 #include "sanitizer_stacktrace.h"
     23 #include "sanitizer_symbolizer.h"  // for InitializeDbgHelpIfNeeded
     24 
     25 using namespace __sanitizer;
     26 
     27 #if !SANITIZER_GO
     28 void BufferedStackTrace::SlowUnwindStack(uptr pc, u32 max_depth) {
     29   CHECK_GE(max_depth, 2);
     30   // FIXME: CaptureStackBackTrace might be too slow for us.
     31   // FIXME: Compare with StackWalk64.
     32   // FIXME: Look at LLVMUnhandledExceptionFilter in Signals.inc
     33   size = CaptureStackBackTrace(1, Min(max_depth, kStackTraceMax),
     34     (void **)&trace_buffer[0], 0);
     35   if (size == 0)
     36     return;
     37 
     38   // Skip the RTL frames by searching for the PC in the stacktrace.
     39   uptr pc_location = LocatePcInTrace(pc);
     40   PopStackFrames(pc_location);
     41 }
     42 
     43 void BufferedStackTrace::SlowUnwindStackWithContext(uptr pc, void *context,
     44   u32 max_depth) {
     45   CONTEXT ctx = *(CONTEXT *)context;
     46   STACKFRAME64 stack_frame;
     47   memset(&stack_frame, 0, sizeof(stack_frame));
     48 
     49   InitializeDbgHelpIfNeeded();
     50 
     51   size = 0;
     52 #if defined(_WIN64)
     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;
     57 #else
     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;
     62 #endif
     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;
     71   }
     72 }
     73 #endif  // #if !SANITIZER_GO
     74 
     75 #endif  // SANITIZER_WINDOWS
     76