xref: /openbsd-src/gnu/llvm/compiler-rt/lib/asan/asan_thread.cpp (revision 810390e339a5425391477d5d41c78d7cab2424ac)
13cab2bb3Spatrick //===-- asan_thread.cpp ---------------------------------------------------===//
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 // Thread-related code.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick #include "asan_allocator.h"
143cab2bb3Spatrick #include "asan_interceptors.h"
153cab2bb3Spatrick #include "asan_poisoning.h"
163cab2bb3Spatrick #include "asan_stack.h"
173cab2bb3Spatrick #include "asan_thread.h"
183cab2bb3Spatrick #include "asan_mapping.h"
193cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
203cab2bb3Spatrick #include "sanitizer_common/sanitizer_placement_new.h"
213cab2bb3Spatrick #include "sanitizer_common/sanitizer_stackdepot.h"
223cab2bb3Spatrick #include "sanitizer_common/sanitizer_tls_get_addr.h"
233cab2bb3Spatrick #include "lsan/lsan_common.h"
243cab2bb3Spatrick 
253cab2bb3Spatrick namespace __asan {
263cab2bb3Spatrick 
273cab2bb3Spatrick // AsanThreadContext implementation.
283cab2bb3Spatrick 
OnCreated(void * arg)293cab2bb3Spatrick void AsanThreadContext::OnCreated(void *arg) {
303cab2bb3Spatrick   CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
313cab2bb3Spatrick   if (args->stack)
323cab2bb3Spatrick     stack_id = StackDepotPut(*args->stack);
333cab2bb3Spatrick   thread = args->thread;
343cab2bb3Spatrick   thread->set_context(this);
353cab2bb3Spatrick }
363cab2bb3Spatrick 
OnFinished()373cab2bb3Spatrick void AsanThreadContext::OnFinished() {
383cab2bb3Spatrick   // Drop the link to the AsanThread object.
393cab2bb3Spatrick   thread = nullptr;
403cab2bb3Spatrick }
413cab2bb3Spatrick 
423cab2bb3Spatrick // MIPS requires aligned address
433cab2bb3Spatrick static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
443cab2bb3Spatrick static ThreadRegistry *asan_thread_registry;
453cab2bb3Spatrick 
46*810390e3Srobert static Mutex mu_for_thread_context;
473cab2bb3Spatrick static LowLevelAllocator allocator_for_thread_context;
483cab2bb3Spatrick 
GetAsanThreadContext(u32 tid)493cab2bb3Spatrick static ThreadContextBase *GetAsanThreadContext(u32 tid) {
50*810390e3Srobert   Lock lock(&mu_for_thread_context);
513cab2bb3Spatrick   return new(allocator_for_thread_context) AsanThreadContext(tid);
523cab2bb3Spatrick }
533cab2bb3Spatrick 
asanThreadRegistry()543cab2bb3Spatrick ThreadRegistry &asanThreadRegistry() {
553cab2bb3Spatrick   static bool initialized;
563cab2bb3Spatrick   // Don't worry about thread_safety - this should be called when there is
573cab2bb3Spatrick   // a single thread.
583cab2bb3Spatrick   if (!initialized) {
593cab2bb3Spatrick     // Never reuse ASan threads: we store pointer to AsanThreadContext
603cab2bb3Spatrick     // in TSD and can't reliably tell when no more TSD destructors will
613cab2bb3Spatrick     // be called. It would be wrong to reuse AsanThreadContext for another
623cab2bb3Spatrick     // thread before all TSD destructors will be called for it.
63d89ec533Spatrick     asan_thread_registry =
64d89ec533Spatrick         new (thread_registry_placeholder) ThreadRegistry(GetAsanThreadContext);
653cab2bb3Spatrick     initialized = true;
663cab2bb3Spatrick   }
673cab2bb3Spatrick   return *asan_thread_registry;
683cab2bb3Spatrick }
693cab2bb3Spatrick 
GetThreadContextByTidLocked(u32 tid)703cab2bb3Spatrick AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
713cab2bb3Spatrick   return static_cast<AsanThreadContext *>(
723cab2bb3Spatrick       asanThreadRegistry().GetThreadLocked(tid));
733cab2bb3Spatrick }
743cab2bb3Spatrick 
753cab2bb3Spatrick // AsanThread implementation.
763cab2bb3Spatrick 
Create(thread_callback_t start_routine,void * arg,u32 parent_tid,StackTrace * stack,bool detached)773cab2bb3Spatrick AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg,
783cab2bb3Spatrick                                u32 parent_tid, StackTrace *stack,
793cab2bb3Spatrick                                bool detached) {
803cab2bb3Spatrick   uptr PageSize = GetPageSizeCached();
813cab2bb3Spatrick   uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
823cab2bb3Spatrick   AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__);
833cab2bb3Spatrick   thread->start_routine_ = start_routine;
843cab2bb3Spatrick   thread->arg_ = arg;
853cab2bb3Spatrick   AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
86*810390e3Srobert   asanThreadRegistry().CreateThread(0, detached, parent_tid, &args);
873cab2bb3Spatrick 
883cab2bb3Spatrick   return thread;
893cab2bb3Spatrick }
903cab2bb3Spatrick 
TSDDtor(void * tsd)913cab2bb3Spatrick void AsanThread::TSDDtor(void *tsd) {
923cab2bb3Spatrick   AsanThreadContext *context = (AsanThreadContext*)tsd;
933cab2bb3Spatrick   VReport(1, "T%d TSDDtor\n", context->tid);
943cab2bb3Spatrick   if (context->thread)
953cab2bb3Spatrick     context->thread->Destroy();
963cab2bb3Spatrick }
973cab2bb3Spatrick 
Destroy()983cab2bb3Spatrick void AsanThread::Destroy() {
993cab2bb3Spatrick   int tid = this->tid();
1003cab2bb3Spatrick   VReport(1, "T%d exited\n", tid);
1013cab2bb3Spatrick 
102d89ec533Spatrick   bool was_running =
103d89ec533Spatrick       (asanThreadRegistry().FinishThread(tid) == ThreadStatusRunning);
104d89ec533Spatrick   if (was_running) {
105d89ec533Spatrick     if (AsanThread *thread = GetCurrentThread())
106d89ec533Spatrick       CHECK_EQ(this, thread);
1073cab2bb3Spatrick     malloc_storage().CommitBack();
108d89ec533Spatrick     if (common_flags()->use_sigaltstack)
109d89ec533Spatrick       UnsetAlternateSignalStack();
1103cab2bb3Spatrick     FlushToDeadThreadStats(&stats_);
1113cab2bb3Spatrick     // We also clear the shadow on thread destruction because
1123cab2bb3Spatrick     // some code may still be executing in later TSD destructors
1133cab2bb3Spatrick     // and we don't want it to have any poisoned stack.
1143cab2bb3Spatrick     ClearShadowForThreadStackAndTLS();
1153cab2bb3Spatrick     DeleteFakeStack(tid);
116d89ec533Spatrick   } else {
117d89ec533Spatrick     CHECK_NE(this, GetCurrentThread());
118d89ec533Spatrick   }
1193cab2bb3Spatrick   uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
1203cab2bb3Spatrick   UnmapOrDie(this, size);
121d89ec533Spatrick   if (was_running)
1223cab2bb3Spatrick     DTLS_Destroy();
1233cab2bb3Spatrick }
1243cab2bb3Spatrick 
StartSwitchFiber(FakeStack ** fake_stack_save,uptr bottom,uptr size)1253cab2bb3Spatrick void AsanThread::StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom,
1263cab2bb3Spatrick                                   uptr size) {
1273cab2bb3Spatrick   if (atomic_load(&stack_switching_, memory_order_relaxed)) {
1283cab2bb3Spatrick     Report("ERROR: starting fiber switch while in fiber switch\n");
1293cab2bb3Spatrick     Die();
1303cab2bb3Spatrick   }
1313cab2bb3Spatrick 
1323cab2bb3Spatrick   next_stack_bottom_ = bottom;
1333cab2bb3Spatrick   next_stack_top_ = bottom + size;
1343cab2bb3Spatrick   atomic_store(&stack_switching_, 1, memory_order_release);
1353cab2bb3Spatrick 
1363cab2bb3Spatrick   FakeStack *current_fake_stack = fake_stack_;
1373cab2bb3Spatrick   if (fake_stack_save)
1383cab2bb3Spatrick     *fake_stack_save = fake_stack_;
1393cab2bb3Spatrick   fake_stack_ = nullptr;
1403cab2bb3Spatrick   SetTLSFakeStack(nullptr);
1413cab2bb3Spatrick   // if fake_stack_save is null, the fiber will die, delete the fakestack
1423cab2bb3Spatrick   if (!fake_stack_save && current_fake_stack)
1433cab2bb3Spatrick     current_fake_stack->Destroy(this->tid());
1443cab2bb3Spatrick }
1453cab2bb3Spatrick 
FinishSwitchFiber(FakeStack * fake_stack_save,uptr * bottom_old,uptr * size_old)1463cab2bb3Spatrick void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save,
1473cab2bb3Spatrick                                    uptr *bottom_old,
1483cab2bb3Spatrick                                    uptr *size_old) {
1493cab2bb3Spatrick   if (!atomic_load(&stack_switching_, memory_order_relaxed)) {
1503cab2bb3Spatrick     Report("ERROR: finishing a fiber switch that has not started\n");
1513cab2bb3Spatrick     Die();
1523cab2bb3Spatrick   }
1533cab2bb3Spatrick 
1543cab2bb3Spatrick   if (fake_stack_save) {
1553cab2bb3Spatrick     SetTLSFakeStack(fake_stack_save);
1563cab2bb3Spatrick     fake_stack_ = fake_stack_save;
1573cab2bb3Spatrick   }
1583cab2bb3Spatrick 
1593cab2bb3Spatrick   if (bottom_old)
1603cab2bb3Spatrick     *bottom_old = stack_bottom_;
1613cab2bb3Spatrick   if (size_old)
1623cab2bb3Spatrick     *size_old = stack_top_ - stack_bottom_;
1633cab2bb3Spatrick   stack_bottom_ = next_stack_bottom_;
1643cab2bb3Spatrick   stack_top_ = next_stack_top_;
1653cab2bb3Spatrick   atomic_store(&stack_switching_, 0, memory_order_release);
1663cab2bb3Spatrick   next_stack_top_ = 0;
1673cab2bb3Spatrick   next_stack_bottom_ = 0;
1683cab2bb3Spatrick }
1693cab2bb3Spatrick 
GetStackBounds() const1703cab2bb3Spatrick inline AsanThread::StackBounds AsanThread::GetStackBounds() const {
1713cab2bb3Spatrick   if (!atomic_load(&stack_switching_, memory_order_acquire)) {
1723cab2bb3Spatrick     // Make sure the stack bounds are fully initialized.
1733cab2bb3Spatrick     if (stack_bottom_ >= stack_top_) return {0, 0};
1743cab2bb3Spatrick     return {stack_bottom_, stack_top_};
1753cab2bb3Spatrick   }
1763cab2bb3Spatrick   char local;
1773cab2bb3Spatrick   const uptr cur_stack = (uptr)&local;
1783cab2bb3Spatrick   // Note: need to check next stack first, because FinishSwitchFiber
1793cab2bb3Spatrick   // may be in process of overwriting stack_top_/bottom_. But in such case
1803cab2bb3Spatrick   // we are already on the next stack.
1813cab2bb3Spatrick   if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_)
1823cab2bb3Spatrick     return {next_stack_bottom_, next_stack_top_};
1833cab2bb3Spatrick   return {stack_bottom_, stack_top_};
1843cab2bb3Spatrick }
1853cab2bb3Spatrick 
stack_top()1863cab2bb3Spatrick uptr AsanThread::stack_top() {
1873cab2bb3Spatrick   return GetStackBounds().top;
1883cab2bb3Spatrick }
1893cab2bb3Spatrick 
stack_bottom()1903cab2bb3Spatrick uptr AsanThread::stack_bottom() {
1913cab2bb3Spatrick   return GetStackBounds().bottom;
1923cab2bb3Spatrick }
1933cab2bb3Spatrick 
stack_size()1943cab2bb3Spatrick uptr AsanThread::stack_size() {
1953cab2bb3Spatrick   const auto bounds = GetStackBounds();
1963cab2bb3Spatrick   return bounds.top - bounds.bottom;
1973cab2bb3Spatrick }
1983cab2bb3Spatrick 
199d89ec533Spatrick // We want to create the FakeStack lazily on the first use, but not earlier
2003cab2bb3Spatrick // than the stack size is known and the procedure has to be async-signal safe.
AsyncSignalSafeLazyInitFakeStack()2013cab2bb3Spatrick FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
2023cab2bb3Spatrick   uptr stack_size = this->stack_size();
2033cab2bb3Spatrick   if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
2043cab2bb3Spatrick     return nullptr;
2053cab2bb3Spatrick   uptr old_val = 0;
2063cab2bb3Spatrick   // fake_stack_ has 3 states:
2073cab2bb3Spatrick   // 0   -- not initialized
2083cab2bb3Spatrick   // 1   -- being initialized
2093cab2bb3Spatrick   // ptr -- initialized
2103cab2bb3Spatrick   // This CAS checks if the state was 0 and if so changes it to state 1,
2113cab2bb3Spatrick   // if that was successful, it initializes the pointer.
2123cab2bb3Spatrick   if (atomic_compare_exchange_strong(
2133cab2bb3Spatrick       reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
2143cab2bb3Spatrick       memory_order_relaxed)) {
2153cab2bb3Spatrick     uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
2163cab2bb3Spatrick     CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
2173cab2bb3Spatrick     stack_size_log =
2183cab2bb3Spatrick         Min(stack_size_log, static_cast<uptr>(flags()->max_uar_stack_size_log));
2193cab2bb3Spatrick     stack_size_log =
2203cab2bb3Spatrick         Max(stack_size_log, static_cast<uptr>(flags()->min_uar_stack_size_log));
2213cab2bb3Spatrick     fake_stack_ = FakeStack::Create(stack_size_log);
222d89ec533Spatrick     DCHECK_EQ(GetCurrentThread(), this);
2233cab2bb3Spatrick     SetTLSFakeStack(fake_stack_);
2243cab2bb3Spatrick     return fake_stack_;
2253cab2bb3Spatrick   }
2263cab2bb3Spatrick   return nullptr;
2273cab2bb3Spatrick }
2283cab2bb3Spatrick 
Init(const InitOptions * options)2293cab2bb3Spatrick void AsanThread::Init(const InitOptions *options) {
230d89ec533Spatrick   DCHECK_NE(tid(), kInvalidTid);
2313cab2bb3Spatrick   next_stack_top_ = next_stack_bottom_ = 0;
2323cab2bb3Spatrick   atomic_store(&stack_switching_, false, memory_order_release);
2333cab2bb3Spatrick   CHECK_EQ(this->stack_size(), 0U);
2343cab2bb3Spatrick   SetThreadStackAndTls(options);
2353cab2bb3Spatrick   if (stack_top_ != stack_bottom_) {
2363cab2bb3Spatrick     CHECK_GT(this->stack_size(), 0U);
2373cab2bb3Spatrick     CHECK(AddrIsInMem(stack_bottom_));
2383cab2bb3Spatrick     CHECK(AddrIsInMem(stack_top_ - 1));
2393cab2bb3Spatrick   }
2403cab2bb3Spatrick   ClearShadowForThreadStackAndTLS();
2413cab2bb3Spatrick   fake_stack_ = nullptr;
242d89ec533Spatrick   if (__asan_option_detect_stack_use_after_return &&
243d89ec533Spatrick       tid() == GetCurrentTidOrInvalid()) {
244d89ec533Spatrick     // AsyncSignalSafeLazyInitFakeStack makes use of threadlocals and must be
245d89ec533Spatrick     // called from the context of the thread it is initializing, not its parent.
246d89ec533Spatrick     // Most platforms call AsanThread::Init on the newly-spawned thread, but
247d89ec533Spatrick     // Fuchsia calls this function from the parent thread.  To support that
248d89ec533Spatrick     // approach, we avoid calling AsyncSignalSafeLazyInitFakeStack here; it will
249d89ec533Spatrick     // be called by the new thread when it first attempts to access the fake
250d89ec533Spatrick     // stack.
2513cab2bb3Spatrick     AsyncSignalSafeLazyInitFakeStack();
252d89ec533Spatrick   }
2533cab2bb3Spatrick   int local = 0;
2543cab2bb3Spatrick   VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
2553cab2bb3Spatrick           (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
256*810390e3Srobert           (void *)&local);
2573cab2bb3Spatrick }
2583cab2bb3Spatrick 
259d89ec533Spatrick // Fuchsia doesn't use ThreadStart.
260d89ec533Spatrick // asan_fuchsia.c definies CreateMainThread and SetThreadStackAndTls.
261d89ec533Spatrick #if !SANITIZER_FUCHSIA
2623cab2bb3Spatrick 
ThreadStart(tid_t os_id)263d89ec533Spatrick thread_return_t AsanThread::ThreadStart(tid_t os_id) {
2643cab2bb3Spatrick   Init();
2653cab2bb3Spatrick   asanThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular, nullptr);
2663cab2bb3Spatrick 
2673cab2bb3Spatrick   if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
2683cab2bb3Spatrick 
2693cab2bb3Spatrick   if (!start_routine_) {
2703cab2bb3Spatrick     // start_routine_ == 0 if we're on the main thread or on one of the
2713cab2bb3Spatrick     // OS X libdispatch worker threads. But nobody is supposed to call
2723cab2bb3Spatrick     // ThreadStart() for the worker threads.
2733cab2bb3Spatrick     CHECK_EQ(tid(), 0);
2743cab2bb3Spatrick     return 0;
2753cab2bb3Spatrick   }
2763cab2bb3Spatrick 
2773cab2bb3Spatrick   thread_return_t res = start_routine_(arg_);
2783cab2bb3Spatrick 
2793cab2bb3Spatrick   // On POSIX systems we defer this to the TSD destructor. LSan will consider
2803cab2bb3Spatrick   // the thread's memory as non-live from the moment we call Destroy(), even
2813cab2bb3Spatrick   // though that memory might contain pointers to heap objects which will be
2823cab2bb3Spatrick   // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
2833cab2bb3Spatrick   // the TSD destructors have run might cause false positives in LSan.
2843cab2bb3Spatrick   if (!SANITIZER_POSIX)
2853cab2bb3Spatrick     this->Destroy();
2863cab2bb3Spatrick 
2873cab2bb3Spatrick   return res;
2883cab2bb3Spatrick }
2893cab2bb3Spatrick 
CreateMainThread()2903cab2bb3Spatrick AsanThread *CreateMainThread() {
2913cab2bb3Spatrick   AsanThread *main_thread = AsanThread::Create(
292d89ec533Spatrick       /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid,
2933cab2bb3Spatrick       /* stack */ nullptr, /* detached */ true);
2943cab2bb3Spatrick   SetCurrentThread(main_thread);
295d89ec533Spatrick   main_thread->ThreadStart(internal_getpid());
2963cab2bb3Spatrick   return main_thread;
2973cab2bb3Spatrick }
2983cab2bb3Spatrick 
2993cab2bb3Spatrick // This implementation doesn't use the argument, which is just passed down
3003cab2bb3Spatrick // from the caller of Init (which see, above).  It's only there to support
3013cab2bb3Spatrick // OS-specific implementations that need more information passed through.
SetThreadStackAndTls(const InitOptions * options)3023cab2bb3Spatrick void AsanThread::SetThreadStackAndTls(const InitOptions *options) {
3033cab2bb3Spatrick   DCHECK_EQ(options, nullptr);
3043cab2bb3Spatrick   uptr tls_size = 0;
3053cab2bb3Spatrick   uptr stack_size = 0;
306d89ec533Spatrick   GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
307d89ec533Spatrick                        &tls_begin_, &tls_size);
308*810390e3Srobert   stack_top_ = RoundDownTo(stack_bottom_ + stack_size, ASAN_SHADOW_GRANULARITY);
3093cab2bb3Spatrick   tls_end_ = tls_begin_ + tls_size;
3103cab2bb3Spatrick   dtls_ = DTLS_Get();
3113cab2bb3Spatrick 
3123cab2bb3Spatrick   if (stack_top_ != stack_bottom_) {
3133cab2bb3Spatrick     int local;
3143cab2bb3Spatrick     CHECK(AddrIsInStack((uptr)&local));
3153cab2bb3Spatrick   }
3163cab2bb3Spatrick }
3173cab2bb3Spatrick 
318d89ec533Spatrick #endif  // !SANITIZER_FUCHSIA
3193cab2bb3Spatrick 
ClearShadowForThreadStackAndTLS()3203cab2bb3Spatrick void AsanThread::ClearShadowForThreadStackAndTLS() {
3213cab2bb3Spatrick   if (stack_top_ != stack_bottom_)
3223cab2bb3Spatrick     PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
3233cab2bb3Spatrick   if (tls_begin_ != tls_end_) {
324*810390e3Srobert     uptr tls_begin_aligned = RoundDownTo(tls_begin_, ASAN_SHADOW_GRANULARITY);
325*810390e3Srobert     uptr tls_end_aligned = RoundUpTo(tls_end_, ASAN_SHADOW_GRANULARITY);
326*810390e3Srobert     FastPoisonShadow(tls_begin_aligned, tls_end_aligned - tls_begin_aligned, 0);
3273cab2bb3Spatrick   }
3283cab2bb3Spatrick }
3293cab2bb3Spatrick 
GetStackFrameAccessByAddr(uptr addr,StackFrameAccess * access)3303cab2bb3Spatrick bool AsanThread::GetStackFrameAccessByAddr(uptr addr,
3313cab2bb3Spatrick                                            StackFrameAccess *access) {
3323cab2bb3Spatrick   if (stack_top_ == stack_bottom_)
3333cab2bb3Spatrick     return false;
3343cab2bb3Spatrick 
3353cab2bb3Spatrick   uptr bottom = 0;
3363cab2bb3Spatrick   if (AddrIsInStack(addr)) {
3373cab2bb3Spatrick     bottom = stack_bottom();
338d89ec533Spatrick   } else if (FakeStack *fake_stack = get_fake_stack()) {
339d89ec533Spatrick     bottom = fake_stack->AddrIsInFakeStack(addr);
3403cab2bb3Spatrick     CHECK(bottom);
3413cab2bb3Spatrick     access->offset = addr - bottom;
3423cab2bb3Spatrick     access->frame_pc = ((uptr*)bottom)[2];
3433cab2bb3Spatrick     access->frame_descr = (const char *)((uptr*)bottom)[1];
3443cab2bb3Spatrick     return true;
3453cab2bb3Spatrick   }
3463cab2bb3Spatrick   uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8);  // align addr.
347*810390e3Srobert   uptr mem_ptr = RoundDownTo(aligned_addr, ASAN_SHADOW_GRANULARITY);
3483cab2bb3Spatrick   u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
3493cab2bb3Spatrick   u8 *shadow_bottom = (u8*)MemToShadow(bottom);
3503cab2bb3Spatrick 
3513cab2bb3Spatrick   while (shadow_ptr >= shadow_bottom &&
3523cab2bb3Spatrick          *shadow_ptr != kAsanStackLeftRedzoneMagic) {
3533cab2bb3Spatrick     shadow_ptr--;
354*810390e3Srobert     mem_ptr -= ASAN_SHADOW_GRANULARITY;
3553cab2bb3Spatrick   }
3563cab2bb3Spatrick 
3573cab2bb3Spatrick   while (shadow_ptr >= shadow_bottom &&
3583cab2bb3Spatrick          *shadow_ptr == kAsanStackLeftRedzoneMagic) {
3593cab2bb3Spatrick     shadow_ptr--;
360*810390e3Srobert     mem_ptr -= ASAN_SHADOW_GRANULARITY;
3613cab2bb3Spatrick   }
3623cab2bb3Spatrick 
3633cab2bb3Spatrick   if (shadow_ptr < shadow_bottom) {
3643cab2bb3Spatrick     return false;
3653cab2bb3Spatrick   }
3663cab2bb3Spatrick 
367*810390e3Srobert   uptr *ptr = (uptr *)(mem_ptr + ASAN_SHADOW_GRANULARITY);
3683cab2bb3Spatrick   CHECK(ptr[0] == kCurrentStackFrameMagic);
3693cab2bb3Spatrick   access->offset = addr - (uptr)ptr;
3703cab2bb3Spatrick   access->frame_pc = ptr[2];
3713cab2bb3Spatrick   access->frame_descr = (const char*)ptr[1];
3723cab2bb3Spatrick   return true;
3733cab2bb3Spatrick }
3743cab2bb3Spatrick 
GetStackVariableShadowStart(uptr addr)3753cab2bb3Spatrick uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
3763cab2bb3Spatrick   uptr bottom = 0;
3773cab2bb3Spatrick   if (AddrIsInStack(addr)) {
3783cab2bb3Spatrick     bottom = stack_bottom();
379d89ec533Spatrick   } else if (FakeStack *fake_stack = get_fake_stack()) {
380d89ec533Spatrick     bottom = fake_stack->AddrIsInFakeStack(addr);
381d89ec533Spatrick     if (bottom == 0) {
382d89ec533Spatrick       return 0;
383d89ec533Spatrick     }
3843cab2bb3Spatrick   } else {
3853cab2bb3Spatrick     return 0;
3863cab2bb3Spatrick   }
3873cab2bb3Spatrick 
3883cab2bb3Spatrick   uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8);  // align addr.
3893cab2bb3Spatrick   u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
3903cab2bb3Spatrick   u8 *shadow_bottom = (u8*)MemToShadow(bottom);
3913cab2bb3Spatrick 
3923cab2bb3Spatrick   while (shadow_ptr >= shadow_bottom &&
3933cab2bb3Spatrick          (*shadow_ptr != kAsanStackLeftRedzoneMagic &&
3943cab2bb3Spatrick           *shadow_ptr != kAsanStackMidRedzoneMagic &&
3953cab2bb3Spatrick           *shadow_ptr != kAsanStackRightRedzoneMagic))
3963cab2bb3Spatrick     shadow_ptr--;
3973cab2bb3Spatrick 
3983cab2bb3Spatrick   return (uptr)shadow_ptr + 1;
3993cab2bb3Spatrick }
4003cab2bb3Spatrick 
AddrIsInStack(uptr addr)4013cab2bb3Spatrick bool AsanThread::AddrIsInStack(uptr addr) {
4023cab2bb3Spatrick   const auto bounds = GetStackBounds();
4033cab2bb3Spatrick   return addr >= bounds.bottom && addr < bounds.top;
4043cab2bb3Spatrick }
4053cab2bb3Spatrick 
ThreadStackContainsAddress(ThreadContextBase * tctx_base,void * addr)4063cab2bb3Spatrick static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
4073cab2bb3Spatrick                                        void *addr) {
4083cab2bb3Spatrick   AsanThreadContext *tctx = static_cast<AsanThreadContext *>(tctx_base);
4093cab2bb3Spatrick   AsanThread *t = tctx->thread;
410d89ec533Spatrick   if (!t)
4113cab2bb3Spatrick     return false;
412d89ec533Spatrick   if (t->AddrIsInStack((uptr)addr))
413d89ec533Spatrick     return true;
414d89ec533Spatrick   FakeStack *fake_stack = t->get_fake_stack();
415d89ec533Spatrick   if (!fake_stack)
416d89ec533Spatrick     return false;
417d89ec533Spatrick   return fake_stack->AddrIsInFakeStack((uptr)addr);
4183cab2bb3Spatrick }
4193cab2bb3Spatrick 
GetCurrentThread()4203cab2bb3Spatrick AsanThread *GetCurrentThread() {
4213cab2bb3Spatrick   AsanThreadContext *context =
4223cab2bb3Spatrick       reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
4233cab2bb3Spatrick   if (!context) {
4243cab2bb3Spatrick     if (SANITIZER_ANDROID) {
4253cab2bb3Spatrick       // On Android, libc constructor is called _after_ asan_init, and cleans up
4263cab2bb3Spatrick       // TSD. Try to figure out if this is still the main thread by the stack
4273cab2bb3Spatrick       // address. We are not entirely sure that we have correct main thread
4283cab2bb3Spatrick       // limits, so only do this magic on Android, and only if the found thread
4293cab2bb3Spatrick       // is the main thread.
430d89ec533Spatrick       AsanThreadContext *tctx = GetThreadContextByTidLocked(kMainTid);
4313cab2bb3Spatrick       if (tctx && ThreadStackContainsAddress(tctx, &context)) {
4323cab2bb3Spatrick         SetCurrentThread(tctx->thread);
4333cab2bb3Spatrick         return tctx->thread;
4343cab2bb3Spatrick       }
4353cab2bb3Spatrick     }
4363cab2bb3Spatrick     return nullptr;
4373cab2bb3Spatrick   }
4383cab2bb3Spatrick   return context->thread;
4393cab2bb3Spatrick }
4403cab2bb3Spatrick 
SetCurrentThread(AsanThread * t)4413cab2bb3Spatrick void SetCurrentThread(AsanThread *t) {
4423cab2bb3Spatrick   CHECK(t->context());
443*810390e3Srobert   VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(),
4443cab2bb3Spatrick           (void *)GetThreadSelf());
4453cab2bb3Spatrick   // Make sure we do not reset the current AsanThread.
4463cab2bb3Spatrick   CHECK_EQ(0, AsanTSDGet());
4473cab2bb3Spatrick   AsanTSDSet(t->context());
4483cab2bb3Spatrick   CHECK_EQ(t->context(), AsanTSDGet());
4493cab2bb3Spatrick }
4503cab2bb3Spatrick 
GetCurrentTidOrInvalid()4513cab2bb3Spatrick u32 GetCurrentTidOrInvalid() {
4523cab2bb3Spatrick   AsanThread *t = GetCurrentThread();
4533cab2bb3Spatrick   return t ? t->tid() : kInvalidTid;
4543cab2bb3Spatrick }
4553cab2bb3Spatrick 
FindThreadByStackAddress(uptr addr)4563cab2bb3Spatrick AsanThread *FindThreadByStackAddress(uptr addr) {
4573cab2bb3Spatrick   asanThreadRegistry().CheckLocked();
4583cab2bb3Spatrick   AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
4593cab2bb3Spatrick       asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
4603cab2bb3Spatrick                                                    (void *)addr));
4613cab2bb3Spatrick   return tctx ? tctx->thread : nullptr;
4623cab2bb3Spatrick }
4633cab2bb3Spatrick 
EnsureMainThreadIDIsCorrect()4643cab2bb3Spatrick void EnsureMainThreadIDIsCorrect() {
4653cab2bb3Spatrick   AsanThreadContext *context =
4663cab2bb3Spatrick       reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
467d89ec533Spatrick   if (context && (context->tid == kMainTid))
4683cab2bb3Spatrick     context->os_id = GetTid();
4693cab2bb3Spatrick }
4703cab2bb3Spatrick 
GetAsanThreadByOsIDLocked(tid_t os_id)4713cab2bb3Spatrick __asan::AsanThread *GetAsanThreadByOsIDLocked(tid_t os_id) {
4723cab2bb3Spatrick   __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
4733cab2bb3Spatrick       __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
4743cab2bb3Spatrick   if (!context) return nullptr;
4753cab2bb3Spatrick   return context->thread;
4763cab2bb3Spatrick }
4773cab2bb3Spatrick } // namespace __asan
4783cab2bb3Spatrick 
4793cab2bb3Spatrick // --- Implementation of LSan-specific functions --- {{{1
4803cab2bb3Spatrick namespace __lsan {
LockThreadRegistry()481*810390e3Srobert void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); }
482*810390e3Srobert 
UnlockThreadRegistry()483*810390e3Srobert void UnlockThreadRegistry() { __asan::asanThreadRegistry().Unlock(); }
484*810390e3Srobert 
GetAsanThreadRegistryLocked()485*810390e3Srobert static ThreadRegistry *GetAsanThreadRegistryLocked() {
486*810390e3Srobert   __asan::asanThreadRegistry().CheckLocked();
487*810390e3Srobert   return &__asan::asanThreadRegistry();
488*810390e3Srobert }
489*810390e3Srobert 
EnsureMainThreadIDIsCorrect()490*810390e3Srobert void EnsureMainThreadIDIsCorrect() { __asan::EnsureMainThreadIDIsCorrect(); }
491*810390e3Srobert 
GetThreadRangesLocked(tid_t os_id,uptr * stack_begin,uptr * stack_end,uptr * tls_begin,uptr * tls_end,uptr * cache_begin,uptr * cache_end,DTLS ** dtls)4923cab2bb3Spatrick bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
4933cab2bb3Spatrick                            uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
4943cab2bb3Spatrick                            uptr *cache_end, DTLS **dtls) {
4953cab2bb3Spatrick   __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
4963cab2bb3Spatrick   if (!t) return false;
4973cab2bb3Spatrick   *stack_begin = t->stack_bottom();
4983cab2bb3Spatrick   *stack_end = t->stack_top();
4993cab2bb3Spatrick   *tls_begin = t->tls_begin();
5003cab2bb3Spatrick   *tls_end = t->tls_end();
5013cab2bb3Spatrick   // ASan doesn't keep allocator caches in TLS, so these are unused.
5023cab2bb3Spatrick   *cache_begin = 0;
5033cab2bb3Spatrick   *cache_end = 0;
5043cab2bb3Spatrick   *dtls = t->dtls();
5053cab2bb3Spatrick   return true;
5063cab2bb3Spatrick }
5073cab2bb3Spatrick 
GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> * caches)5081f9cb04fSpatrick void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {}
5091f9cb04fSpatrick 
GetThreadExtraStackRangesLocked(tid_t os_id,InternalMmapVector<Range> * ranges)510*810390e3Srobert void GetThreadExtraStackRangesLocked(tid_t os_id,
511*810390e3Srobert                                      InternalMmapVector<Range> *ranges) {
5123cab2bb3Spatrick   __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
513d89ec533Spatrick   if (!t)
514d89ec533Spatrick     return;
515d89ec533Spatrick   __asan::FakeStack *fake_stack = t->get_fake_stack();
516d89ec533Spatrick   if (!fake_stack)
517d89ec533Spatrick     return;
518*810390e3Srobert 
519*810390e3Srobert   fake_stack->ForEachFakeFrame(
520*810390e3Srobert       [](uptr begin, uptr end, void *arg) {
521*810390e3Srobert         reinterpret_cast<InternalMmapVector<Range> *>(arg)->push_back(
522*810390e3Srobert             {begin, end});
523*810390e3Srobert       },
524*810390e3Srobert       ranges);
5253cab2bb3Spatrick }
5263cab2bb3Spatrick 
GetThreadExtraStackRangesLocked(InternalMmapVector<Range> * ranges)527*810390e3Srobert void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {
528*810390e3Srobert   GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
529*810390e3Srobert       [](ThreadContextBase *tctx, void *arg) {
530*810390e3Srobert         GetThreadExtraStackRangesLocked(
531*810390e3Srobert             tctx->os_id, reinterpret_cast<InternalMmapVector<Range> *>(arg));
532*810390e3Srobert       },
533*810390e3Srobert       ranges);
5343cab2bb3Spatrick }
5353cab2bb3Spatrick 
GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> * ptrs)536*810390e3Srobert void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {
537*810390e3Srobert   GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
538*810390e3Srobert       [](ThreadContextBase *tctx, void *ptrs) {
539*810390e3Srobert         // Look for the arg pointer of threads that have been created or are
540*810390e3Srobert         // running. This is necessary to prevent false positive leaks due to the
541*810390e3Srobert         // AsanThread holding the only live reference to a heap object.  This
542*810390e3Srobert         // can happen because the `pthread_create()` interceptor doesn't wait
543*810390e3Srobert         // for the child thread to start before returning and thus loosing the
544*810390e3Srobert         // the only live reference to the heap object on the stack.
545*810390e3Srobert 
546*810390e3Srobert         __asan::AsanThreadContext *atctx =
547*810390e3Srobert             static_cast<__asan::AsanThreadContext *>(tctx);
548*810390e3Srobert 
549*810390e3Srobert         // Note ThreadStatusRunning is required because there is a small window
550*810390e3Srobert         // where the thread status switches to `ThreadStatusRunning` but the
551*810390e3Srobert         // `arg` pointer still isn't on the stack yet.
552*810390e3Srobert         if (atctx->status != ThreadStatusCreated &&
553*810390e3Srobert             atctx->status != ThreadStatusRunning)
554*810390e3Srobert           return;
555*810390e3Srobert 
556*810390e3Srobert         uptr thread_arg = reinterpret_cast<uptr>(atctx->thread->get_arg());
557*810390e3Srobert         if (!thread_arg)
558*810390e3Srobert           return;
559*810390e3Srobert 
560*810390e3Srobert         auto ptrsVec = reinterpret_cast<InternalMmapVector<uptr> *>(ptrs);
561*810390e3Srobert         ptrsVec->push_back(thread_arg);
562*810390e3Srobert       },
563*810390e3Srobert       ptrs);
5643cab2bb3Spatrick }
5653cab2bb3Spatrick 
GetRunningThreadsLocked(InternalMmapVector<tid_t> * threads)566*810390e3Srobert void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {
567*810390e3Srobert   GetAsanThreadRegistryLocked()->RunCallbackForEachThreadLocked(
568*810390e3Srobert       [](ThreadContextBase *tctx, void *threads) {
569*810390e3Srobert         if (tctx->status == ThreadStatusRunning)
570*810390e3Srobert           reinterpret_cast<InternalMmapVector<tid_t> *>(threads)->push_back(
571*810390e3Srobert               tctx->os_id);
572*810390e3Srobert       },
573*810390e3Srobert       threads);
5743cab2bb3Spatrick }
5753cab2bb3Spatrick 
FinishThreadLocked(u32 tid)576*810390e3Srobert void FinishThreadLocked(u32 tid) {
577*810390e3Srobert   GetAsanThreadRegistryLocked()->FinishThread(tid);
5783cab2bb3Spatrick }
579*810390e3Srobert 
5803cab2bb3Spatrick } // namespace __lsan
5813cab2bb3Spatrick 
5823cab2bb3Spatrick // ---------------------- Interface ---------------- {{{1
5833cab2bb3Spatrick using namespace __asan;
5843cab2bb3Spatrick 
5853cab2bb3Spatrick extern "C" {
5863cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__sanitizer_start_switch_fiber(void ** fakestacksave,const void * bottom,uptr size)5873cab2bb3Spatrick void __sanitizer_start_switch_fiber(void **fakestacksave, const void *bottom,
5883cab2bb3Spatrick                                     uptr size) {
5893cab2bb3Spatrick   AsanThread *t = GetCurrentThread();
5903cab2bb3Spatrick   if (!t) {
5913cab2bb3Spatrick     VReport(1, "__asan_start_switch_fiber called from unknown thread\n");
5923cab2bb3Spatrick     return;
5933cab2bb3Spatrick   }
5943cab2bb3Spatrick   t->StartSwitchFiber((FakeStack**)fakestacksave, (uptr)bottom, size);
5953cab2bb3Spatrick }
5963cab2bb3Spatrick 
5973cab2bb3Spatrick SANITIZER_INTERFACE_ATTRIBUTE
__sanitizer_finish_switch_fiber(void * fakestack,const void ** bottom_old,uptr * size_old)5983cab2bb3Spatrick void __sanitizer_finish_switch_fiber(void* fakestack,
5993cab2bb3Spatrick                                      const void **bottom_old,
6003cab2bb3Spatrick                                      uptr *size_old) {
6013cab2bb3Spatrick   AsanThread *t = GetCurrentThread();
6023cab2bb3Spatrick   if (!t) {
6033cab2bb3Spatrick     VReport(1, "__asan_finish_switch_fiber called from unknown thread\n");
6043cab2bb3Spatrick     return;
6053cab2bb3Spatrick   }
6063cab2bb3Spatrick   t->FinishSwitchFiber((FakeStack*)fakestack,
6073cab2bb3Spatrick                        (uptr*)bottom_old,
6083cab2bb3Spatrick                        (uptr*)size_old);
6093cab2bb3Spatrick }
6103cab2bb3Spatrick }
611