13cab2bb3Spatrick //===-- asan_thread.h -------------------------------------------*- C++ -*-===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // 93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker. 103cab2bb3Spatrick // 113cab2bb3Spatrick // ASan-private header for asan_thread.cpp. 123cab2bb3Spatrick //===----------------------------------------------------------------------===// 133cab2bb3Spatrick 143cab2bb3Spatrick #ifndef ASAN_THREAD_H 153cab2bb3Spatrick #define ASAN_THREAD_H 163cab2bb3Spatrick 173cab2bb3Spatrick #include "asan_allocator.h" 183cab2bb3Spatrick #include "asan_internal.h" 193cab2bb3Spatrick #include "asan_fake_stack.h" 203cab2bb3Spatrick #include "asan_stats.h" 213cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h" 223cab2bb3Spatrick #include "sanitizer_common/sanitizer_libc.h" 233cab2bb3Spatrick #include "sanitizer_common/sanitizer_thread_registry.h" 243cab2bb3Spatrick 253cab2bb3Spatrick namespace __sanitizer { 263cab2bb3Spatrick struct DTLS; 273cab2bb3Spatrick } // namespace __sanitizer 283cab2bb3Spatrick 293cab2bb3Spatrick namespace __asan { 303cab2bb3Spatrick 313cab2bb3Spatrick class AsanThread; 323cab2bb3Spatrick 333cab2bb3Spatrick // These objects are created for every thread and are never deleted, 343cab2bb3Spatrick // so we can find them by tid even if the thread is long dead. 35*d89ec533Spatrick class AsanThreadContext final : public ThreadContextBase { 363cab2bb3Spatrick public: AsanThreadContext(int tid)373cab2bb3Spatrick explicit AsanThreadContext(int tid) 383cab2bb3Spatrick : ThreadContextBase(tid), announced(false), 393cab2bb3Spatrick destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), 403cab2bb3Spatrick thread(nullptr) {} 413cab2bb3Spatrick bool announced; 423cab2bb3Spatrick u8 destructor_iterations; 433cab2bb3Spatrick u32 stack_id; 443cab2bb3Spatrick AsanThread *thread; 453cab2bb3Spatrick 463cab2bb3Spatrick void OnCreated(void *arg) override; 473cab2bb3Spatrick void OnFinished() override; 483cab2bb3Spatrick 493cab2bb3Spatrick struct CreateThreadContextArgs { 503cab2bb3Spatrick AsanThread *thread; 513cab2bb3Spatrick StackTrace *stack; 523cab2bb3Spatrick }; 533cab2bb3Spatrick }; 543cab2bb3Spatrick 553cab2bb3Spatrick // AsanThreadContext objects are never freed, so we need many of them. 563cab2bb3Spatrick COMPILER_CHECK(sizeof(AsanThreadContext) <= 256); 573cab2bb3Spatrick 583cab2bb3Spatrick // AsanThread are stored in TSD and destroyed when the thread dies. 593cab2bb3Spatrick class AsanThread { 603cab2bb3Spatrick public: 613cab2bb3Spatrick static AsanThread *Create(thread_callback_t start_routine, void *arg, 623cab2bb3Spatrick u32 parent_tid, StackTrace *stack, bool detached); 633cab2bb3Spatrick static void TSDDtor(void *tsd); 643cab2bb3Spatrick void Destroy(); 653cab2bb3Spatrick 663cab2bb3Spatrick struct InitOptions; 673cab2bb3Spatrick void Init(const InitOptions *options = nullptr); 683cab2bb3Spatrick 69*d89ec533Spatrick thread_return_t ThreadStart(tid_t os_id); 703cab2bb3Spatrick 713cab2bb3Spatrick uptr stack_top(); 723cab2bb3Spatrick uptr stack_bottom(); 733cab2bb3Spatrick uptr stack_size(); tls_begin()743cab2bb3Spatrick uptr tls_begin() { return tls_begin_; } tls_end()753cab2bb3Spatrick uptr tls_end() { return tls_end_; } dtls()763cab2bb3Spatrick DTLS *dtls() { return dtls_; } tid()773cab2bb3Spatrick u32 tid() { return context_->tid; } context()783cab2bb3Spatrick AsanThreadContext *context() { return context_; } set_context(AsanThreadContext * context)793cab2bb3Spatrick void set_context(AsanThreadContext *context) { context_ = context; } 803cab2bb3Spatrick 813cab2bb3Spatrick struct StackFrameAccess { 823cab2bb3Spatrick uptr offset; 833cab2bb3Spatrick uptr frame_pc; 843cab2bb3Spatrick const char *frame_descr; 853cab2bb3Spatrick }; 863cab2bb3Spatrick bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access); 873cab2bb3Spatrick 883cab2bb3Spatrick // Returns a pointer to the start of the stack variable's shadow memory. 893cab2bb3Spatrick uptr GetStackVariableShadowStart(uptr addr); 903cab2bb3Spatrick 913cab2bb3Spatrick bool AddrIsInStack(uptr addr); 923cab2bb3Spatrick DeleteFakeStack(int tid)933cab2bb3Spatrick void DeleteFakeStack(int tid) { 943cab2bb3Spatrick if (!fake_stack_) return; 953cab2bb3Spatrick FakeStack *t = fake_stack_; 963cab2bb3Spatrick fake_stack_ = nullptr; 973cab2bb3Spatrick SetTLSFakeStack(nullptr); 983cab2bb3Spatrick t->Destroy(tid); 993cab2bb3Spatrick } 1003cab2bb3Spatrick 1013cab2bb3Spatrick void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); 1023cab2bb3Spatrick void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old, 1033cab2bb3Spatrick uptr *size_old); 1043cab2bb3Spatrick get_fake_stack()105*d89ec533Spatrick FakeStack *get_fake_stack() { 1063cab2bb3Spatrick if (atomic_load(&stack_switching_, memory_order_relaxed)) 1073cab2bb3Spatrick return nullptr; 108*d89ec533Spatrick if (reinterpret_cast<uptr>(fake_stack_) <= 1) 109*d89ec533Spatrick return nullptr; 110*d89ec533Spatrick return fake_stack_; 111*d89ec533Spatrick } 112*d89ec533Spatrick get_or_create_fake_stack()113*d89ec533Spatrick FakeStack *get_or_create_fake_stack() { 114*d89ec533Spatrick if (atomic_load(&stack_switching_, memory_order_relaxed)) 115*d89ec533Spatrick return nullptr; 116*d89ec533Spatrick if (reinterpret_cast<uptr>(fake_stack_) <= 1) 1173cab2bb3Spatrick return AsyncSignalSafeLazyInitFakeStack(); 1183cab2bb3Spatrick return fake_stack_; 1193cab2bb3Spatrick } 1203cab2bb3Spatrick 1213cab2bb3Spatrick // True is this thread is currently unwinding stack (i.e. collecting a stack 1223cab2bb3Spatrick // trace). Used to prevent deadlocks on platforms where libc unwinder calls 1233cab2bb3Spatrick // malloc internally. See PR17116 for more details. isUnwinding()1243cab2bb3Spatrick bool isUnwinding() const { return unwinding_; } setUnwinding(bool b)1253cab2bb3Spatrick void setUnwinding(bool b) { unwinding_ = b; } 1263cab2bb3Spatrick malloc_storage()1273cab2bb3Spatrick AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } stats()1283cab2bb3Spatrick AsanStats &stats() { return stats_; } 1293cab2bb3Spatrick extra_spill_area()1303cab2bb3Spatrick void *extra_spill_area() { return &extra_spill_area_; } 1313cab2bb3Spatrick get_arg()132*d89ec533Spatrick void *get_arg() { return arg_; } 133*d89ec533Spatrick 1343cab2bb3Spatrick private: 1353cab2bb3Spatrick // NOTE: There is no AsanThread constructor. It is allocated 1363cab2bb3Spatrick // via mmap() and *must* be valid in zero-initialized state. 1373cab2bb3Spatrick 1383cab2bb3Spatrick void SetThreadStackAndTls(const InitOptions *options); 1393cab2bb3Spatrick 1403cab2bb3Spatrick void ClearShadowForThreadStackAndTLS(); 1413cab2bb3Spatrick FakeStack *AsyncSignalSafeLazyInitFakeStack(); 1423cab2bb3Spatrick 1433cab2bb3Spatrick struct StackBounds { 1443cab2bb3Spatrick uptr bottom; 1453cab2bb3Spatrick uptr top; 1463cab2bb3Spatrick }; 1473cab2bb3Spatrick StackBounds GetStackBounds() const; 1483cab2bb3Spatrick 1493cab2bb3Spatrick AsanThreadContext *context_; 1503cab2bb3Spatrick thread_callback_t start_routine_; 1513cab2bb3Spatrick void *arg_; 1523cab2bb3Spatrick 1533cab2bb3Spatrick uptr stack_top_; 1543cab2bb3Spatrick uptr stack_bottom_; 1553cab2bb3Spatrick // these variables are used when the thread is about to switch stack 1563cab2bb3Spatrick uptr next_stack_top_; 1573cab2bb3Spatrick uptr next_stack_bottom_; 1583cab2bb3Spatrick // true if switching is in progress 1593cab2bb3Spatrick atomic_uint8_t stack_switching_; 1603cab2bb3Spatrick 1613cab2bb3Spatrick uptr tls_begin_; 1623cab2bb3Spatrick uptr tls_end_; 1633cab2bb3Spatrick DTLS *dtls_; 1643cab2bb3Spatrick 1653cab2bb3Spatrick FakeStack *fake_stack_; 1663cab2bb3Spatrick AsanThreadLocalMallocStorage malloc_storage_; 1673cab2bb3Spatrick AsanStats stats_; 1683cab2bb3Spatrick bool unwinding_; 1693cab2bb3Spatrick uptr extra_spill_area_; 1703cab2bb3Spatrick }; 1713cab2bb3Spatrick 1723cab2bb3Spatrick // Returns a single instance of registry. 1733cab2bb3Spatrick ThreadRegistry &asanThreadRegistry(); 1743cab2bb3Spatrick 1753cab2bb3Spatrick // Must be called under ThreadRegistryLock. 1763cab2bb3Spatrick AsanThreadContext *GetThreadContextByTidLocked(u32 tid); 1773cab2bb3Spatrick 1783cab2bb3Spatrick // Get the current thread. May return 0. 1793cab2bb3Spatrick AsanThread *GetCurrentThread(); 1803cab2bb3Spatrick void SetCurrentThread(AsanThread *t); 1813cab2bb3Spatrick u32 GetCurrentTidOrInvalid(); 1823cab2bb3Spatrick AsanThread *FindThreadByStackAddress(uptr addr); 1833cab2bb3Spatrick 1843cab2bb3Spatrick // Used to handle fork(). 1853cab2bb3Spatrick void EnsureMainThreadIDIsCorrect(); 1863cab2bb3Spatrick } // namespace __asan 1873cab2bb3Spatrick 1883cab2bb3Spatrick #endif // ASAN_THREAD_H 189