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" 1655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov#include "asan_stack.h" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 18af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany#include "asan_thread_registry.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 20e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include "sanitizer_common/sanitizer_common.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 29e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya SerebryanyAsanThread *AsanThread::Create(u32 parent_tid, thread_callback_t start_routine, 30c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany void *arg, StackTrace *stack) { 313f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr size = RoundUpTo(sizeof(AsanThread), kPageSize); 32a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__); 3355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->start_routine_ = start_routine; 3455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->arg_ = arg; 3555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 366d924facc5c979a0d25f484cffcdb51c766ed551Kostya Serebryany const uptr kSummaryAllocSize = kPageSize; 37b134ffa00ce2a4cbf7f48ac029e31c3e6e23ff6bKostya Serebryany CHECK_LE(sizeof(AsanThreadSummary), kSummaryAllocSize); 386d924facc5c979a0d25f484cffcdb51c766ed551Kostya Serebryany AsanThreadSummary *summary = 396d924facc5c979a0d25f484cffcdb51c766ed551Kostya Serebryany (AsanThreadSummary*)MmapOrDie(kPageSize, "AsanThreadSummary"); 40b134ffa00ce2a4cbf7f48ac029e31c3e6e23ff6bKostya Serebryany summary->Init(parent_tid, stack); 4155cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov summary->set_thread(thread); 4255cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov thread->set_summary(summary); 4355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 4455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov return thread; 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 47f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryanyvoid AsanThreadSummary::TSDDtor(void *tsd) { 48f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany AsanThreadSummary *summary = (AsanThreadSummary*)tsd; 49cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 1) { 50f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany Report("T%d TSDDtor\n", summary->tid()); 51f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 52f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany if (summary->thread()) { 53f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany summary->thread()->Destroy(); 54f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 55f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany} 56f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 57a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() { 58cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 1) { 59f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany Report("T%d exited\n", tid()); 60f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany } 61f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany 62f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany asanThreadRegistry().UnregisterThread(this); 633f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany CHECK(summary()->thread() == 0); 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We also clear the shadow on thread destruction because 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // some code may still be executing in later TSD destructors 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // and we don't want it to have any poisoned stack. 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ClearShadowForThreadStack(); 6855cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov fake_stack().Cleanup(); 693f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr size = RoundUpTo(sizeof(AsanThread), kPageSize); 70a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov UnmapOrDie(this, size); 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 7369eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() { 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany SetThreadStackTopAndBottom(); 7555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov CHECK(AddrIsInMem(stack_bottom_)); 7655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov CHECK(AddrIsInMem(stack_top_)); 7755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov ClearShadowForThreadStack(); 78cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->verbosity >= 1) { 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int local = 0; 80739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", 815bcca4e33ececdddd8e9e07619c129e870492251Alexey Samsonov tid(), (void*)stack_bottom_, (void*)stack_top_, 82a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany stack_top_ - stack_bottom_, &local); 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 8455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov fake_stack_.Init(stack_size()); 8575b19ebf25af204cf209d108997272822241d6daAlexander Potapenko AsanPlatformThreadInit(); 8669eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany} 8769eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany 88600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanovthread_return_t AsanThread::ThreadStart() { 8969eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany Init(); 90cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->use_sigaltstack) SetAlternateSignalStack(); 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!start_routine_) { 933f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany // start_routine_ == 0 if we're on the main thread or on one of the 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // OS X libdispatch worker threads. But nobody is supposed to call 951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // ThreadStart() for the worker threads. 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(tid() == 0); 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return 0; 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 100600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov thread_return_t res = start_routine_(arg_); 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage().CommitBack(); 102cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov if (flags()->use_sigaltstack) UnsetAlternateSignalStack(); 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 104af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany this->Destroy(); 105af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 109e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonovvoid AsanThread::SetThreadStackTopAndBottom() { 110e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_); 111e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov int local; 112e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov CHECK(AddrIsInStack((uptr)&local)); 113e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov} 114e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov 11555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonovvoid AsanThread::ClearShadowForThreadStack() { 11655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); 11755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov} 11855cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov 1193f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) { 1203f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr bottom = 0; 1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bool is_fake_stack = false; 1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (AddrIsInStack(addr)) { 1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = stack_bottom(); 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = fake_stack().AddrIsInFakeStack(addr); 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(bottom); 1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany is_fake_stack = true; 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1293f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 130ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); 131ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany u8 *shadow_bottom = (u8*)MemToShadow(bottom); 1323972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1333972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov while (shadow_ptr >= shadow_bottom && 1343972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *shadow_ptr != kAsanStackLeftRedzoneMagic) { 1353972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov shadow_ptr--; 1363972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov } 1373972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1383972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov while (shadow_ptr >= shadow_bottom && 1393972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *shadow_ptr == kAsanStackLeftRedzoneMagic) { 1403972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov shadow_ptr--; 1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1423972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1433972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov if (shadow_ptr < shadow_bottom) { 1443972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov *offset = 0; 1453972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov return "UNKNOWN"; 1463972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov } 1473972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov 1483f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); 1493972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov CHECK((ptr[0] == kCurrentStackFrameMagic) || 1503972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)); 1513f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany *offset = addr - (uptr)ptr; 1523972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov return (const char*)ptr[1]; 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 156