1//===-- asan_stack.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// Code for ASan stack trace.
12//===----------------------------------------------------------------------===//
13#include "asan_internal.h"
14#include "asan_stack.h"
15#include "sanitizer_common/sanitizer_atomic.h"
16
17namespace __asan {
18
19static atomic_uint32_t malloc_context_size;
20
21void SetMallocContextSize(u32 size) {
22 atomic_store(a: &malloc_context_size, v: size, mo: memory_order_release);
23}
24
25u32 GetMallocContextSize() {
26 return atomic_load(a: &malloc_context_size, mo: memory_order_acquire);
27}
28
29namespace {
30
31// ScopedUnwinding is a scope for stacktracing member of a context
32class ScopedUnwinding {
33 public:
34 explicit ScopedUnwinding(AsanThread *t) : thread(t) {
35 if (thread) {
36 can_unwind = !thread->isUnwinding();
37 thread->setUnwinding(true);
38 }
39 }
40 ~ScopedUnwinding() {
41 if (thread)
42 thread->setUnwinding(false);
43 }
44
45 bool CanUnwind() const { return can_unwind; }
46
47 private:
48 AsanThread *thread = nullptr;
49 bool can_unwind = true;
50};
51
52} // namespace
53
54} // namespace __asan
55
56void __sanitizer::BufferedStackTrace::UnwindImpl(
57 uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
58 using namespace __asan;
59 size = 0;
60 if (UNLIKELY(!AsanInited()))
61 return;
62 request_fast = StackTrace::WillUseFastUnwind(request_fast_unwind: request_fast);
63 AsanThread *t = GetCurrentThread();
64 ScopedUnwinding unwind_scope(t);
65 if (!unwind_scope.CanUnwind())
66 return;
67 if (request_fast) {
68 if (t) {
69 Unwind(max_depth, pc, bp, context: nullptr, stack_top: t->stack_top(), stack_bottom: t->stack_bottom(),
70 request_fast_unwind: true);
71 }
72 return;
73 }
74 if (SANITIZER_MIPS && t &&
75 !IsValidFrame(frame: bp, stack_top: t->stack_top(), stack_bottom: t->stack_bottom()))
76 return;
77 Unwind(max_depth, pc, bp, context, stack_top: t ? t->stack_top() : 0,
78 stack_bottom: t ? t->stack_bottom() : 0, request_fast_unwind: false);
79}
80
81// ------------------ Interface -------------- {{{1
82
83extern "C" {
84SANITIZER_INTERFACE_ATTRIBUTE
85void __sanitizer_print_stack_trace() {
86 using namespace __asan;
87 PRINT_CURRENT_STACK();
88}
89} // extern "C"
90