1 //===-- sanitizer_stacktrace.h ----------------------------------*- C++ -*-===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
10 //===----------------------------------------------------------------------===//
11 #ifndef SANITIZER_STACKTRACE_H
12 #define SANITIZER_STACKTRACE_H
14 #include "sanitizer_internal_defs.h"
16 namespace __sanitizer
{
18 static const u32 kStackTraceMax
= 256;
20 #if SANITIZER_LINUX && (defined(__sparc__) || defined(__mips__))
21 # define SANITIZER_CAN_FAST_UNWIND 0
22 #elif SANITIZER_WINDOWS
23 # define SANITIZER_CAN_FAST_UNWIND 0
25 # define SANITIZER_CAN_FAST_UNWIND 1
28 // Fast unwind is the only option on Mac for now; we will need to
29 // revisit this macro when slow unwind works on Mac, see
30 // https://github.com/google/sanitizers/issues/137
32 # define SANITIZER_CAN_SLOW_UNWIND 0
34 # define SANITIZER_CAN_SLOW_UNWIND 1
42 static const int TAG_UNKNOWN
= 0;
43 static const int TAG_ALLOC
= 1;
44 static const int TAG_DEALLOC
= 2;
45 static const int TAG_CUSTOM
= 100; // Tool specific tags start here.
47 StackTrace() : trace(nullptr), size(0), tag(0) {}
48 StackTrace(const uptr
*trace
, u32 size
) : trace(trace
), size(size
), tag(0) {}
49 StackTrace(const uptr
*trace
, u32 size
, u32 tag
)
50 : trace(trace
), size(size
), tag(tag
) {}
52 // Prints a symbolized stacktrace, followed by an empty line.
55 static bool WillUseFastUnwind(bool request_fast_unwind
) {
56 if (!SANITIZER_CAN_FAST_UNWIND
)
58 else if (!SANITIZER_CAN_SLOW_UNWIND
)
60 return request_fast_unwind
;
63 static uptr
GetCurrentPc();
64 static inline uptr
GetPreviousInstructionPc(uptr pc
);
65 static uptr
GetNextInstructionPc(uptr pc
);
66 typedef bool (*SymbolizeCallback
)(const void *pc
, char *out_buffer
,
70 // Performance-critical, must be in the header.
72 uptr
StackTrace::GetPreviousInstructionPc(uptr pc
) {
77 #if defined(__powerpc__) || defined(__powerpc64__)
78 // PCs are always 4 byte aligned.
80 #elif defined(__sparc__) || defined(__mips__)
87 // StackTrace that owns the buffer used to store the addresses.
88 struct BufferedStackTrace
: public StackTrace
{
89 uptr trace_buffer
[kStackTraceMax
];
90 uptr top_frame_bp
; // Optional bp of a top frame.
92 BufferedStackTrace() : StackTrace(trace_buffer
, 0), top_frame_bp(0) {}
94 void Init(const uptr
*pcs
, uptr cnt
, uptr extra_top_pc
= 0);
95 void Unwind(u32 max_depth
, uptr pc
, uptr bp
, void *context
, uptr stack_top
,
96 uptr stack_bottom
, bool request_fast_unwind
);
99 void FastUnwindStack(uptr pc
, uptr bp
, uptr stack_top
, uptr stack_bottom
,
101 void SlowUnwindStack(uptr pc
, u32 max_depth
);
102 void SlowUnwindStackWithContext(uptr pc
, void *context
,
104 void PopStackFrames(uptr count
);
105 uptr
LocatePcInTrace(uptr pc
);
107 BufferedStackTrace(const BufferedStackTrace
&);
108 void operator=(const BufferedStackTrace
&);
111 // Check if given pointer points into allocated stack area.
112 static inline bool IsValidFrame(uptr frame
, uptr stack_top
, uptr stack_bottom
) {
113 return frame
> stack_bottom
&& frame
< stack_top
- 2 * sizeof (uhwptr
);
116 } // namespace __sanitizer
118 // Use this macro if you want to print stack trace with the caller
119 // of the current function in the top frame.
120 #define GET_CALLER_PC_BP_SP \
121 uptr bp = GET_CURRENT_FRAME(); \
122 uptr pc = GET_CALLER_PC(); \
124 uptr sp = (uptr)&local_stack
126 #define GET_CALLER_PC_BP \
127 uptr bp = GET_CURRENT_FRAME(); \
128 uptr pc = GET_CALLER_PC();
130 // Use this macro if you want to print stack trace with the current
131 // function in the top frame.
132 #define GET_CURRENT_PC_BP_SP \
133 uptr bp = GET_CURRENT_FRAME(); \
134 uptr pc = StackTrace::GetCurrentPc(); \
136 uptr sp = (uptr)&local_stack
139 #endif // SANITIZER_STACKTRACE_H