asan_thread.cc revision a7e760a53bc43b8e09bfdf5cd6f215267ba99729
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_mapping.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::AsanThread(LinkerInitialized x)
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    : fake_stack_(x),
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      malloc_storage_(x),
251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      stats_(x) { }
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
27a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya SerebryanyAsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *),
28a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany                               void *arg) {
29a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
30a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
31a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  res->start_routine_ = start_routine;
32a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  res->arg_ = arg;
33a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  return res;
341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
36a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() {
371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  fake_stack().Cleanup();
381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // We also clear the shadow on thread destruction because
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // some code may still be executing in later TSD destructors
401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // and we don't want it to have any poisoned stack.
411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ClearShadowForThreadStack();
42a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
43a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  AsanUnmapOrDie(this, size);
441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid AsanThread::ClearShadowForThreadStack() {
471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uintptr_t shadow_bot = MemToShadow(stack_bottom_);
481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uintptr_t shadow_top = MemToShadow(stack_top_);
491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  real_memset((void*)shadow_bot, 0, shadow_top - shadow_bot);
501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
5269eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() {
531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  SetThreadStackTopAndBottom();
541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  fake_stack_.Init(stack_size());
551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_v >= 1) {
561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    int local = 0;
57a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany    Report("T%d: stack [%p,%p) size 0x%lx; local=%p\n",
581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany           tid(), stack_bottom_, stack_top_,
59a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany           stack_top_ - stack_bottom_, &local);
601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  CHECK(AddrIsInMem(stack_bottom_));
631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  CHECK(AddrIsInMem(stack_top_));
641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ClearShadowForThreadStack();
6669eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany}
6769eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany
6869eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid *AsanThread::ThreadStart() {
6969eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany  Init();
701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (!start_routine_) {
721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // start_routine_ == NULL if we're on the main thread or on one of the
731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // OS X libdispatch worker threads. But nobody is supposed to call
741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // ThreadStart() for the worker threads.
751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK(tid() == 0);
761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return 0;
771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  void *res = start_routine_(arg_);
801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  malloc_storage().CommitBack();
811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (FLAG_v >= 1) {
831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    Report("T%d exited\n", tid());
841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return res;
871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) {
901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uintptr_t bottom = 0;
911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  bool is_fake_stack = false;
921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (AddrIsInStack(addr)) {
931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    bottom = stack_bottom();
941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  } else {
951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    bottom = fake_stack().AddrIsInFakeStack(addr);
961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK(bottom);
971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    is_fake_stack = true;
981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1);  // align addr.
1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  uintptr_t *ptr = (uintptr_t*)aligned_addr;
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  while (ptr >= (uintptr_t*)bottom) {
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    if (ptr[0] == kCurrentStackFrameMagic ||
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany        (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)) {
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      *offset = addr - (uintptr_t)ptr;
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      return (const char*)ptr[1];
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    }
1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    ptr--;
1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  *offset = 0;
1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return "UNKNOWN";
1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
114