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