asan_thread.cc revision 3972ea03aa52d81ca324945ba94eea22d403df12
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_thread.cc ------------------------------------------*- C++ -*-===// 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" 16df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_procmaps.h" 1755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov#include "asan_stack.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 19af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany#include "asan_thread_registry.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::AsanThread(LinkerInitialized x) 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany : fake_stack_(x), 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage_(x), 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats_(x) { } 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 29600972e3427173cc8904d741decd1af0ed5de9fdTimur IskhodzhanovAsanThread *AsanThread::Create(int parent_tid, thread_callback_t start_routine, 3055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov void *arg, AsanStackTrace *stack) { 31a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); 3255cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov AsanThread *thread = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__); 3355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->start_routine_ = start_routine; 3455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->arg_ = arg; 3555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 3655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov AsanThreadSummary *summary = new AsanThreadSummary(parent_tid, stack); 3755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov summary->set_thread(thread); 3855cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->set_summary(summary); 3955cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 4055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov return thread; 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 43f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryanyvoid AsanThreadSummary::TSDDtor(void *tsd) { 44f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany AsanThreadSummary *summary = (AsanThreadSummary*)tsd; 45f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany if (FLAG_v >= 1) { 46f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany Report("T%d TSDDtor\n", summary->tid()); 47f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 48f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany if (summary->thread()) { 49f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany summary->thread()->Destroy(); 50f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 51f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany} 52f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 53a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() { 54f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany if (FLAG_v >= 1) { 55f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany Report("T%d exited\n", tid()); 56f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 57f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 58f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany asanThreadRegistry().UnregisterThread(this); 59f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany CHECK(summary()->thread() == NULL); 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We also clear the shadow on thread destruction because 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // some code may still be executing in later TSD destructors 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // and we don't want it to have any poisoned stack. 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ClearShadowForThreadStack(); 6455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov fake_stack().Cleanup(); 65a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); 66a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany AsanUnmapOrDie(this, size); 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 6969eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() { 701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany SetThreadStackTopAndBottom(); 7155cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov CHECK(AddrIsInMem(stack_bottom_)); 7255cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov CHECK(AddrIsInMem(stack_top_)); 7355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov ClearShadowForThreadStack(); 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 1) { 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int local = 0; 76739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany tid(), stack_bottom_, stack_top_, 78a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany stack_top_ - stack_bottom_, &local); 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 8055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov fake_stack_.Init(stack_size()); 8169eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany} 8269eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany 83600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovthread_return_t AsanThread::ThreadStart() { 8469eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany Init(); 85f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko if (FLAG_use_sigaltstack) SetAlternateSignalStack(); 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!start_routine_) { 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // start_routine_ == NULL if we're on the main thread or on one of the 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // OS X libdispatch worker threads. But nobody is supposed to call 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // ThreadStart() for the worker threads. 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(tid() == 0); 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return 0; 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 95600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov thread_return_t res = start_routine_(arg_); 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage().CommitBack(); 97f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko if (FLAG_use_sigaltstack) UnsetAlternateSignalStack(); 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 99af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany this->Destroy(); 100af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 10455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonovvoid AsanThread::ClearShadowForThreadStack() { 10555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); 10655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov} 10755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t bottom = 0; 1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bool is_fake_stack = false; 1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (AddrIsInStack(addr)) { 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = stack_bottom(); 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = fake_stack().AddrIsInFakeStack(addr); 1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(bottom); 1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany is_fake_stack = true; 1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 1193972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov uint8_t *shadow_ptr = (uint8_t*)MemToShadow(aligned_addr); 1203972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov uint8_t *shadow_bottom = (uint8_t*)MemToShadow(bottom); 1213972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1223972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov while (shadow_ptr >= shadow_bottom && 1233972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *shadow_ptr != kAsanStackLeftRedzoneMagic) { 1243972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov shadow_ptr--; 1253972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov } 1263972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1273972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov while (shadow_ptr >= shadow_bottom && 1283972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *shadow_ptr == kAsanStackLeftRedzoneMagic) { 1293972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov shadow_ptr--; 1301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1313972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1323972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov if (shadow_ptr < shadow_bottom) { 1333972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *offset = 0; 1343972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov return "UNKNOWN"; 1353972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov } 1363972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1373972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov uintptr_t* ptr = (uintptr_t*)SHADOW_TO_MEM((uintptr_t)(shadow_ptr + 1)); 1383972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov CHECK((ptr[0] == kCurrentStackFrameMagic) || 1393972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)); 1403972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *offset = addr - (uintptr_t)ptr; 1413972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov return (const char*)ptr[1]; 1421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 145