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, 0, 0, false); 78 } 79 80 // ------------------ Interface -------------- {{{1 81 82 extern "C" { 83 SANITIZER_INTERFACE_ATTRIBUTE 84 void __sanitizer_print_stack_trace() { 85 using namespace __asan; 86 PRINT_CURRENT_STACK(); 87 } 88 } // extern "C" 89