asan_thread.cc revision a6b52264e1231bfc4ee9a2d9a4f32678c97295f0
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 Serebryany#include <pthread.h>
211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <stdlib.h>
221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <string.h>
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::AsanThread(LinkerInitialized x)
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    : fake_stack_(x),
281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      malloc_storage_(x),
291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany      stats_(x) { }
301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
31a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya SerebryanyAsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *),
32a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany                               void *arg) {
33a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
34a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
35a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  res->start_routine_ = start_routine;
36a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  res->arg_ = arg;
37a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  return res;
381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
40a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() {
411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  fake_stack().Cleanup();
421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // We also clear the shadow on thread destruction because
431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // some code may still be executing in later TSD destructors
441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // and we don't want it to have any poisoned stack.
451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  ClearShadowForThreadStack();
46a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  size_t size = RoundUpTo(sizeof(AsanThread), kPageSize);
47a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany  AsanUnmapOrDie(this, size);
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 Serebryany}  // namespace __asan
118