xref: /aosp_15_r20/external/compiler-rt/lib/asan/asan_stack.h (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
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