diff --git a/compiler-rt/lib/asan/asan_interceptors.cpp b/compiler-rt/lib/asan/asan_interceptors.cpp --- a/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/compiler-rt/lib/asan/asan_interceptors.cpp @@ -223,9 +223,8 @@ auto self = GetThreadSelf(); auto args = asanThreadArgRetval().GetArgs(self); t->ThreadStart(GetTid()); - thread_return_t retval = t->RunThread(); + thread_return_t retval = (*args.routine)(args.arg_retval); asanThreadArgRetval().Finish(self, retval); - CHECK_EQ(args.arg_retval, t->get_arg()); return retval; } @@ -243,8 +242,7 @@ }(); u32 current_tid = GetCurrentTidOrInvalid(); - AsanThread *t = - AsanThread::Create(start_routine, arg, current_tid, &stack, detached); + AsanThread *t = AsanThread::Create(current_tid, &stack, detached); int result; { diff --git a/compiler-rt/lib/asan/asan_mac.cpp b/compiler-rt/lib/asan/asan_mac.cpp --- a/compiler-rt/lib/asan/asan_mac.cpp +++ b/compiler-rt/lib/asan/asan_mac.cpp @@ -154,8 +154,7 @@ void asan_register_worker_thread(int parent_tid, StackTrace *stack) { AsanThread *t = GetCurrentThread(); if (!t) { - t = AsanThread::Create(/* start_routine */ nullptr, /* arg */ nullptr, - parent_tid, stack, /* detached */ true); + t = AsanThread::Create(parent_tid, stack, /* detached */ true); t->Init(); asanThreadRegistry().StartThread(t->tid(), GetTid(), ThreadType::Worker, nullptr); diff --git a/compiler-rt/lib/asan/asan_thread.h b/compiler-rt/lib/asan/asan_thread.h --- a/compiler-rt/lib/asan/asan_thread.h +++ b/compiler-rt/lib/asan/asan_thread.h @@ -59,8 +59,14 @@ // AsanThread are stored in TSD and destroyed when the thread dies. class AsanThread { public: - static AsanThread *Create(thread_callback_t start_routine, void *arg, - u32 parent_tid, StackTrace *stack, bool detached); + template + static AsanThread *Create(const T &data, u32 parent_tid, StackTrace *stack, + bool detached) { + return Create(&data, sizeof(data), parent_tid, stack, detached); + } + static AsanThread *Create(u32 parent_tid, StackTrace *stack, bool detached) { + return Create(nullptr, 0, parent_tid, stack, detached); + } static void TSDDtor(void *tsd); void Destroy(); @@ -131,12 +137,18 @@ void *extra_spill_area() { return &extra_spill_area_; } - void *get_arg() const { return arg_; } + template + void GetStartData(T &data) const { + GetStartData(&data, sizeof(data)); + } private: // NOTE: There is no AsanThread constructor. It is allocated // via mmap() and *must* be valid in zero-initialized state. + static AsanThread *Create(const void *start_data, uptr data_size, + u32 parent_tid, StackTrace *stack, bool detached); + void SetThreadStackAndTls(const InitOptions *options); void ClearShadowForThreadStackAndTLS(); @@ -148,9 +160,9 @@ }; StackBounds GetStackBounds() const; + void GetStartData(void *out, uptr out_size) const; + AsanThreadContext *context_; - thread_callback_t start_routine_; - void *arg_; uptr stack_top_; uptr stack_bottom_; @@ -169,6 +181,8 @@ AsanStats stats_; bool unwinding_; uptr extra_spill_area_; + + char start_data_[]; }; // Returns a single instance of registry. diff --git a/compiler-rt/lib/asan/asan_thread.cpp b/compiler-rt/lib/asan/asan_thread.cpp --- a/compiler-rt/lib/asan/asan_thread.cpp +++ b/compiler-rt/lib/asan/asan_thread.cpp @@ -91,20 +91,27 @@ // AsanThread implementation. -AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg, +AsanThread *AsanThread::Create(const void *start_data, uptr data_size, u32 parent_tid, StackTrace *stack, bool detached) { uptr PageSize = GetPageSizeCached(); uptr size = RoundUpTo(sizeof(AsanThread), PageSize); AsanThread *thread = (AsanThread *)MmapOrDie(size, __func__); - thread->start_routine_ = start_routine; - thread->arg_ = arg; + if (data_size) { + uptr availible_size = (uptr)thread + size - (uptr)(thread->start_data_); + CHECK_LE(data_size, availible_size); + internal_memcpy(thread->start_data_, start_data, data_size); + } AsanThreadContext::CreateThreadContextArgs args = {thread, stack}; asanThreadRegistry().CreateThread(0, detached, parent_tid, &args); return thread; } +void AsanThread::GetStartData(void *out, uptr out_size) const { + internal_memcpy(out, start_data_, out_size); +} + void AsanThread::TSDDtor(void *tsd) { AsanThreadContext *context = (AsanThreadContext *)tsd; VReport(1, "T%d TSDDtor\n", context->tid); @@ -281,11 +288,9 @@ SetAlternateSignalStack(); } -thread_return_t AsanThread::RunThread() { return start_routine_(arg_); } - AsanThread *CreateMainThread() { AsanThread *main_thread = AsanThread::Create( - /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid, + /* parent_tid */ kMainTid, /* stack */ nullptr, /* detached */ true); SetCurrentThread(main_thread); main_thread->ThreadStart(internal_getpid()); diff --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp --- a/compiler-rt/lib/asan/asan_win.cpp +++ b/compiler-rt/lib/asan/asan_win.cpp @@ -131,11 +131,20 @@ } #endif +struct ThreadStartParams { + thread_callback_t start_routine; + void *arg; +}; + static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { AsanThread *t = (AsanThread *)arg; SetCurrentThread(t); t->ThreadStart(GetTid()); - auto res = t->RunThread(); + + ThreadStartParams params; + t->GetStartData(params); + + auto res = (*params.start_routine)(params.arg); t->Destroy(); // POSIX calls this from TSD destructor. return res; } @@ -151,8 +160,8 @@ // one. This is a bandaid fix for PR22025. bool detached = false; // FIXME: how can we determine it on Windows? u32 current_tid = GetCurrentTidOrInvalid(); - AsanThread *t = - AsanThread::Create(start_routine, arg, current_tid, &stack, detached); + ThreadStartParams params = {start_routine, arg}; + AsanThread *t = AsanThread::Create(params, current_tid, &stack, detached); return REAL(CreateThread)(security, stack_size, asan_thread_start, t, thr_flags, tid); }