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