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