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