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