168d75effSDimitry Andric //===-- asan_stack.cpp ----------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // Code for ASan stack trace. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric #include "asan_internal.h" 1468d75effSDimitry Andric #include "asan_stack.h" 1568d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 1668d75effSDimitry Andric 1768d75effSDimitry Andric namespace __asan { 1868d75effSDimitry Andric 1968d75effSDimitry Andric static atomic_uint32_t malloc_context_size; 2068d75effSDimitry Andric 2168d75effSDimitry Andric void SetMallocContextSize(u32 size) { 2268d75effSDimitry Andric atomic_store(&malloc_context_size, size, memory_order_release); 2368d75effSDimitry Andric } 2468d75effSDimitry Andric 2568d75effSDimitry Andric u32 GetMallocContextSize() { 2668d75effSDimitry Andric return atomic_load(&malloc_context_size, memory_order_acquire); 2768d75effSDimitry Andric } 2868d75effSDimitry Andric 2968d75effSDimitry Andric namespace { 3068d75effSDimitry Andric 3168d75effSDimitry Andric // ScopedUnwinding is a scope for stacktracing member of a context 3268d75effSDimitry Andric class ScopedUnwinding { 3368d75effSDimitry Andric public: 3468d75effSDimitry Andric explicit ScopedUnwinding(AsanThread *t) : thread(t) { 3568d75effSDimitry Andric if (thread) { 3668d75effSDimitry Andric can_unwind = !thread->isUnwinding(); 3768d75effSDimitry Andric thread->setUnwinding(true); 3868d75effSDimitry Andric } 3968d75effSDimitry Andric } 4068d75effSDimitry Andric ~ScopedUnwinding() { 4168d75effSDimitry Andric if (thread) 4268d75effSDimitry Andric thread->setUnwinding(false); 4368d75effSDimitry Andric } 4468d75effSDimitry Andric 4568d75effSDimitry Andric bool CanUnwind() const { return can_unwind; } 4668d75effSDimitry Andric 4768d75effSDimitry Andric private: 4868d75effSDimitry Andric AsanThread *thread = nullptr; 4968d75effSDimitry Andric bool can_unwind = true; 5068d75effSDimitry Andric }; 5168d75effSDimitry Andric 5268d75effSDimitry Andric } // namespace 5368d75effSDimitry Andric 5468d75effSDimitry Andric } // namespace __asan 5568d75effSDimitry Andric 5668d75effSDimitry Andric void __sanitizer::BufferedStackTrace::UnwindImpl( 5768d75effSDimitry Andric uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { 5868d75effSDimitry Andric using namespace __asan; 5968d75effSDimitry Andric size = 0; 60*5f757f3fSDimitry Andric if (UNLIKELY(!AsanInited())) 6168d75effSDimitry Andric return; 6268d75effSDimitry Andric request_fast = StackTrace::WillUseFastUnwind(request_fast); 6368d75effSDimitry Andric AsanThread *t = GetCurrentThread(); 6468d75effSDimitry Andric ScopedUnwinding unwind_scope(t); 6568d75effSDimitry Andric if (!unwind_scope.CanUnwind()) 6668d75effSDimitry Andric return; 6768d75effSDimitry Andric if (request_fast) { 6868d75effSDimitry Andric if (t) { 6968d75effSDimitry Andric Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), 7068d75effSDimitry Andric true); 7168d75effSDimitry Andric } 7268d75effSDimitry Andric return; 7368d75effSDimitry Andric } 7468d75effSDimitry Andric if (SANITIZER_MIPS && t && 7568d75effSDimitry Andric !IsValidFrame(bp, t->stack_top(), t->stack_bottom())) 7668d75effSDimitry Andric return; 77fe6060f1SDimitry Andric Unwind(max_depth, pc, bp, context, t ? t->stack_top() : 0, 78fe6060f1SDimitry Andric t ? t->stack_bottom() : 0, false); 7968d75effSDimitry Andric } 8068d75effSDimitry Andric 8168d75effSDimitry Andric // ------------------ Interface -------------- {{{1 8268d75effSDimitry Andric 8368d75effSDimitry Andric extern "C" { 8468d75effSDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 8568d75effSDimitry Andric void __sanitizer_print_stack_trace() { 8668d75effSDimitry Andric using namespace __asan; 8768d75effSDimitry Andric PRINT_CURRENT_STACK(); 8868d75effSDimitry Andric } 8968d75effSDimitry Andric } // extern "C" 90