asan_thread.cc revision c98fc1f8e52812cfaf5b19a29db5ed56acb0a682
1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_thread.cc ----------------------------------------------------===// 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// Thread-related code. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 167e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_poisoning.h" 1755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov#include "asan_stack.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 20e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include "sanitizer_common/sanitizer_common.h" 21def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h" 22f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev#include "lsan/lsan_common.h" 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 26def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThreadContext implementation. 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 28def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThreadContext::OnCreated(void *arg) { 29def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg); 30def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (args->stack) { 31def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov internal_memcpy(&stack, args->stack, sizeof(stack)); 32def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov } 33def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov thread = args->thread; 34def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov thread->set_context(this); 35def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 36def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 37def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThreadContext::OnFinished() { 38def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // Drop the link to the AsanThread object. 39def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov thread = 0; 40def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 41def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 4240527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryany// MIPS requires aligned address 437c9ffde46a475d6dd739e977b547c27ac5968976Timur Iskhodzhanovstatic ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)]; 44def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic ThreadRegistry *asan_thread_registry; 45def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 46def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic ThreadContextBase *GetAsanThreadContext(u32 tid) { 47def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext"); 48def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return new(mem) AsanThreadContext(tid); 49def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 50def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 51def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovThreadRegistry &asanThreadRegistry() { 52def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov static bool initialized; 53def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // Don't worry about thread_safety - this should be called when there is 54def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // a single thread. 55def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (!initialized) { 56def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // Never reuse ASan threads: we store pointer to AsanThreadContext 57def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // in TSD and can't reliably tell when no more TSD destructors will 58def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // be called. It would be wrong to reuse AsanThreadContext for another 59def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // thread before all TSD destructors will be called for it. 60def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry( 61def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads); 62def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov initialized = true; 63def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov } 64def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return *asan_thread_registry; 65def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 66def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 67def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThreadContext *GetThreadContextByTidLocked(u32 tid) { 68def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return static_cast<AsanThreadContext *>( 69def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().GetThreadLocked(tid)); 70def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 71def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 72def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThread implementation. 73def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 74def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *AsanThread::Create(thread_callback_t start_routine, 75def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov void *arg) { 76f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr PageSize = GetPageSizeCached(); 77f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr size = RoundUpTo(sizeof(AsanThread), PageSize); 78a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__); 7955cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->start_routine_ = start_routine; 8055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->arg_ = arg; 81def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov thread->context_ = 0; 8255cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 8355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov return thread; 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 86def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThread::TSDDtor(void *tsd) { 87def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThreadContext *context = (AsanThreadContext*)tsd; 88def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (flags()->verbosity >= 1) 89def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov Report("T%d TSDDtor\n", context->tid); 90def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (context->thread) 91def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov context->thread->Destroy(); 92f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany} 93f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 94a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() { 95cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 1) { 96f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany Report("T%d exited\n", tid()); 97f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 98f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 99def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().FinishThread(tid()); 100717ece58e18190c4aef50bd16254db1d74036395Alexey Samsonov FlushToDeadThreadStats(&stats_); 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We also clear the shadow on thread destruction because 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // some code may still be executing in later TSD destructors 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // and we don't want it to have any poisoned stack. 10412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev ClearShadowForThreadStackAndTLS(); 1057a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany DeleteFakeStack(); 106f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached()); 107a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov UnmapOrDie(this, size); 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 110c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany// We want to create the FakeStack lazyly on the first use, but not eralier 111c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany// than the stack size is known and the procedure has to be async-signal safe. 112c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya SerebryanyFakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() { 113c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany uptr stack_size = this->stack_size(); 114c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany if (stack_size == 0) // stack_size is not yet available, don't use FakeStack. 115c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany return 0; 116c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany uptr old_val = 0; 117c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany // fake_stack_ has 3 states: 118c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany // 0 -- not initialized 119c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany // 1 -- being initialized 120c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany // ptr -- initialized 121c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany // This CAS checks if the state was 0 and if so changes it to state 1, 122c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany // if that was successfull, it initilizes the pointer. 123c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany if (atomic_compare_exchange_strong( 124c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL, 125c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany memory_order_relaxed)) 126c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany return fake_stack_ = 127c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany FakeStack::Create(Log2(RoundUpToPowerOfTwo(stack_size))); 128c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany return 0; 129c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany} 130c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany 13169eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() { 13212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev SetThreadStackAndTls(); 13355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov CHECK(AddrIsInMem(stack_bottom_)); 134541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany CHECK(AddrIsInMem(stack_top_ - 1)); 13512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev ClearShadowForThreadStackAndTLS(); 136cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 1) { 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int local = 0; 138739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", 1395bcca4e33ececdddd8e9e07619c129e870492251Alexey Samsonov tid(), (void*)stack_bottom_, (void*)stack_top_, 140a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany stack_top_ - stack_bottom_, &local); 1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1427a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany fake_stack_ = 0; // Will be initialized lazily if needed. 14375b19ebf25af204cf209d108997272822241d6daAlexander Potapenko AsanPlatformThreadInit(); 14469eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany} 14569eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany 146def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovthread_return_t AsanThread::ThreadStart(uptr os_id) { 14769eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany Init(); 148def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().StartThread(tid(), os_id, 0); 149cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->use_sigaltstack) SetAlternateSignalStack(); 1501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!start_routine_) { 1523f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany // start_routine_ == 0 if we're on the main thread or on one of the 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // OS X libdispatch worker threads. But nobody is supposed to call 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // ThreadStart() for the worker threads. 155a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany CHECK_EQ(tid(), 0); 1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return 0; 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 159600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov thread_return_t res = start_routine_(arg_); 1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage().CommitBack(); 161cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->use_sigaltstack) UnsetAlternateSignalStack(); 1621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 163af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany this->Destroy(); 164af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 16812d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveevvoid AsanThread::SetThreadStackAndTls() { 16912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev uptr stack_size = 0, tls_size = 0; 17012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size, &tls_begin_, 17112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev &tls_size); 17212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev stack_top_ = stack_bottom_ + stack_size; 17312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev tls_end_ = tls_begin_ + tls_size; 17412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev 175e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov int local; 176e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(AddrIsInStack((uptr)&local)); 177e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 178e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 17912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveevvoid AsanThread::ClearShadowForThreadStackAndTLS() { 18055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); 18112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev if (tls_begin_ != tls_end_) 18212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0); 18355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov} 18455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 18550f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset, 18650f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany uptr *frame_pc) { 1873f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr bottom = 0; 1881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (AddrIsInStack(addr)) { 1891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = stack_bottom(); 1907a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany } else if (fake_stack()) { 1917a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany bottom = fake_stack()->AddrIsInFakeStack(addr); 1921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(bottom); 193e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko *offset = addr - bottom; 19450f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany *frame_pc = ((uptr*)bottom)[2]; 195e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko return (const char *)((uptr*)bottom)[1]; 1961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1975af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr. 198ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); 199ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany u8 *shadow_bottom = (u8*)MemToShadow(bottom); 2003972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 2013972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov while (shadow_ptr >= shadow_bottom && 202e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko *shadow_ptr != kAsanStackLeftRedzoneMagic) { 2033972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov shadow_ptr--; 2043972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov } 2053972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 2063972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov while (shadow_ptr >= shadow_bottom && 207e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko *shadow_ptr == kAsanStackLeftRedzoneMagic) { 2083972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov shadow_ptr--; 2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 2103972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 2113972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov if (shadow_ptr < shadow_bottom) { 212e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko *offset = 0; 213e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko return "UNKNOWN"; 2143972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov } 2153972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 2163f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); 217e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko CHECK(ptr[0] == kCurrentStackFrameMagic); 2183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany *offset = addr - (uptr)ptr; 21950f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany *frame_pc = ptr[2]; 2203972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov return (const char*)ptr[1]; 2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 223def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic bool ThreadStackContainsAddress(ThreadContextBase *tctx_base, 224def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov void *addr) { 225def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base); 226def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThread *t = tctx->thread; 2277a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany if (!t) return false; 2287a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany if (t->AddrIsInStack((uptr)addr)) return true; 2297a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany if (t->fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr)) 2307a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany return true; 2317a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany return false; 232def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 233def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov 23489c1384464848c1ad041becf8b97936fa10de21bAlexey SamsonovAsanThread *GetCurrentThread() { 235c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev AsanThreadContext *context = 236c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev reinterpret_cast<AsanThreadContext *>(AsanTSDGet()); 237def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (!context) { 238def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (SANITIZER_ANDROID) { 239def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // On Android, libc constructor is called _after_ asan_init, and cleans up 240def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // TSD. Try to figure out if this is still the main thread by the stack 241def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov // address. We are not entirely sure that we have correct main thread 242195369bb7f59896487c4542716ca9c5d53975e78Dmitry Vyukov // limits, so only do this magic on Android, and only if the found thread 243195369bb7f59896487c4542716ca9c5d53975e78Dmitry Vyukov // is the main thread. 244def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThreadContext *tctx = GetThreadContextByTidLocked(0); 245def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov if (ThreadStackContainsAddress(tctx, &context)) { 246def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov SetCurrentThread(tctx->thread); 247def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return tctx->thread; 248def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov } 24989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov } 25089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov return 0; 25189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov } 252def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return context->thread; 25389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov} 25489c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov 25589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovvoid SetCurrentThread(AsanThread *t) { 256def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CHECK(t->context()); 25789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov if (flags()->verbosity >= 2) { 25889c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov Report("SetCurrentThread: %p for thread %p\n", 259def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov t->context(), (void*)GetThreadSelf()); 26089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov } 26189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov // Make sure we do not reset the current AsanThread. 262def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CHECK_EQ(0, AsanTSDGet()); 263def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanTSDSet(t->context()); 264def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov CHECK_EQ(t->context(), AsanTSDGet()); 26589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov} 26689c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov 26789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovu32 GetCurrentTidOrInvalid() { 26889c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov AsanThread *t = GetCurrentThread(); 26989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov return t ? t->tid() : kInvalidTid; 27089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov} 27189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov 272def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *FindThreadByStackAddress(uptr addr) { 273def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().CheckLocked(); 274def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov AsanThreadContext *tctx = static_cast<AsanThreadContext *>( 275def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress, 276def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov (void *)addr)); 277def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov return tctx ? tctx->thread : 0; 278def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov} 279c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev 280c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect() { 281c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev AsanThreadContext *context = 282c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev reinterpret_cast<AsanThreadContext *>(AsanTSDGet()); 283c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev if (context && (context->tid == 0)) 284c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev context->os_id = GetTid(); 285c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev} 2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 287f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev 288f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev// --- Implementation of LSan-specific functions --- {{{1 289f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevnamespace __lsan { 290f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end, 291f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev uptr *tls_begin, uptr *tls_end, 292f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev uptr *cache_begin, uptr *cache_end) { 29312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>( 29412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id)); 29512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev if (!context) return false; 29612d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev __asan::AsanThread *t = context->thread; 29712d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev if (!t) return false; 29812d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev *stack_begin = t->stack_bottom(); 29912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev *stack_end = t->stack_top(); 30012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev *tls_begin = t->tls_begin(); 30112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev *tls_end = t->tls_end(); 30212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev // ASan doesn't keep allocator caches in TLS, so these are unused. 30312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev *cache_begin = 0; 30412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev *cache_end = 0; 30512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev return true; 306f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev} 307f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev 308f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevvoid LockThreadRegistry() { 309f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev __asan::asanThreadRegistry().Lock(); 310f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev} 311f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev 312f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevvoid UnlockThreadRegistry() { 313f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev __asan::asanThreadRegistry().Unlock(); 314f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev} 315c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev 316c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect() { 317c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev __asan::EnsureMainThreadIDIsCorrect(); 318c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev} 319f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev} // namespace __lsan 320