asan_thread.cc revision e86e35fbe861e73c5991200510a028877427b3e7
1//===-- asan_thread.cc ----------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// Thread-related code.
13//===----------------------------------------------------------------------===//
14#include "asan_allocator.h"
15#include "asan_interceptors.h"
16#include "asan_poisoning.h"
17#include "asan_stack.h"
18#include "asan_thread.h"
19#include "asan_mapping.h"
20#include "sanitizer_common/sanitizer_common.h"
21#include "sanitizer_common/sanitizer_placement_new.h"
22#include "lsan/lsan_common.h"
23
24namespace __asan {
25
26// AsanThreadContext implementation.
27
28void AsanThreadContext::OnCreated(void *arg) {
29  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
30  if (args->stack) {
31    internal_memcpy(&stack, args->stack, sizeof(stack));
32  }
33  thread = args->thread;
34  thread->set_context(this);
35}
36
37void AsanThreadContext::OnFinished() {
38  // Drop the link to the AsanThread object.
39  thread = 0;
40}
41
42// MIPS requires aligned address
43static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
44static ThreadRegistry *asan_thread_registry;
45
46static ThreadContextBase *GetAsanThreadContext(u32 tid) {
47  void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext");
48  return new(mem) AsanThreadContext(tid);
49}
50
51ThreadRegistry &asanThreadRegistry() {
52  static bool initialized;
53  // Don't worry about thread_safety - this should be called when there is
54  // a single thread.
55  if (!initialized) {
56    // Never reuse ASan threads: we store pointer to AsanThreadContext
57    // in TSD and can't reliably tell when no more TSD destructors will
58    // be called. It would be wrong to reuse AsanThreadContext for another
59    // thread before all TSD destructors will be called for it.
60    asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
61        GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
62    initialized = true;
63  }
64  return *asan_thread_registry;
65}
66
67AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
68  return static_cast<AsanThreadContext *>(
69      asanThreadRegistry().GetThreadLocked(tid));
70}
71
72// AsanThread implementation.
73
74AsanThread *AsanThread::Create(thread_callback_t start_routine,
75                               void *arg) {
76  uptr PageSize = GetPageSizeCached();
77  uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
78  AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
79  thread->start_routine_ = start_routine;
80  thread->arg_ = arg;
81  thread->context_ = 0;
82
83  return thread;
84}
85
86void AsanThread::TSDDtor(void *tsd) {
87  AsanThreadContext *context = (AsanThreadContext*)tsd;
88  if (flags()->verbosity >= 1)
89    Report("T%d TSDDtor\n", context->tid);
90  if (context->thread)
91    context->thread->Destroy();
92}
93
94void AsanThread::Destroy() {
95  if (flags()->verbosity >= 1) {
96    Report("T%d exited\n", tid());
97  }
98
99  asanThreadRegistry().FinishThread(tid());
100  FlushToDeadThreadStats(&stats_);
101  // We also clear the shadow on thread destruction because
102  // some code may still be executing in later TSD destructors
103  // and we don't want it to have any poisoned stack.
104  ClearShadowForThreadStackAndTLS();
105  DeleteFakeStack();
106  uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
107  UnmapOrDie(this, size);
108}
109
110// We want to create the FakeStack lazyly on the first use, but not eralier
111// than the stack size is known and the procedure has to be async-signal safe.
112FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
113  uptr stack_size = this->stack_size();
114  if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
115    return 0;
116  uptr old_val = 0;
117  // fake_stack_ has 3 states:
118  // 0   -- not initialized
119  // 1   -- being initialized
120  // ptr -- initialized
121  // This CAS checks if the state was 0 and if so changes it to state 1,
122  // if that was successfull, it initilizes the pointer.
123  if (atomic_compare_exchange_strong(
124      reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
125      memory_order_relaxed)) {
126    uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
127    if (flags()->uar_stack_size_log)
128      stack_size_log = static_cast<uptr>(flags()->uar_stack_size_log);
129    fake_stack_ = FakeStack::Create(stack_size_log);
130    SetTLSFakeStack(fake_stack_);
131    return fake_stack_;
132  }
133  return 0;
134}
135
136void AsanThread::Init() {
137  SetThreadStackAndTls();
138  CHECK(AddrIsInMem(stack_bottom_));
139  CHECK(AddrIsInMem(stack_top_ - 1));
140  ClearShadowForThreadStackAndTLS();
141  if (flags()->verbosity >= 1) {
142    int local = 0;
143    Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
144           tid(), (void*)stack_bottom_, (void*)stack_top_,
145           stack_top_ - stack_bottom_, &local);
146  }
147  fake_stack_ = 0;  // Will be initialized lazily if needed.
148  AsanPlatformThreadInit();
149}
150
151thread_return_t AsanThread::ThreadStart(uptr os_id) {
152  Init();
153  asanThreadRegistry().StartThread(tid(), os_id, 0);
154  if (flags()->use_sigaltstack) SetAlternateSignalStack();
155
156  if (!start_routine_) {
157    // start_routine_ == 0 if we're on the main thread or on one of the
158    // OS X libdispatch worker threads. But nobody is supposed to call
159    // ThreadStart() for the worker threads.
160    CHECK_EQ(tid(), 0);
161    return 0;
162  }
163
164  thread_return_t res = start_routine_(arg_);
165  malloc_storage().CommitBack();
166  if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
167
168  // On POSIX systems we defer this to the TSD destructor. LSan will consider
169  // the thread's memory as non-live from the moment we call Destroy(), even
170  // though that memory might contain pointers to heap objects which will be
171  // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
172  // the TSD destructors have run might cause false positives in LSan.
173  if (!SANITIZER_POSIX)
174    this->Destroy();
175
176  return res;
177}
178
179void AsanThread::SetThreadStackAndTls() {
180  uptr tls_size = 0;
181  GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size_, &tls_begin_,
182                       &tls_size);
183  stack_top_ = stack_bottom_ + stack_size_;
184  tls_end_ = tls_begin_ + tls_size;
185
186  int local;
187  CHECK(AddrIsInStack((uptr)&local));
188}
189
190void AsanThread::ClearShadowForThreadStackAndTLS() {
191  PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
192  if (tls_begin_ != tls_end_)
193    PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0);
194}
195
196const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
197                                           uptr *frame_pc) {
198  uptr bottom = 0;
199  if (AddrIsInStack(addr)) {
200    bottom = stack_bottom();
201  } else if (has_fake_stack()) {
202    bottom = fake_stack()->AddrIsInFakeStack(addr);
203    CHECK(bottom);
204    *offset = addr - bottom;
205    *frame_pc = ((uptr*)bottom)[2];
206    return  (const char *)((uptr*)bottom)[1];
207  }
208  uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1);  // align addr.
209  u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
210  u8 *shadow_bottom = (u8*)MemToShadow(bottom);
211
212  while (shadow_ptr >= shadow_bottom &&
213         *shadow_ptr != kAsanStackLeftRedzoneMagic) {
214    shadow_ptr--;
215  }
216
217  while (shadow_ptr >= shadow_bottom &&
218         *shadow_ptr == kAsanStackLeftRedzoneMagic) {
219    shadow_ptr--;
220  }
221
222  if (shadow_ptr < shadow_bottom) {
223    *offset = 0;
224    return "UNKNOWN";
225  }
226
227  uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
228  CHECK(ptr[0] == kCurrentStackFrameMagic);
229  *offset = addr - (uptr)ptr;
230  *frame_pc = ptr[2];
231  return (const char*)ptr[1];
232}
233
234static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
235                                       void *addr) {
236  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
237  AsanThread *t = tctx->thread;
238  if (!t) return false;
239  if (t->AddrIsInStack((uptr)addr)) return true;
240  if (t->has_fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr))
241    return true;
242  return false;
243}
244
245AsanThread *GetCurrentThread() {
246  AsanThreadContext *context =
247      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
248  if (!context) {
249    if (SANITIZER_ANDROID) {
250      // On Android, libc constructor is called _after_ asan_init, and cleans up
251      // TSD. Try to figure out if this is still the main thread by the stack
252      // address. We are not entirely sure that we have correct main thread
253      // limits, so only do this magic on Android, and only if the found thread
254      // is the main thread.
255      AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
256      if (ThreadStackContainsAddress(tctx, &context)) {
257        SetCurrentThread(tctx->thread);
258        return tctx->thread;
259      }
260    }
261    return 0;
262  }
263  return context->thread;
264}
265
266void SetCurrentThread(AsanThread *t) {
267  CHECK(t->context());
268  if (flags()->verbosity >= 2) {
269    Report("SetCurrentThread: %p for thread %p\n",
270           t->context(), (void*)GetThreadSelf());
271  }
272  // Make sure we do not reset the current AsanThread.
273  CHECK_EQ(0, AsanTSDGet());
274  AsanTSDSet(t->context());
275  CHECK_EQ(t->context(), AsanTSDGet());
276}
277
278u32 GetCurrentTidOrInvalid() {
279  AsanThread *t = GetCurrentThread();
280  return t ? t->tid() : kInvalidTid;
281}
282
283AsanThread *FindThreadByStackAddress(uptr addr) {
284  asanThreadRegistry().CheckLocked();
285  AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
286      asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
287                                                   (void *)addr));
288  return tctx ? tctx->thread : 0;
289}
290
291void EnsureMainThreadIDIsCorrect() {
292  AsanThreadContext *context =
293      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
294  if (context && (context->tid == 0))
295    context->os_id = GetTid();
296}
297}  // namespace __asan
298
299// --- Implementation of LSan-specific functions --- {{{1
300namespace __lsan {
301bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
302                           uptr *tls_begin, uptr *tls_end,
303                           uptr *cache_begin, uptr *cache_end) {
304  __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
305      __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
306  if (!context) return false;
307  __asan::AsanThread *t = context->thread;
308  if (!t) return false;
309  *stack_begin = t->stack_bottom();
310  *stack_end = t->stack_top();
311  *tls_begin = t->tls_begin();
312  *tls_end = t->tls_end();
313  // ASan doesn't keep allocator caches in TLS, so these are unused.
314  *cache_begin = 0;
315  *cache_end = 0;
316  return true;
317}
318
319void LockThreadRegistry() {
320  __asan::asanThreadRegistry().Lock();
321}
322
323void UnlockThreadRegistry() {
324  __asan::asanThreadRegistry().Unlock();
325}
326
327void EnsureMainThreadIDIsCorrect() {
328  __asan::EnsureMainThreadIDIsCorrect();
329}
330}  // namespace __lsan
331