asan_thread.cc revision df499b44de81fc757a789878f07fcaf19ebb0016
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" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread_registry.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 21ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany#include <sys/time.h> 22ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany#include <sys/resource.h> 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <pthread.h> 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <stdlib.h> 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <string.h> 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 291e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::AsanThread(LinkerInitialized x) 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany : fake_stack_(x), 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage_(x), 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats_(x) { } 331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::AsanThread(int parent_tid, void *(*start_routine) (void *), 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *arg, AsanStackTrace *stack) 361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany : start_routine_(start_routine), 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany arg_(arg) { 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asanThreadRegistry().RegisterThread(this, parent_tid, stack); 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::~AsanThread() { 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany asanThreadRegistry().UnregisterThread(this); 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany fake_stack().Cleanup(); 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We also clear the shadow on thread destruction because 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // some code may still be executing in later TSD destructors 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // and we don't want it to have any poisoned stack. 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ClearShadowForThreadStack(); 481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid AsanThread::ClearShadowForThreadStack() { 511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t shadow_bot = MemToShadow(stack_bottom_); 521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t shadow_top = MemToShadow(stack_top_); 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany real_memset((void*)shadow_bot, 0, shadow_top - shadow_bot); 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5669eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() { 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany SetThreadStackTopAndBottom(); 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany fake_stack_.Init(stack_size()); 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 1) { 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int local = 0; 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("T%d: stack [%p,%p) size 0x%lx; local=%p, pthread_self=%p\n", 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany tid(), stack_bottom_, stack_top_, 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack_top_ - stack_bottom_, &local, pthread_self()); 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInMem(stack_bottom_)); 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInMem(stack_top_)); 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ClearShadowForThreadStack(); 7069eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany} 7169eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany 7269eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid *AsanThread::ThreadStart() { 7369eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany Init(); 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!start_routine_) { 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // start_routine_ == NULL if we're on the main thread or on one of the 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // OS X libdispatch worker threads. But nobody is supposed to call 781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // ThreadStart() for the worker threads. 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(tid() == 0); 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return 0; 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *res = start_routine_(arg_); 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage().CommitBack(); 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 1) { 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("T%d exited\n", tid()); 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t bottom = 0; 951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bool is_fake_stack = false; 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (AddrIsInStack(addr)) { 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = stack_bottom(); 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = fake_stack().AddrIsInFakeStack(addr); 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(bottom); 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany is_fake_stack = true; 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t *ptr = (uintptr_t*)aligned_addr; 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany while (ptr >= (uintptr_t*)bottom) { 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (ptr[0] == kCurrentStackFrameMagic || 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)) { 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany *offset = addr - (uintptr_t)ptr; 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return (const char*)ptr[1]; 1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ptr--; 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany *offset = 0; 1141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return "UNKNOWN"; 1151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifdef __APPLE__ 1191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t stacksize = pthread_get_stacksize_np(pthread_self()); 1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *stackaddr = pthread_get_stackaddr_np(pthread_self()); 1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack_top_ = (uintptr_t)stackaddr; 1221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack_bottom_ = stack_top_ - stacksize; 1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int local; 1241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInStack((uintptr_t)&local)); 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#else 126ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany if (tid() == 0) { 127ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany // This is the main thread. Libpthread may not be initialized yet. 128ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany struct rlimit rl; 129ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); 130ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany 131ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany // Find the mapping that contains a stack variable. 132df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany AsanProcMaps proc_maps; 133df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany uint64_t start, end, offset; 134ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany uint64_t prev_end = 0; 135df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { 136ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany if ((uintptr_t)&rl < end) 137ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany break; 138ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany prev_end = end; 139ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany } 140ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); 141ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany 142ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany // Get stacksize from rlimit, but clip it so that it does not overlap 143ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany // with other mappings. 144ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany size_t stacksize = rl.rlim_cur; 145ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany if (stacksize > end - prev_end) 146ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany stacksize = end - prev_end; 147ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany if (stacksize > kMaxThreadStackSize) 148ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany stacksize = kMaxThreadStackSize; 149ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany stack_top_ = end; 150ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany stack_bottom_ = end - stacksize; 151ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&rl)); 152ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany return; 153ab9da7ec5e4194ba0d0a90e00e9f29dbc8d34c69Kostya Serebryany } 1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany pthread_attr_t attr; 1551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); 1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_t stacksize = 0; 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *stackaddr = NULL; 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany pthread_attr_getstack(&attr, &stackaddr, &stacksize); 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany pthread_attr_destroy(&attr); 1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack_top_ = (uintptr_t)stackaddr + stacksize; 1621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack_bottom_ = (uintptr_t)stackaddr; 1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // When running with unlimited stack size, we still want to set some limit. 1641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // The unlimited stack size is caused by 'ulimit -s unlimited'. 1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Also, for some reason, GNU make spawns subrocesses with unlimited stack. 1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (stacksize > kMaxThreadStackSize) { 1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stack_bottom_ = stack_top_ - kMaxThreadStackSize; 1681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInStack((uintptr_t)&attr)); 1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif 1711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 174