11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_thread.h -------------------------------------------*- C++ -*-===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ASan-private header for asan_thread.cc. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 14799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef ASAN_THREAD_H 161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_THREAD_H 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 20244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany#include "asan_fake_stack.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_stats.h" 22e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev#include "sanitizer_common/sanitizer_common.h" 23b134ffa00ce2a4cbf7f48ac029e31c3e6e23ff6bKostya Serebryany#include "sanitizer_common/sanitizer_libc.h" 24def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov#include "sanitizer_common/sanitizer_thread_registry.h" 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 26c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarnamespace __sanitizer { 27c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarstruct DTLS; 28c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar} // namespace __sanitizer 29c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 32e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryanyconst u32 kInvalidTid = 0xffffff; // Must fit into 24 bits. 33def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovconst u32 kMaxNumberOfThreads = (1 << 22); // 4M 34e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyclass AsanThread; 361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// These objects are created for every thread and are never deleted, 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// so we can find them by tid even if the thread is long dead. 39def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovclass AsanThreadContext : public ThreadContextBase { 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany public: 41def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov explicit AsanThreadContext(int tid) 42799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar : ThreadContextBase(tid), announced(false), 43799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar destructor_iterations(GetPthreadDestructorIterations()), stack_id(0), 44799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar thread(nullptr) {} 45def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov bool announced; 466d95869fa900da9ddd68e15e2aa065854cfa176bKostya Serebryany u8 destructor_iterations; 476d95869fa900da9ddd68e15e2aa065854cfa176bKostya Serebryany u32 stack_id; 48def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThread *thread; 49f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 50259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar void OnCreated(void *arg) override; 51259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar void OnFinished() override; 521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 54def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThreadContext objects are never freed, so we need many of them. 556d95869fa900da9ddd68e15e2aa065854cfa176bKostya SerebryanyCOMPILER_CHECK(sizeof(AsanThreadContext) <= 256); 56716e2f25123bf9b20fbc6b582803a3929b78b96dKostya Serebryany 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// AsanThread are stored in TSD and destroyed when the thread dies. 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyclass AsanThread { 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany public: 6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines static AsanThread *Create(thread_callback_t start_routine, void *arg, 6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines u32 parent_tid, StackTrace *stack, bool detached); 62def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov static void TSDDtor(void *tsd); 63a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany void Destroy(); 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 6569eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany void Init(); // Should be called from the thread itself. 6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines thread_return_t ThreadStart(uptr os_id, 6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines atomic_uintptr_t *signal_thread_is_registered); 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 69c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr stack_top(); 70c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr stack_bottom(); 71c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr stack_size(); 7212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev uptr tls_begin() { return tls_begin_; } 7312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev uptr tls_end() { return tls_end_; } 74c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar DTLS *dtls() { return dtls_; } 75def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov u32 tid() { return context_->tid; } 76def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThreadContext *context() { return context_; } 77def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov void set_context(AsanThreadContext *context) { context_ = context; } 781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines struct StackFrameAccess { 806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines uptr offset; 816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines uptr frame_pc; 826d1862363c88c183b0ed7740fca876342cf0474bStephen Hines const char *frame_descr; 836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines }; 846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access); 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 86c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar bool AddrIsInStack(uptr addr); 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void DeleteFakeStack(int tid) { 897a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany if (!fake_stack_) return; 909433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany FakeStack *t = fake_stack_; 91799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar fake_stack_ = nullptr; 92799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar SetTLSFakeStack(nullptr); 932d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines t->Destroy(tid); 94ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany } 95ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany 96c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size); 97c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar void FinishSwitchFiber(FakeStack *fake_stack_save); 98c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 99dcf98bf49d68533c7aebadbf6c4467afdd486c99Kostya Serebryany bool has_fake_stack() { 100c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return !atomic_load(&stack_switching_, memory_order_relaxed) && 101c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar (reinterpret_cast<uptr>(fake_stack_) > 1); 102dcf98bf49d68533c7aebadbf6c4467afdd486c99Kostya Serebryany } 103dcf98bf49d68533c7aebadbf6c4467afdd486c99Kostya Serebryany 104ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany FakeStack *fake_stack() { 105230e52f4e91b53f05ce19dbbf11047f4a0113483Kostya Serebryany if (!__asan_option_detect_stack_use_after_return) 106799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return nullptr; 107c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (atomic_load(&stack_switching_, memory_order_relaxed)) 108c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar return nullptr; 109dcf98bf49d68533c7aebadbf6c4467afdd486c99Kostya Serebryany if (!has_fake_stack()) 110c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany return AsyncSignalSafeLazyInitFakeStack(); 111ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany return fake_stack_; 1127a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany } 1137a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany 11496a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov // True is this thread is currently unwinding stack (i.e. collecting a stack 11596a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov // trace). Used to prevent deadlocks on platforms where libc unwinder calls 11696a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov // malloc internally. See PR17116 for more details. 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines bool isUnwinding() const { return unwinding_; } 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines void setUnwinding(bool b) { unwinding_ = b; } 11996a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov 1206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines // True if we are in a deadly signal handler. 1216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines bool isInDeadlySignal() const { return in_deadly_signal_; } 1226d1862363c88c183b0ed7740fca876342cf0474bStephen Hines void setInDeadlySignal(bool b) { in_deadly_signal_ = b; } 1236d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanStats &stats() { return stats_; } 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany private: 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // NOTE: There is no AsanThread constructor. It is allocated 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines // via mmap() and *must* be valid in zero-initialized state. 13012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev void SetThreadStackAndTls(); 13112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev void ClearShadowForThreadStackAndTLS(); 132c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany FakeStack *AsyncSignalSafeLazyInitFakeStack(); 133c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany 134c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar struct StackBounds { 135c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr bottom; 136c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr top; 137c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar }; 138c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar StackBounds GetStackBounds() const; 139c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 140def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThreadContext *context_; 141600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov thread_callback_t start_routine_; 1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *arg_; 143c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 1442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr stack_top_; 1452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines uptr stack_bottom_; 146c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // these variables are used when the thread is about to switch stack 147c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr next_stack_top_; 148c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar uptr next_stack_bottom_; 149c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar // true if switching is in progress 150c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar atomic_uint8_t stack_switching_; 151c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar 15212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev uptr tls_begin_; 15312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev uptr tls_end_; 154c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar DTLS *dtls_; 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1567a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany FakeStack *fake_stack_; 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanThreadLocalMallocStorage malloc_storage_; 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanStats stats_; 1592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines bool unwinding_; 1606d1862363c88c183b0ed7740fca876342cf0474bStephen Hines bool in_deadly_signal_; 16196a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov}; 16296a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov 16396a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov// ScopedUnwinding is a scope for stacktracing member of a context 16496a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanovclass ScopedUnwinding { 16596a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov public: 16696a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov explicit ScopedUnwinding(AsanThread *t) : thread(t) { 16796a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov t->setUnwinding(true); 16896a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov } 16996a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov ~ScopedUnwinding() { thread->setUnwinding(false); } 17096a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov 17196a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov private: 17296a575f05b2a45774170a118ea69ddae3659b645Evgeniy Stepanov AsanThread *thread; 1731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 1741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1756d1862363c88c183b0ed7740fca876342cf0474bStephen Hines// ScopedDeadlySignal is a scope for handling deadly signals. 1766d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesclass ScopedDeadlySignal { 1776d1862363c88c183b0ed7740fca876342cf0474bStephen Hines public: 1786d1862363c88c183b0ed7740fca876342cf0474bStephen Hines explicit ScopedDeadlySignal(AsanThread *t) : thread(t) { 1796d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (thread) thread->setInDeadlySignal(true); 1806d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 1816d1862363c88c183b0ed7740fca876342cf0474bStephen Hines ~ScopedDeadlySignal() { 1826d1862363c88c183b0ed7740fca876342cf0474bStephen Hines if (thread) thread->setInDeadlySignal(false); 1836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines } 1846d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 1856d1862363c88c183b0ed7740fca876342cf0474bStephen Hines private: 1866d1862363c88c183b0ed7740fca876342cf0474bStephen Hines AsanThread *thread; 1876d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}; 1886d1862363c88c183b0ed7740fca876342cf0474bStephen Hines 189def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// Returns a single instance of registry. 190def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovThreadRegistry &asanThreadRegistry(); 191def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 192def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// Must be called under ThreadRegistryLock. 193def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThreadContext *GetThreadContextByTidLocked(u32 tid); 194def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 19589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov// Get the current thread. May return 0. 19689c1384464848c1ad041becf8b97936fa10de21bAlexey SamsonovAsanThread *GetCurrentThread(); 19789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovvoid SetCurrentThread(AsanThread *t); 19889c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovu32 GetCurrentTidOrInvalid(); 199def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *FindThreadByStackAddress(uptr addr); 20089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov 201c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev// Used to handle fork(). 202c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect(); 203799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} // namespace __asan 2041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 205799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif // ASAN_THREAD_H 206