Home | History | Annotate | Line # | Download | only in asan
      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 
     17 namespace __asan {
     18 
     19 static atomic_uint32_t malloc_context_size;
     20 
     21 void SetMallocContextSize(u32 size) {
     22   atomic_store(&malloc_context_size, size, memory_order_release);
     23 }
     24 
     25 u32 GetMallocContextSize() {
     26   return atomic_load(&malloc_context_size, memory_order_acquire);
     27 }
     28 
     29 namespace {
     30 
     31 // ScopedUnwinding is a scope for stacktracing member of a context
     32 class 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 
     56 void __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, t ? t->stack_top() : 0,
     78          t ? t->stack_bottom() : 0, false);
     79 }
     80 
     81 // ------------------ Interface -------------- {{{1
     82 
     83 extern "C" {
     84 SANITIZER_INTERFACE_ATTRIBUTE
     85 void __sanitizer_print_stack_trace() {
     86   using namespace __asan;
     87   PRINT_CURRENT_STACK();
     88 }
     89 }  // extern "C"
     90