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