sanitizer_stacktrace.h revision 276789
1245614Sandrew//===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===// 2245614Sandrew// 3245614Sandrew// The LLVM Compiler Infrastructure 4245614Sandrew// 5245614Sandrew// This file is distributed under the University of Illinois Open Source 6245614Sandrew// License. See LICENSE.TXT for details. 7245614Sandrew// 8245614Sandrew//===----------------------------------------------------------------------===// 9245614Sandrew// 10245614Sandrew// This file is shared between AddressSanitizer and ThreadSanitizer 11245614Sandrew// run-time libraries. 12245614Sandrew//===----------------------------------------------------------------------===// 13245614Sandrew#ifndef SANITIZER_STACKTRACE_H 14245614Sandrew#define SANITIZER_STACKTRACE_H 15245614Sandrew 16245614Sandrew#include "sanitizer_internal_defs.h" 17245614Sandrew 18245614Sandrewnamespace __sanitizer { 19245614Sandrew 20245614Sandrewstatic const uptr kStackTraceMax = 256; 21245614Sandrew 22276789Sdim#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__powerpc__) || \ 23276789Sdim defined(__powerpc64__) || defined(__sparc__) || \ 24276789Sdim defined(__mips__)) 25274201Sdim# define SANITIZER_CAN_FAST_UNWIND 0 26274201Sdim#elif SANITIZER_WINDOWS 27274201Sdim# define SANITIZER_CAN_FAST_UNWIND 0 28251034Sed#else 29274201Sdim# define SANITIZER_CAN_FAST_UNWIND 1 30251034Sed#endif 31251034Sed 32276789Sdim// Fast unwind is the only option on Mac for now; we will need to 33276789Sdim// revisit this macro when slow unwind works on Mac, see 34276789Sdim// https://code.google.com/p/address-sanitizer/issues/detail?id=137 35276789Sdim#if SANITIZER_MAC 36276789Sdim# define SANITIZER_CAN_SLOW_UNWIND 0 37276789Sdim#else 38276789Sdim# define SANITIZER_CAN_SLOW_UNWIND 1 39276789Sdim#endif 40276789Sdim 41245614Sandrewstruct StackTrace { 42276789Sdim const uptr *trace; 43245614Sandrew uptr size; 44274201Sdim 45276789Sdim StackTrace() : trace(nullptr), size(0) {} 46276789Sdim StackTrace(const uptr *trace, uptr size) : trace(trace), size(size) {} 47276789Sdim 48274201Sdim // Prints a symbolized stacktrace, followed by an empty line. 49276789Sdim void Print() const; 50245614Sandrew 51274201Sdim static bool WillUseFastUnwind(bool request_fast_unwind) { 52274201Sdim if (!SANITIZER_CAN_FAST_UNWIND) 53274201Sdim return false; 54276789Sdim else if (!SANITIZER_CAN_SLOW_UNWIND) 55274201Sdim return true; 56274201Sdim return request_fast_unwind; 57274201Sdim } 58245614Sandrew 59245614Sandrew static uptr GetCurrentPc(); 60245614Sandrew static uptr GetPreviousInstructionPc(uptr pc); 61276789Sdim static uptr GetNextInstructionPc(uptr pc); 62276789Sdim typedef bool (*SymbolizeCallback)(const void *pc, char *out_buffer, 63276789Sdim int out_size); 64276789Sdim}; 65245614Sandrew 66276789Sdim// StackTrace that owns the buffer used to store the addresses. 67276789Sdimstruct BufferedStackTrace : public StackTrace { 68276789Sdim uptr trace_buffer[kStackTraceMax]; 69276789Sdim uptr top_frame_bp; // Optional bp of a top frame. 70276789Sdim 71276789Sdim BufferedStackTrace() : StackTrace(trace_buffer, 0), top_frame_bp(0) {} 72276789Sdim 73276789Sdim void Init(const uptr *pcs, uptr cnt, uptr extra_top_pc = 0); 74276789Sdim void Unwind(uptr max_depth, uptr pc, uptr bp, void *context, uptr stack_top, 75276789Sdim uptr stack_bottom, bool request_fast_unwind); 76276789Sdim 77274201Sdim private: 78274201Sdim void FastUnwindStack(uptr pc, uptr bp, uptr stack_top, uptr stack_bottom, 79274201Sdim uptr max_depth); 80274201Sdim void SlowUnwindStack(uptr pc, uptr max_depth); 81276789Sdim void SlowUnwindStackWithContext(uptr pc, void *context, 82276789Sdim uptr max_depth); 83274201Sdim void PopStackFrames(uptr count); 84274201Sdim uptr LocatePcInTrace(uptr pc); 85276789Sdim 86276789Sdim BufferedStackTrace(const BufferedStackTrace &); 87276789Sdim void operator=(const BufferedStackTrace &); 88245614Sandrew}; 89245614Sandrew 90245614Sandrew} // namespace __sanitizer 91245614Sandrew 92245614Sandrew// Use this macro if you want to print stack trace with the caller 93245614Sandrew// of the current function in the top frame. 94245614Sandrew#define GET_CALLER_PC_BP_SP \ 95245614Sandrew uptr bp = GET_CURRENT_FRAME(); \ 96245614Sandrew uptr pc = GET_CALLER_PC(); \ 97245614Sandrew uptr local_stack; \ 98245614Sandrew uptr sp = (uptr)&local_stack 99245614Sandrew 100276789Sdim#define GET_CALLER_PC_BP \ 101276789Sdim uptr bp = GET_CURRENT_FRAME(); \ 102276789Sdim uptr pc = GET_CALLER_PC(); 103276789Sdim 104245614Sandrew// Use this macro if you want to print stack trace with the current 105245614Sandrew// function in the top frame. 106245614Sandrew#define GET_CURRENT_PC_BP_SP \ 107245614Sandrew uptr bp = GET_CURRENT_FRAME(); \ 108245614Sandrew uptr pc = StackTrace::GetCurrentPc(); \ 109245614Sandrew uptr local_stack; \ 110245614Sandrew uptr sp = (uptr)&local_stack 111245614Sandrew 112245614Sandrew 113245614Sandrew#endif // SANITIZER_STACKTRACE_H 114