1 //===-- asan_stack.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 a part of AddressSanitizer, an address sanity checker.
11 //
12 // ASan-private header for asan_stack.cc.
13 //===----------------------------------------------------------------------===//
14 #ifndef ASAN_STACK_H
15 #define ASAN_STACK_H
16
17 #include "asan_flags.h"
18 #include "asan_thread.h"
19 #include "sanitizer_common/sanitizer_flags.h"
20 #include "sanitizer_common/sanitizer_stacktrace.h"
21
22 namespace __asan {
23
24 // Get the stack trace with the given pc and bp.
25 // The pc will be in the position 0 of the resulting stack trace.
26 // The bp may refer to the current frame or to the caller's frame.
27 ALWAYS_INLINE
GetStackTraceWithPcBpAndContext(StackTrace * stack,uptr max_depth,uptr pc,uptr bp,void * context,bool fast)28 void GetStackTraceWithPcBpAndContext(StackTrace *stack, uptr max_depth, uptr pc,
29 uptr bp, void *context, bool fast) {
30 #if SANITIZER_WINDOWS
31 stack->Unwind(max_depth, pc, bp, context, 0, 0, fast);
32 #else
33 AsanThread *t;
34 stack->size = 0;
35 if (LIKELY(asan_inited)) {
36 if ((t = GetCurrentThread()) && !t->isUnwinding()) {
37 uptr stack_top = t->stack_top();
38 uptr stack_bottom = t->stack_bottom();
39 ScopedUnwinding unwind_scope(t);
40 stack->Unwind(max_depth, pc, bp, context, stack_top, stack_bottom, fast);
41 } else if (t == 0 && !fast) {
42 /* If GetCurrentThread() has failed, try to do slow unwind anyways. */
43 stack->Unwind(max_depth, pc, bp, context, 0, 0, false);
44 }
45 }
46 #endif // SANITIZER_WINDOWS
47 }
48
49 } // namespace __asan
50
51 // NOTE: A Rule of thumb is to retrieve stack trace in the interceptors
52 // as early as possible (in functions exposed to the user), as we generally
53 // don't want stack trace to contain functions from ASan internals.
54
55 #define GET_STACK_TRACE(max_size, fast) \
56 StackTrace stack; \
57 if (max_size <= 2) { \
58 stack.size = max_size; \
59 if (max_size > 0) { \
60 stack.top_frame_bp = GET_CURRENT_FRAME(); \
61 stack.trace[0] = StackTrace::GetCurrentPc(); \
62 if (max_size > 1) \
63 stack.trace[1] = GET_CALLER_PC(); \
64 } \
65 } else { \
66 GetStackTraceWithPcBpAndContext(&stack, max_size, \
67 StackTrace::GetCurrentPc(), \
68 GET_CURRENT_FRAME(), 0, fast); \
69 }
70
71 #define GET_STACK_TRACE_FATAL(pc, bp) \
72 StackTrace stack; \
73 GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \
74 common_flags()->fast_unwind_on_fatal)
75
76 #define GET_STACK_TRACE_SIGNAL(pc, bp, context) \
77 StackTrace stack; \
78 GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, \
79 common_flags()->fast_unwind_on_fatal)
80
81 #define GET_STACK_TRACE_FATAL_HERE \
82 GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_fatal)
83
84 #define GET_STACK_TRACE_THREAD \
85 GET_STACK_TRACE(kStackTraceMax, true)
86
87 #define GET_STACK_TRACE_MALLOC \
88 GET_STACK_TRACE(common_flags()->malloc_context_size, \
89 common_flags()->fast_unwind_on_malloc)
90
91 #define GET_STACK_TRACE_FREE GET_STACK_TRACE_MALLOC
92
93 #define PRINT_CURRENT_STACK() \
94 { \
95 GET_STACK_TRACE_FATAL_HERE; \
96 stack.Print(); \
97 }
98
99 #endif // ASAN_STACK_H
100