Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===//
      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 // This file is shared between AddressSanitizer and ThreadSanitizer
     11 // run-time libraries.
     12 //===----------------------------------------------------------------------===//
     13 #ifndef SANITIZER_STACKTRACE_H
     14 #define SANITIZER_STACKTRACE_H
     15 
     16 #include "sanitizer_internal_defs.h"
     17 
     18 namespace __sanitizer {
     19 
     20 static const uptr kStackTraceMax = 256;
     21 
     22 #if SANITIZER_LINUX && (defined(__arm__) || \
     23     defined(__powerpc__) || defined(__powerpc64__) || \
     24     defined(__sparc__) || \
     25     defined(__mips__))
     26 #define SANITIZER_CAN_FAST_UNWIND 0
     27 #else
     28 #define SANITIZER_CAN_FAST_UNWIND 1
     29 #endif
     30 
     31 struct StackTrace {
     32   typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer,
     33                                      int out_size);
     34   uptr size;
     35   uptr max_size;
     36   uptr trace[kStackTraceMax];
     37   static void PrintStack(const uptr *addr, uptr size,
     38                          bool symbolize, const char *strip_file_prefix,
     39                          SymbolizeCallback symbolize_callback);
     40   void CopyTo(uptr *dst, uptr dst_size) {
     41     for (uptr i = 0; i < size && i < dst_size; i++)
     42       dst[i] = trace[i];
     43     for (uptr i = size; i < dst_size; i++)
     44       dst[i] = 0;
     45   }
     46 
     47   void CopyFrom(uptr *src, uptr src_size) {
     48     size = src_size;
     49     if (size > kStackTraceMax) size = kStackTraceMax;
     50     for (uptr i = 0; i < size; i++) {
     51       trace[i] = src[i];
     52     }
     53   }
     54 
     55   void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom);
     56   void SlowUnwindStack(uptr pc, uptr max_depth);
     57 
     58   void PopStackFrames(uptr count);
     59 
     60   static uptr GetCurrentPc();
     61   static uptr GetPreviousInstructionPc(uptr pc);
     62 
     63   static uptr CompressStack(StackTrace *stack,
     64                             u32 *compressed, uptr size);
     65   static void UncompressStack(StackTrace *stack,
     66                               u32 *compressed, uptr size);
     67 };
     68 
     69 
     70 const char *StripPathPrefix(const char *filepath,
     71                             const char *strip_file_prefix);
     72 
     73 void GetStackTrace(StackTrace *stack, uptr max_s, uptr pc, uptr bp,
     74                    uptr stack_top, uptr stack_bottom, bool fast);
     75 
     76 }  // namespace __sanitizer
     77 
     78 // Use this macro if you want to print stack trace with the caller
     79 // of the current function in the top frame.
     80 #define GET_CALLER_PC_BP_SP \
     81   uptr bp = GET_CURRENT_FRAME();              \
     82   uptr pc = GET_CALLER_PC();                  \
     83   uptr local_stack;                           \
     84   uptr sp = (uptr)&local_stack
     85 
     86 // Use this macro if you want to print stack trace with the current
     87 // function in the top frame.
     88 #define GET_CURRENT_PC_BP_SP \
     89   uptr bp = GET_CURRENT_FRAME();              \
     90   uptr pc = StackTrace::GetCurrentPc();   \
     91   uptr local_stack;                           \
     92   uptr sp = (uptr)&local_stack
     93 
     94 
     95 #endif  // SANITIZER_STACKTRACE_H
     96