diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index 2f3a7465ef45..4fafc061708c 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -280,8 +280,8 @@ int WRAP(pthread_create)(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg) { GET_STACK_TRACE_HERE(kStackTraceMax, /*fast_unwind*/false); int current_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); - AsanThread *t = AsanThread::Create(current_tid, start_routine, arg); - asanThreadRegistry().RegisterThread(t, current_tid, &stack); + AsanThread *t = AsanThread::Create(current_tid, start_routine, arg, &stack); + asanThreadRegistry().RegisterThread(t); return real_pthread_create(thread, attr, asan_thread_start, t); } diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index 575eb06d0090..c5af6103777c 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -246,8 +246,8 @@ void asan_dispatch_call_block_and_release(void *block) { } AsanThread *t = asanThreadRegistry().GetCurrent(); if (!t) { - t = AsanThread::Create(context->parent_tid, NULL, NULL); - asanThreadRegistry().RegisterThread(t, context->parent_tid, &stack); + t = AsanThread::Create(context->parent_tid, NULL, NULL, &stack); + asanThreadRegistry().RegisterThread(t); t->Init(); asanThreadRegistry().SetCurrent(t); } diff --git a/compiler-rt/lib/asan/asan_stack.h b/compiler-rt/lib/asan/asan_stack.h index 97aefd6d4218..4b54e084f82a 100644 --- a/compiler-rt/lib/asan/asan_stack.h +++ b/compiler-rt/lib/asan/asan_stack.h @@ -75,6 +75,10 @@ struct AsanStackTrace { } \ } \ +// NOTE: A Rule of thumb is to retrieve stack trace in the interceptors +// as early as possible (in functions exposed to the user), as we generally +// don't want stack trace to contain functions from ASan internals. + #define GET_STACK_TRACE_HERE(max_size, fast_unwind) \ GET_STACK_TRACE_WITH_PC_AND_BP(max_size, fast_unwind, \ AsanStackTrace::GetCurrentPc(), GET_CURRENT_FRAME()) \ diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index 0257e7acdf48..66bb01e23a6e 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -14,6 +14,7 @@ #include "asan_allocator.h" #include "asan_interceptors.h" #include "asan_procmaps.h" +#include "asan_stack.h" #include "asan_thread.h" #include "asan_thread_registry.h" #include "asan_mapping.h" @@ -26,42 +27,41 @@ AsanThread::AsanThread(LinkerInitialized x) stats_(x) { } AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *), - void *arg) { + void *arg, AsanStackTrace *stack) { size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); - AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__); - res->start_routine_ = start_routine; - res->arg_ = arg; - return res; + AsanThread *thread = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__); + thread->start_routine_ = start_routine; + thread->arg_ = arg; + + AsanThreadSummary *summary = new AsanThreadSummary(parent_tid, stack); + summary->set_thread(thread); + thread->set_summary(summary); + + return thread; } void AsanThread::Destroy() { - fake_stack().Cleanup(); // We also clear the shadow on thread destruction because // some code may still be executing in later TSD destructors // and we don't want it to have any poisoned stack. ClearShadowForThreadStack(); + fake_stack().Cleanup(); size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); AsanUnmapOrDie(this, size); } -void AsanThread::ClearShadowForThreadStack() { - PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); -} - void AsanThread::Init() { SetThreadStackTopAndBottom(); - fake_stack_.Init(stack_size()); + CHECK(AddrIsInMem(stack_bottom_)); + CHECK(AddrIsInMem(stack_top_)); + ClearShadowForThreadStack(); if (FLAG_v >= 1) { int local = 0; Report("T%d: stack [%p,%p) size 0x%lx; local=%p\n", tid(), stack_bottom_, stack_top_, stack_top_ - stack_bottom_, &local); } - - CHECK(AddrIsInMem(stack_bottom_)); - CHECK(AddrIsInMem(stack_top_)); - - ClearShadowForThreadStack(); + fake_stack_.Init(stack_size()); } void *AsanThread::ThreadStart() { @@ -88,6 +88,10 @@ void *AsanThread::ThreadStart() { return res; } +void AsanThread::ClearShadowForThreadStack() { + PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); +} + const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { uintptr_t bottom = 0; bool is_fake_stack = false; diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h index a3d0146aa929..45351a7a7af2 100644 --- a/compiler-rt/lib/asan/asan_thread.h +++ b/compiler-rt/lib/asan/asan_thread.h @@ -30,10 +30,10 @@ class AsanThread; class AsanThreadSummary { public: explicit AsanThreadSummary(LinkerInitialized) { } // for T0. - AsanThreadSummary(int tid, int parent_tid, AsanStackTrace *stack) - : tid_(tid), - parent_tid_(parent_tid), + AsanThreadSummary(int parent_tid, AsanStackTrace *stack) + : parent_tid_(parent_tid), announced_(false) { + tid_ = -1; if (stack) { stack_ = *stack; } @@ -48,6 +48,7 @@ class AsanThreadSummary { } } int tid() { return tid_; } + void set_tid(int tid) { tid_ = tid; } AsanThread *thread() { return thread_; } void set_thread(AsanThread *thread) { thread_ = thread; } private: @@ -63,7 +64,7 @@ class AsanThread { public: explicit AsanThread(LinkerInitialized); // for T0. static AsanThread *Create(int parent_tid, void *(*start_routine) (void *), - void *arg); + void *arg, AsanStackTrace *stack); void Destroy(); void Init(); // Should be called from the thread itself. diff --git a/compiler-rt/lib/asan/asan_thread_registry.cc b/compiler-rt/lib/asan/asan_thread_registry.cc index 41119b808384..c8f25d38f408 100644 --- a/compiler-rt/lib/asan/asan_thread_registry.cc +++ b/compiler-rt/lib/asan/asan_thread_registry.cc @@ -35,22 +35,20 @@ void AsanThreadRegistry::Init() { AsanTSDInit(); main_thread_.set_summary(&main_thread_summary_); main_thread_summary_.set_thread(&main_thread_); + RegisterThread(&main_thread_); SetCurrent(&main_thread_); - thread_summaries_[0] = &main_thread_summary_; - n_threads_ = 1; } -void AsanThreadRegistry::RegisterThread(AsanThread *thread, int parent_tid, - AsanStackTrace *stack) { +void AsanThreadRegistry::RegisterThread(AsanThread *thread) { ScopedLock lock(&mu_); - CHECK(n_threads_ > 0); int tid = n_threads_; n_threads_++; CHECK(n_threads_ < kMaxNumberOfThreads); - AsanThreadSummary *summary = new AsanThreadSummary(tid, parent_tid, stack); - summary->set_thread(thread); + + AsanThreadSummary *summary = thread->summary(); + CHECK(summary != NULL); + summary->set_tid(tid); thread_summaries_[tid] = summary; - thread->set_summary(summary); } void AsanThreadRegistry::UnregisterThread(AsanThread *thread) { diff --git a/compiler-rt/lib/asan/asan_thread_registry.h b/compiler-rt/lib/asan/asan_thread_registry.h index 994de98d60f1..b011c29386f5 100644 --- a/compiler-rt/lib/asan/asan_thread_registry.h +++ b/compiler-rt/lib/asan/asan_thread_registry.h @@ -30,8 +30,7 @@ class AsanThreadRegistry { public: explicit AsanThreadRegistry(LinkerInitialized); void Init(); - void RegisterThread(AsanThread *thread, int parent_tid, - AsanStackTrace *stack); + void RegisterThread(AsanThread *thread); void UnregisterThread(AsanThread *thread); AsanThread *GetMain();