asan_thread.cc revision ee3925515e4c7966f3ef489f687aa7e5692806a9
1c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//===-- asan_thread.cc ------------------------------------------*- C++ -*-===//
2ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman//
36fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell//                     The LLVM Compiler Infrastructure
46fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
7ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman//
86fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell//===----------------------------------------------------------------------===//
9ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman//
10c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// This file is a part of AddressSanitizer, an address sanity checker.
11c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//
12ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman// Thread-related code.
13cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner//===----------------------------------------------------------------------===//
14cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_allocator.h"
15cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_interceptors.h"
16cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_procmaps.h"
17cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_stack.h"
18fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman#include "asan_thread.h"
19c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene#include "asan_thread_registry.h"
20583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey#include "asan_mapping.h"
214b84086e89d86fb16f562166d9fea8df37db6be7Dan Gohman
22583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskeynamespace __asan {
23b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner
24acaf09dbe4a6781163857db1321bbd5795e7d410Dan GohmanAsanThread::AsanThread(LinkerInitialized x)
255892d47a625638a90afeb31dd4f6f80a2f9bacdeChris Lattner    : fake_stack_(x),
26322812e603705e1c2037313633e72f689524b163Evan Cheng      malloc_storage_(x),
27eb19e40efbd3cae80c908a30cdf4d33450733c45Chris Lattner      stats_(x) { }
28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke
29d0fde30ce850b78371fd1386338350591f9ff494Brian GaekeAsanThread *AsanThread::Create(int parent_tid, thread_callback_t start_routine,
30fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman                               void *arg, AsanStackTrace *stack) {
31fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  uptr size = RoundUpTo(sizeof(AsanThread), kPageSize);
32fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  AsanThread *thread = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
33fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  thread->start_routine_ = start_routine;
34fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  thread->arg_ = arg;
356e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel
36fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  AsanThreadSummary *summary = new AsanThreadSummary(parent_tid, stack);
37fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  summary->set_thread(thread);
38fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  thread->set_summary(summary);
39fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
408e4018e2de52c534405d7155c7009d0b35afb861Cedric Venet  return thread;
418e4018e2de52c534405d7155c7009d0b35afb861Cedric Venet}
42c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif
43fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohmanvoid AsanThreadSummary::TSDDtor(void *tsd) {
44fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  AsanThreadSummary *summary = (AsanThreadSummary*)tsd;
45c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif  if (FLAG_v >= 1) {
46fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    Report("T%d TSDDtor\n", summary->tid());
47fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  }
48fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  if (summary->thread()) {
49c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif    summary->thread()->Destroy();
50c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif  }
51c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif}
52fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
53fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohmanvoid AsanThread::Destroy() {
54fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  if (FLAG_v >= 1) {
55fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    Report("T%d exited\n", tid());
56fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman  }
57fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman
58c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  asanThreadRegistry().UnregisterThread(this);
5925cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  CHECK(summary()->thread() == 0);
6025cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  // We also clear the shadow on thread destruction because
6125cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  // some code may still be executing in later TSD destructors
6225cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  // and we don't want it to have any poisoned stack.
6325cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  ClearShadowForThreadStack();
6425cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands  fake_stack().Cleanup();
65c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  uptr size = RoundUpTo(sizeof(AsanThread), kPageSize);
66c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  AsanUnmapOrDie(this, size);
67c3aae25116e66c177579b0b79182b09340b19753Chris Lattner}
68c3aae25116e66c177579b0b79182b09340b19753Chris Lattner
69c3aae25116e66c177579b0b79182b09340b19753Chris Lattnervoid AsanThread::Init() {
70c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  SetThreadStackTopAndBottom();
71c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  CHECK(AddrIsInMem(stack_bottom_));
72c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  CHECK(AddrIsInMem(stack_top_));
73c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  ClearShadowForThreadStack();
74c3aae25116e66c177579b0b79182b09340b19753Chris Lattner  if (FLAG_v >= 1) {
75cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner    int local = 0;
76cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner    Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
77063287a76b5d1486f498fcf674a26d1155471a3fChris Lattner           tid(), stack_bottom_, stack_top_,
787c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman           stack_top_ - stack_bottom_, &local);
79ead0d88ad7659dabd66cc3149af97d98256fca84Chris Lattner  }
8044c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  fake_stack_.Init(stack_size());
816e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel}
82cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner
83f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohmanthread_return_t AsanThread::ThreadStart() {
84f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  Init();
85f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  if (FLAG_use_sigaltstack) SetAlternateSignalStack();
86f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
87f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  if (!start_routine_) {
88cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner    // start_routine_ == 0 if we're on the main thread or on one of the
89213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner    // OS X libdispatch worker threads. But nobody is supposed to call
90fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    // ThreadStart() for the worker threads.
91fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman    CHECK(tid() == 0);
92f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    return 0;
93f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  }
94f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
95f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  thread_return_t res = start_routine_(arg_);
96f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  malloc_storage().CommitBack();
97f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  if (FLAG_use_sigaltstack) UnsetAlternateSignalStack();
98f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
99f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  this->Destroy();
100691ef2ba066dda14ae4ac0ad645054fbc967785aAndrew Lenharth
101213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner  return res;
102213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner}
103583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey
104213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattnervoid AsanThread::ClearShadowForThreadStack() {
105f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
106f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman}
107f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman
108e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohmanconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) {
109e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman  uptr bottom = 0;
110e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman  bool is_fake_stack = false;
111e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman  if (AddrIsInStack(addr)) {
112d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands    bottom = stack_bottom();
113d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands  } else {
114d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands    bottom = fake_stack().AddrIsInFakeStack(addr);
115c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene    CHECK(bottom);
116c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene    is_fake_stack = true;
117c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  }
118c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif  uptr aligned_addr = addr & ~(__WORDSIZE/8 - 1);  // align addr.
119c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif  u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
120c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene  u8 *shadow_bottom = (u8*)MemToShadow(bottom);
121c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene
122cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  while (shadow_ptr >= shadow_bottom &&
1237c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      *shadow_ptr != kAsanStackLeftRedzoneMagic) {
124cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner    shadow_ptr--;
125cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner  }
1267c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman
1277c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman  while (shadow_ptr >= shadow_bottom &&
1287c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman      *shadow_ptr == kAsanStackLeftRedzoneMagic) {
1296e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel    shadow_ptr--;
1307c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman  }
1317c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman
132f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  if (shadow_ptr < shadow_bottom) {
133f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman    *offset = 0;
1347c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman    return "UNKNOWN";
135f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  }
1367c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman
137063287a76b5d1486f498fcf674a26d1155471a3fChris Lattner  uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
138063287a76b5d1486f498fcf674a26d1155471a3fChris Lattner  CHECK((ptr[0] == kCurrentStackFrameMagic) ||
139ead0d88ad7659dabd66cc3149af97d98256fca84Chris Lattner      (is_fake_stack && ptr[0] == kRetiredStackFrameMagic));
14044c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey  *offset = addr - (uptr)ptr;
14183489bb7700c69b7a4a8da59365c42d3f5c8129bDevang Patel  return (const char*)ptr[1];
142cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner}
143ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey
1441080b9ee534579c67f7c99364cc6fa11edbcd919Chris Lattner}  // namespace __asan
145462dc7f4960e5074ddf4769ec8b2ef1ba7a4d2c8Dan Gohman