1*7c3d14c8STreehugger Robot //===-- asan_stack.h --------------------------------------------*- C++ -*-===//
2*7c3d14c8STreehugger Robot //
3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure
4*7c3d14c8STreehugger Robot //
5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source
6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details.
7*7c3d14c8STreehugger Robot //
8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
9*7c3d14c8STreehugger Robot //
10*7c3d14c8STreehugger Robot // This file is a part of AddressSanitizer, an address sanity checker.
11*7c3d14c8STreehugger Robot //
12*7c3d14c8STreehugger Robot // ASan-private header for asan_stack.cc.
13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===//
14*7c3d14c8STreehugger Robot
15*7c3d14c8STreehugger Robot #ifndef ASAN_STACK_H
16*7c3d14c8STreehugger Robot #define ASAN_STACK_H
17*7c3d14c8STreehugger Robot
18*7c3d14c8STreehugger Robot #include "asan_flags.h"
19*7c3d14c8STreehugger Robot #include "asan_thread.h"
20*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_flags.h"
21*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_stacktrace.h"
22*7c3d14c8STreehugger Robot
23*7c3d14c8STreehugger Robot namespace __asan {
24*7c3d14c8STreehugger Robot
25*7c3d14c8STreehugger Robot static const u32 kDefaultMallocContextSize = 30;
26*7c3d14c8STreehugger Robot
27*7c3d14c8STreehugger Robot void SetMallocContextSize(u32 size);
28*7c3d14c8STreehugger Robot u32 GetMallocContextSize();
29*7c3d14c8STreehugger Robot
30*7c3d14c8STreehugger Robot // Get the stack trace with the given pc and bp.
31*7c3d14c8STreehugger Robot // The pc will be in the position 0 of the resulting stack trace.
32*7c3d14c8STreehugger Robot // The bp may refer to the current frame or to the caller's frame.
33*7c3d14c8STreehugger Robot ALWAYS_INLINE
GetStackTraceWithPcBpAndContext(BufferedStackTrace * stack,uptr max_depth,uptr pc,uptr bp,void * context,bool fast)34*7c3d14c8STreehugger Robot void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth,
35*7c3d14c8STreehugger Robot uptr pc, uptr bp, void *context,
36*7c3d14c8STreehugger Robot bool fast) {
37*7c3d14c8STreehugger Robot #if SANITIZER_WINDOWS
38*7c3d14c8STreehugger Robot stack->Unwind(max_depth, pc, bp, context, 0, 0, fast);
39*7c3d14c8STreehugger Robot #else
40*7c3d14c8STreehugger Robot AsanThread *t;
41*7c3d14c8STreehugger Robot stack->size = 0;
42*7c3d14c8STreehugger Robot if (LIKELY(asan_inited)) {
43*7c3d14c8STreehugger Robot if ((t = GetCurrentThread()) && !t->isUnwinding()) {
44*7c3d14c8STreehugger Robot // On FreeBSD the slow unwinding that leverages _Unwind_Backtrace()
45*7c3d14c8STreehugger Robot // yields the call stack of the signal's handler and not of the code
46*7c3d14c8STreehugger Robot // that raised the signal (as it does on Linux).
47*7c3d14c8STreehugger Robot if (SANITIZER_FREEBSD && t->isInDeadlySignal()) fast = true;
48*7c3d14c8STreehugger Robot uptr stack_top = t->stack_top();
49*7c3d14c8STreehugger Robot uptr stack_bottom = t->stack_bottom();
50*7c3d14c8STreehugger Robot ScopedUnwinding unwind_scope(t);
51*7c3d14c8STreehugger Robot if (!SANITIZER_MIPS || IsValidFrame(bp, stack_top, stack_bottom)) {
52*7c3d14c8STreehugger Robot stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom,
53*7c3d14c8STreehugger Robot fast);
54*7c3d14c8STreehugger Robot }
55*7c3d14c8STreehugger Robot } else if (!t && !fast) {
56*7c3d14c8STreehugger Robot /* If GetCurrentThread() has failed, try to do slow unwind anyways. */
57*7c3d14c8STreehugger Robot stack->Unwind(max_depth, pc, bp, context, 0, 0, false);
58*7c3d14c8STreehugger Robot }
59*7c3d14c8STreehugger Robot }
60*7c3d14c8STreehugger Robot #endif // SANITIZER_WINDOWS
61*7c3d14c8STreehugger Robot }
62*7c3d14c8STreehugger Robot
63*7c3d14c8STreehugger Robot } // namespace __asan
64*7c3d14c8STreehugger Robot
65*7c3d14c8STreehugger Robot // NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
66*7c3d14c8STreehugger Robot // as early as possible (in functions exposed to the user), as we generally
67*7c3d14c8STreehugger Robot // don't want stack trace to contain functions from ASan internals.
68*7c3d14c8STreehugger Robot
69*7c3d14c8STreehugger Robot #define GET_STACK_TRACE(max_size, fast) \
70*7c3d14c8STreehugger Robot BufferedStackTrace stack; \
71*7c3d14c8STreehugger Robot if (max_size <= 2) { \
72*7c3d14c8STreehugger Robot stack.size = max_size; \
73*7c3d14c8STreehugger Robot if (max_size > 0) { \
74*7c3d14c8STreehugger Robot stack.top_frame_bp = GET_CURRENT_FRAME(); \
75*7c3d14c8STreehugger Robot stack.trace_buffer[0] = StackTrace::GetCurrentPc(); \
76*7c3d14c8STreehugger Robot if (max_size > 1) \
77*7c3d14c8STreehugger Robot stack.trace_buffer[1] = GET_CALLER_PC(); \
78*7c3d14c8STreehugger Robot } \
79*7c3d14c8STreehugger Robot } else { \
80*7c3d14c8STreehugger Robot GetStackTraceWithPcBpAndContext(&stack, max_size, \
81*7c3d14c8STreehugger Robot StackTrace::GetCurrentPc(), \
82*7c3d14c8STreehugger Robot GET_CURRENT_FRAME(), 0, fast); \
83*7c3d14c8STreehugger Robot }
84*7c3d14c8STreehugger Robot
85*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_FATAL(pc, bp) \
86*7c3d14c8STreehugger Robot BufferedStackTrace stack; \
87*7c3d14c8STreehugger Robot GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \
88*7c3d14c8STreehugger Robot common_flags()->fast_unwind_on_fatal)
89*7c3d14c8STreehugger Robot
90*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_SIGNAL(sig) \
91*7c3d14c8STreehugger Robot BufferedStackTrace stack; \
92*7c3d14c8STreehugger Robot GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, \
93*7c3d14c8STreehugger Robot (sig).pc, (sig).bp, (sig).context, \
94*7c3d14c8STreehugger Robot common_flags()->fast_unwind_on_fatal)
95*7c3d14c8STreehugger Robot
96*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_FATAL_HERE \
97*7c3d14c8STreehugger Robot GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
98*7c3d14c8STreehugger Robot
99*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_CHECK_HERE \
100*7c3d14c8STreehugger Robot GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check)
101*7c3d14c8STreehugger Robot
102*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_THREAD \
103*7c3d14c8STreehugger Robot GET_STACK_TRACE(kStackTraceMax, true)
104*7c3d14c8STreehugger Robot
105*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_MALLOC \
106*7c3d14c8STreehugger Robot GET_STACK_TRACE(GetMallocContextSize(), common_flags()->fast_unwind_on_malloc)
107*7c3d14c8STreehugger Robot
108*7c3d14c8STreehugger Robot #define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
109*7c3d14c8STreehugger Robot
110*7c3d14c8STreehugger Robot #define PRINT_CURRENT_STACK() \
111*7c3d14c8STreehugger Robot { \
112*7c3d14c8STreehugger Robot GET_STACK_TRACE_FATAL_HERE; \
113*7c3d14c8STreehugger Robot stack.Print(); \
114*7c3d14c8STreehugger Robot }
115*7c3d14c8STreehugger Robot
116*7c3d14c8STreehugger Robot #define PRINT_CURRENT_STACK_CHECK() \
117*7c3d14c8STreehugger Robot { \
118*7c3d14c8STreehugger Robot GET_STACK_TRACE_CHECK_HERE; \
119*7c3d14c8STreehugger Robot stack.Print(); \
120*7c3d14c8STreehugger Robot }
121*7c3d14c8STreehugger Robot
122*7c3d14c8STreehugger Robot #endif // ASAN_STACK_H
123