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(&malloc_context_size, size, memory_order_release);
23}
24
25u32 GetMallocContextSize() {
26  return atomic_load(&malloc_context_size, 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(!asan_inited))
61    return;
62  request_fast = StackTrace::WillUseFastUnwind(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, nullptr, t->stack_top(), t->stack_bottom(),
70             true);
71    }
72    return;
73  }
74  if (SANITIZER_MIPS && t &&
75      !IsValidFrame(bp, t->stack_top(), t->stack_bottom()))
76    return;
77  Unwind(max_depth, pc, bp, context, 0, 0, false);
78}
79
80// ------------------ Interface -------------- {{{1
81
82extern "C" {
83SANITIZER_INTERFACE_ATTRIBUTE
84void __sanitizer_print_stack_trace() {
85  using namespace __asan;
86  PRINT_CURRENT_STACK();
87}
88}  // extern "C"
89