1*7c3d14c8STreehugger Robot //===-- asan_thread.h -------------------------------------------*- C++ -*-===// 2*7c3d14c8STreehugger Robot // 3*7c3d14c8STreehugger Robot // The LLVM Compiler Infrastructure 4*7c3d14c8STreehugger Robot // 5*7c3d14c8STreehugger Robot // This file is distributed under the University of Illinois Open Source 6*7c3d14c8STreehugger Robot // License. See LICENSE.TXT for details. 7*7c3d14c8STreehugger Robot // 8*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===// 9*7c3d14c8STreehugger Robot // 10*7c3d14c8STreehugger Robot // This file is a part of AddressSanitizer, an address sanity checker. 11*7c3d14c8STreehugger Robot // 12*7c3d14c8STreehugger Robot // ASan-private header for asan_thread.cc. 13*7c3d14c8STreehugger Robot //===----------------------------------------------------------------------===// 14*7c3d14c8STreehugger Robot 15*7c3d14c8STreehugger Robot #ifndef ASAN_THREAD_H 16*7c3d14c8STreehugger Robot #define ASAN_THREAD_H 17*7c3d14c8STreehugger Robot 18*7c3d14c8STreehugger Robot #include "asan_allocator.h" 19*7c3d14c8STreehugger Robot #include "asan_internal.h" 20*7c3d14c8STreehugger Robot #include "asan_fake_stack.h" 21*7c3d14c8STreehugger Robot #include "asan_stats.h" 22*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_common.h" 23*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_libc.h" 24*7c3d14c8STreehugger Robot #include "sanitizer_common/sanitizer_thread_registry.h" 25*7c3d14c8STreehugger Robot 26*7c3d14c8STreehugger Robot namespace __sanitizer { 27*7c3d14c8STreehugger Robot struct DTLS; 28*7c3d14c8STreehugger Robot } // namespace __sanitizer 29*7c3d14c8STreehugger Robot 30*7c3d14c8STreehugger Robot namespace __asan { 31*7c3d14c8STreehugger Robot 32*7c3d14c8STreehugger Robot const u32 kInvalidTid = 0xffffff; // Must fit into 24 bits. 33*7c3d14c8STreehugger Robot const u32 kMaxNumberOfThreads = (1 << 22); // 4M 34*7c3d14c8STreehugger Robot 35*7c3d14c8STreehugger Robot class AsanThread; 36*7c3d14c8STreehugger Robot 37*7c3d14c8STreehugger Robot // These objects are created for every thread and are never deleted, 38*7c3d14c8STreehugger Robot // so we can find them by tid even if the thread is long dead. 39*7c3d14c8STreehugger Robot class AsanThreadContext : public ThreadContextBase { 40*7c3d14c8STreehugger Robot public: AsanThreadContext(int tid)41*7c3d14c8STreehugger Robot explicit AsanThreadContext(int tid) 42*7c3d14c8STreehugger Robot : ThreadContextBase(tid), announced(false), 43*7c3d14c8STreehugger Robot destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), 44*7c3d14c8STreehugger Robot thread(nullptr) {} 45*7c3d14c8STreehugger Robot bool announced; 46*7c3d14c8STreehugger Robot u8 destructor_iterations; 47*7c3d14c8STreehugger Robot u32 stack_id; 48*7c3d14c8STreehugger Robot AsanThread *thread; 49*7c3d14c8STreehugger Robot 50*7c3d14c8STreehugger Robot void OnCreated(void *arg) override; 51*7c3d14c8STreehugger Robot void OnFinished() override; 52*7c3d14c8STreehugger Robot }; 53*7c3d14c8STreehugger Robot 54*7c3d14c8STreehugger Robot // AsanThreadContext objects are never freed, so we need many of them. 55*7c3d14c8STreehugger Robot COMPILER_CHECK(sizeof(AsanThreadContext) <= 256); 56*7c3d14c8STreehugger Robot 57*7c3d14c8STreehugger Robot // AsanThread are stored in TSD and destroyed when the thread dies. 58*7c3d14c8STreehugger Robot class AsanThread { 59*7c3d14c8STreehugger Robot public: 60*7c3d14c8STreehugger Robot static AsanThread *Create(thread_callback_t start_routine, void *arg, 61*7c3d14c8STreehugger Robot u32 parent_tid, StackTrace *stack, bool detached); 62*7c3d14c8STreehugger Robot static void TSDDtor(void *tsd); 63*7c3d14c8STreehugger Robot void Destroy(); 64*7c3d14c8STreehugger Robot 65*7c3d14c8STreehugger Robot void Init(); // Should be called from the thread itself. 66*7c3d14c8STreehugger Robot thread_return_t ThreadStart(uptr os_id, 67*7c3d14c8STreehugger Robot atomic_uintptr_t *signal_thread_is_registered); 68*7c3d14c8STreehugger Robot 69*7c3d14c8STreehugger Robot uptr stack_top(); 70*7c3d14c8STreehugger Robot uptr stack_bottom(); 71*7c3d14c8STreehugger Robot uptr stack_size(); tls_begin()72*7c3d14c8STreehugger Robot uptr tls_begin() { return tls_begin_; } tls_end()73*7c3d14c8STreehugger Robot uptr tls_end() { return tls_end_; } dtls()74*7c3d14c8STreehugger Robot DTLS *dtls() { return dtls_; } tid()75*7c3d14c8STreehugger Robot u32 tid() { return context_->tid; } context()76*7c3d14c8STreehugger Robot AsanThreadContext *context() { return context_; } set_context(AsanThreadContext * context)77*7c3d14c8STreehugger Robot void set_context(AsanThreadContext *context) { context_ = context; } 78*7c3d14c8STreehugger Robot 79*7c3d14c8STreehugger Robot struct StackFrameAccess { 80*7c3d14c8STreehugger Robot uptr offset; 81*7c3d14c8STreehugger Robot uptr frame_pc; 82*7c3d14c8STreehugger Robot const char *frame_descr; 83*7c3d14c8STreehugger Robot }; 84*7c3d14c8STreehugger Robot bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access); 85*7c3d14c8STreehugger Robot 86*7c3d14c8STreehugger Robot bool AddrIsInStack(uptr addr); 87*7c3d14c8STreehugger Robot DeleteFakeStack(int tid)88*7c3d14c8STreehugger Robot void DeleteFakeStack(int tid) { 89*7c3d14c8STreehugger Robot if (!fake_stack_) return; 90*7c3d14c8STreehugger Robot FakeStack *t = fake_stack_; 91*7c3d14c8STreehugger Robot fake_stack_ = nullptr; 92*7c3d14c8STreehugger Robot SetTLSFakeStack(nullptr); 93*7c3d14c8STreehugger Robot t->Destroy(tid); 94*7c3d14c8STreehugger Robot } 95*7c3d14c8STreehugger Robot 96*7c3d14c8STreehugger Robot void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); 97*7c3d14c8STreehugger Robot void FinishSwitchFiber(FakeStack *fake_stack_save); 98*7c3d14c8STreehugger Robot has_fake_stack()99*7c3d14c8STreehugger Robot bool has_fake_stack() { 100*7c3d14c8STreehugger Robot return !atomic_load(&stack_switching_, memory_order_relaxed) && 101*7c3d14c8STreehugger Robot (reinterpret_cast<uptr>(fake_stack_) > 1); 102*7c3d14c8STreehugger Robot } 103*7c3d14c8STreehugger Robot fake_stack()104*7c3d14c8STreehugger Robot FakeStack *fake_stack() { 105*7c3d14c8STreehugger Robot if (!__asan_option_detect_stack_use_after_return) 106*7c3d14c8STreehugger Robot return nullptr; 107*7c3d14c8STreehugger Robot if (atomic_load(&stack_switching_, memory_order_relaxed)) 108*7c3d14c8STreehugger Robot return nullptr; 109*7c3d14c8STreehugger Robot if (!has_fake_stack()) 110*7c3d14c8STreehugger Robot return AsyncSignalSafeLazyInitFakeStack(); 111*7c3d14c8STreehugger Robot return fake_stack_; 112*7c3d14c8STreehugger Robot } 113*7c3d14c8STreehugger Robot 114*7c3d14c8STreehugger Robot // True is this thread is currently unwinding stack (i.e. collecting a stack 115*7c3d14c8STreehugger Robot // trace). Used to prevent deadlocks on platforms where libc unwinder calls 116*7c3d14c8STreehugger Robot // malloc internally. See PR17116 for more details. isUnwinding()117*7c3d14c8STreehugger Robot bool isUnwinding() const { return unwinding_; } setUnwinding(bool b)118*7c3d14c8STreehugger Robot void setUnwinding(bool b) { unwinding_ = b; } 119*7c3d14c8STreehugger Robot 120*7c3d14c8STreehugger Robot // True if we are in a deadly signal handler. isInDeadlySignal()121*7c3d14c8STreehugger Robot bool isInDeadlySignal() const { return in_deadly_signal_; } setInDeadlySignal(bool b)122*7c3d14c8STreehugger Robot void setInDeadlySignal(bool b) { in_deadly_signal_ = b; } 123*7c3d14c8STreehugger Robot malloc_storage()124*7c3d14c8STreehugger Robot AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } stats()125*7c3d14c8STreehugger Robot AsanStats &stats() { return stats_; } 126*7c3d14c8STreehugger Robot 127*7c3d14c8STreehugger Robot private: 128*7c3d14c8STreehugger Robot // NOTE: There is no AsanThread constructor. It is allocated 129*7c3d14c8STreehugger Robot // via mmap() and *must* be valid in zero-initialized state. 130*7c3d14c8STreehugger Robot void SetThreadStackAndTls(); 131*7c3d14c8STreehugger Robot void ClearShadowForThreadStackAndTLS(); 132*7c3d14c8STreehugger Robot FakeStack *AsyncSignalSafeLazyInitFakeStack(); 133*7c3d14c8STreehugger Robot 134*7c3d14c8STreehugger Robot struct StackBounds { 135*7c3d14c8STreehugger Robot uptr bottom; 136*7c3d14c8STreehugger Robot uptr top; 137*7c3d14c8STreehugger Robot }; 138*7c3d14c8STreehugger Robot StackBounds GetStackBounds() const; 139*7c3d14c8STreehugger Robot 140*7c3d14c8STreehugger Robot AsanThreadContext *context_; 141*7c3d14c8STreehugger Robot thread_callback_t start_routine_; 142*7c3d14c8STreehugger Robot void *arg_; 143*7c3d14c8STreehugger Robot 144*7c3d14c8STreehugger Robot uptr stack_top_; 145*7c3d14c8STreehugger Robot uptr stack_bottom_; 146*7c3d14c8STreehugger Robot // these variables are used when the thread is about to switch stack 147*7c3d14c8STreehugger Robot uptr next_stack_top_; 148*7c3d14c8STreehugger Robot uptr next_stack_bottom_; 149*7c3d14c8STreehugger Robot // true if switching is in progress 150*7c3d14c8STreehugger Robot atomic_uint8_t stack_switching_; 151*7c3d14c8STreehugger Robot 152*7c3d14c8STreehugger Robot uptr tls_begin_; 153*7c3d14c8STreehugger Robot uptr tls_end_; 154*7c3d14c8STreehugger Robot DTLS *dtls_; 155*7c3d14c8STreehugger Robot 156*7c3d14c8STreehugger Robot FakeStack *fake_stack_; 157*7c3d14c8STreehugger Robot AsanThreadLocalMallocStorage malloc_storage_; 158*7c3d14c8STreehugger Robot AsanStats stats_; 159*7c3d14c8STreehugger Robot bool unwinding_; 160*7c3d14c8STreehugger Robot bool in_deadly_signal_; 161*7c3d14c8STreehugger Robot }; 162*7c3d14c8STreehugger Robot 163*7c3d14c8STreehugger Robot // ScopedUnwinding is a scope for stacktracing member of a context 164*7c3d14c8STreehugger Robot class ScopedUnwinding { 165*7c3d14c8STreehugger Robot public: ScopedUnwinding(AsanThread * t)166*7c3d14c8STreehugger Robot explicit ScopedUnwinding(AsanThread *t) : thread(t) { 167*7c3d14c8STreehugger Robot t->setUnwinding(true); 168*7c3d14c8STreehugger Robot } ~ScopedUnwinding()169*7c3d14c8STreehugger Robot ~ScopedUnwinding() { thread->setUnwinding(false); } 170*7c3d14c8STreehugger Robot 171*7c3d14c8STreehugger Robot private: 172*7c3d14c8STreehugger Robot AsanThread *thread; 173*7c3d14c8STreehugger Robot }; 174*7c3d14c8STreehugger Robot 175*7c3d14c8STreehugger Robot // ScopedDeadlySignal is a scope for handling deadly signals. 176*7c3d14c8STreehugger Robot class ScopedDeadlySignal { 177*7c3d14c8STreehugger Robot public: ScopedDeadlySignal(AsanThread * t)178*7c3d14c8STreehugger Robot explicit ScopedDeadlySignal(AsanThread *t) : thread(t) { 179*7c3d14c8STreehugger Robot if (thread) thread->setInDeadlySignal(true); 180*7c3d14c8STreehugger Robot } ~ScopedDeadlySignal()181*7c3d14c8STreehugger Robot ~ScopedDeadlySignal() { 182*7c3d14c8STreehugger Robot if (thread) thread->setInDeadlySignal(false); 183*7c3d14c8STreehugger Robot } 184*7c3d14c8STreehugger Robot 185*7c3d14c8STreehugger Robot private: 186*7c3d14c8STreehugger Robot AsanThread *thread; 187*7c3d14c8STreehugger Robot }; 188*7c3d14c8STreehugger Robot 189*7c3d14c8STreehugger Robot // Returns a single instance of registry. 190*7c3d14c8STreehugger Robot ThreadRegistry &asanThreadRegistry(); 191*7c3d14c8STreehugger Robot 192*7c3d14c8STreehugger Robot // Must be called under ThreadRegistryLock. 193*7c3d14c8STreehugger Robot AsanThreadContext *GetThreadContextByTidLocked(u32 tid); 194*7c3d14c8STreehugger Robot 195*7c3d14c8STreehugger Robot // Get the current thread. May return 0. 196*7c3d14c8STreehugger Robot AsanThread *GetCurrentThread(); 197*7c3d14c8STreehugger Robot void SetCurrentThread(AsanThread *t); 198*7c3d14c8STreehugger Robot u32 GetCurrentTidOrInvalid(); 199*7c3d14c8STreehugger Robot AsanThread *FindThreadByStackAddress(uptr addr); 200*7c3d14c8STreehugger Robot 201*7c3d14c8STreehugger Robot // Used to handle fork(). 202*7c3d14c8STreehugger Robot void EnsureMainThreadIDIsCorrect(); 203*7c3d14c8STreehugger Robot } // namespace __asan 204*7c3d14c8STreehugger Robot 205*7c3d14c8STreehugger Robot #endif // ASAN_THREAD_H 206