diff options
Diffstat (limited to 'libsanitizer/asan/asan_thread.cc')
-rw-r--r-- | libsanitizer/asan/asan_thread.cc | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/libsanitizer/asan/asan_thread.cc b/libsanitizer/asan/asan_thread.cc index 1da714c6013..5a9c2dddffb 100644 --- a/libsanitizer/asan/asan_thread.cc +++ b/libsanitizer/asan/asan_thread.cc @@ -17,6 +17,7 @@ #include "asan_mapping.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_placement_new.h" +#include "sanitizer_common/sanitizer_stackdepot.h" #include "lsan/lsan_common.h" namespace __asan { @@ -25,9 +26,8 @@ namespace __asan { void AsanThreadContext::OnCreated(void *arg) { CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg); - if (args->stack) { - internal_memcpy(&stack, args->stack, sizeof(stack)); - } + if (args->stack) + stack_id = StackDepotPut(args->stack->trace, args->stack->size); thread = args->thread; thread->set_context(this); } @@ -41,9 +41,12 @@ void AsanThreadContext::OnFinished() { static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)]; static ThreadRegistry *asan_thread_registry; +static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED); +static LowLevelAllocator allocator_for_thread_context; + static ThreadContextBase *GetAsanThreadContext(u32 tid) { - void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext"); - return new(mem) AsanThreadContext(tid); + BlockingMutexLock lock(&mu_for_thread_context); + return new(allocator_for_thread_context) AsanThreadContext(tid); } ThreadRegistry &asanThreadRegistry() { @@ -76,24 +79,25 @@ AsanThread *AsanThread::Create(thread_callback_t start_routine, AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__); thread->start_routine_ = start_routine; thread->arg_ = arg; - thread->context_ = 0; return thread; } void AsanThread::TSDDtor(void *tsd) { AsanThreadContext *context = (AsanThreadContext*)tsd; - if (flags()->verbosity >= 1) + if (common_flags()->verbosity >= 1) Report("T%d TSDDtor\n", context->tid); if (context->thread) context->thread->Destroy(); } void AsanThread::Destroy() { - if (flags()->verbosity >= 1) { + if (common_flags()->verbosity >= 1) { Report("T%d exited\n", tid()); } + malloc_storage().CommitBack(); + if (flags()->use_sigaltstack) UnsetAlternateSignalStack(); asanThreadRegistry().FinishThread(tid()); FlushToDeadThreadStats(&stats_); // We also clear the shadow on thread destruction because @@ -136,7 +140,7 @@ void AsanThread::Init() { CHECK(AddrIsInMem(stack_bottom_)); CHECK(AddrIsInMem(stack_top_ - 1)); ClearShadowForThreadStackAndTLS(); - if (flags()->verbosity >= 1) { + if (common_flags()->verbosity >= 1) { int local = 0; Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(), (void*)stack_bottom_, (void*)stack_top_, @@ -160,10 +164,14 @@ thread_return_t AsanThread::ThreadStart(uptr os_id) { } thread_return_t res = start_routine_(arg_); - malloc_storage().CommitBack(); - if (flags()->use_sigaltstack) UnsetAlternateSignalStack(); - this->Destroy(); + // On POSIX systems we defer this to the TSD destructor. LSan will consider + // the thread's memory as non-live from the moment we call Destroy(), even + // though that memory might contain pointers to heap objects which will be + // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before + // the TSD destructors have run might cause false positives in LSan. + if (!SANITIZER_POSIX) + this->Destroy(); return res; } @@ -257,7 +265,7 @@ AsanThread *GetCurrentThread() { void SetCurrentThread(AsanThread *t) { CHECK(t->context()); - if (flags()->verbosity >= 2) { + if (common_flags()->verbosity >= 2) { Report("SetCurrentThread: %p for thread %p\n", t->context(), (void*)GetThreadSelf()); } @@ -286,6 +294,13 @@ void EnsureMainThreadIDIsCorrect() { if (context && (context->tid == 0)) context->os_id = GetTid(); } + +__asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) { + __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>( + __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id)); + if (!context) return 0; + return context->thread; +} } // namespace __asan // --- Implementation of LSan-specific functions --- {{{1 @@ -293,10 +308,7 @@ namespace __lsan { bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, uptr *tls_begin, uptr *tls_end, uptr *cache_begin, uptr *cache_end) { - __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>( - __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id)); - if (!context) return false; - __asan::AsanThread *t = context->thread; + __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id); if (!t) return false; *stack_begin = t->stack_bottom(); *stack_end = t->stack_top(); @@ -308,6 +320,13 @@ bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, return true; } +void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback, + void *arg) { + __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id); + if (t && t->has_fake_stack()) + t->fake_stack()->ForEachFakeFrame(callback, arg); +} + void LockThreadRegistry() { __asan::asanThreadRegistry().Lock(); } |