1353944Sdim//===-- asan_stack.cpp ----------------------------------------------------===//
2353944Sdim//
3353944Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353944Sdim// See https://llvm.org/LICENSE.txt for license information.
5353944Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353944Sdim//
7353944Sdim//===----------------------------------------------------------------------===//
8353944Sdim//
9353944Sdim// This file is a part of AddressSanitizer, an address sanity checker.
10353944Sdim//
11353944Sdim// Code for ASan stack trace.
12353944Sdim//===----------------------------------------------------------------------===//
13353944Sdim#include "asan_internal.h"
14353944Sdim#include "asan_stack.h"
15353944Sdim#include "sanitizer_common/sanitizer_atomic.h"
16353944Sdim
17353944Sdimnamespace __asan {
18353944Sdim
19353944Sdimstatic atomic_uint32_t malloc_context_size;
20353944Sdim
21353944Sdimvoid SetMallocContextSize(u32 size) {
22353944Sdim  atomic_store(&malloc_context_size, size, memory_order_release);
23353944Sdim}
24353944Sdim
25353944Sdimu32 GetMallocContextSize() {
26353944Sdim  return atomic_load(&malloc_context_size, memory_order_acquire);
27353944Sdim}
28353944Sdim
29353944Sdimnamespace {
30353944Sdim
31353944Sdim// ScopedUnwinding is a scope for stacktracing member of a context
32353944Sdimclass ScopedUnwinding {
33353944Sdim public:
34353944Sdim  explicit ScopedUnwinding(AsanThread *t) : thread(t) {
35353944Sdim    if (thread) {
36353944Sdim      can_unwind = !thread->isUnwinding();
37353944Sdim      thread->setUnwinding(true);
38353944Sdim    }
39353944Sdim  }
40353944Sdim  ~ScopedUnwinding() {
41353944Sdim    if (thread)
42353944Sdim      thread->setUnwinding(false);
43353944Sdim  }
44353944Sdim
45353944Sdim  bool CanUnwind() const { return can_unwind; }
46353944Sdim
47353944Sdim private:
48353944Sdim  AsanThread *thread = nullptr;
49353944Sdim  bool can_unwind = true;
50353944Sdim};
51353944Sdim
52353944Sdim}  // namespace
53353944Sdim
54353944Sdim}  // namespace __asan
55353944Sdim
56353944Sdimvoid __sanitizer::BufferedStackTrace::UnwindImpl(
57353944Sdim    uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
58353944Sdim  using namespace __asan;
59353944Sdim  size = 0;
60353944Sdim  if (UNLIKELY(!asan_inited))
61353944Sdim    return;
62353944Sdim  request_fast = StackTrace::WillUseFastUnwind(request_fast);
63353944Sdim  AsanThread *t = GetCurrentThread();
64353944Sdim  ScopedUnwinding unwind_scope(t);
65353944Sdim  if (!unwind_scope.CanUnwind())
66353944Sdim    return;
67353944Sdim  if (request_fast) {
68353944Sdim    if (t) {
69353944Sdim      Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(),
70353944Sdim             true);
71353944Sdim    }
72353944Sdim    return;
73353944Sdim  }
74353944Sdim  if (SANITIZER_MIPS && t &&
75353944Sdim      !IsValidFrame(bp, t->stack_top(), t->stack_bottom()))
76353944Sdim    return;
77353944Sdim  Unwind(max_depth, pc, bp, context, 0, 0, false);
78353944Sdim}
79353944Sdim
80353944Sdim// ------------------ Interface -------------- {{{1
81353944Sdim
82353944Sdimextern "C" {
83353944SdimSANITIZER_INTERFACE_ATTRIBUTE
84353944Sdimvoid __sanitizer_print_stack_trace() {
85353944Sdim  using namespace __asan;
86353944Sdim  PRINT_CURRENT_STACK();
87353944Sdim}
88353944Sdim}  // extern "C"
89