asan_thread.cc revision 7e8434940a1fe7dce531d4c458ccd714da48f609
1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===-- asan_thread.cc ----------------------------------------------------===//
2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant//                     The LLVM Compiler Infrastructure
4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is distributed under the University of Illinois Open Source
6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// License. See LICENSE.TXT for details.
7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===//
9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
10bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// This file is a part of AddressSanitizer, an address sanity checker.
11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//
12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// Thread-related code.
13bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===//
14bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_allocator.h"
15bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_interceptors.h"
16bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_poisoning.h"
17bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_stack.h"
18bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_thread.h"
19bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_mapping.h"
20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "sanitizer_common/sanitizer_common.h"
21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "sanitizer_common/sanitizer_placement_new.h"
22bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant
23namespace __asan {
24
25// AsanThreadContext implementation.
26
27void AsanThreadContext::OnCreated(void *arg) {
28  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
29  if (args->stack) {
30    internal_memcpy(&stack, args->stack, sizeof(stack));
31  }
32  thread = args->thread;
33  thread->set_context(this);
34}
35
36void AsanThreadContext::OnFinished() {
37  // Drop the link to the AsanThread object.
38  thread = 0;
39}
40
41static char thread_registry_placeholder[sizeof(ThreadRegistry)];
42static ThreadRegistry *asan_thread_registry;
43
44static ThreadContextBase *GetAsanThreadContext(u32 tid) {
45  void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext");
46  return new(mem) AsanThreadContext(tid);
47}
48
49ThreadRegistry &asanThreadRegistry() {
50  static bool initialized;
51  // Don't worry about thread_safety - this should be called when there is
52  // a single thread.
53  if (!initialized) {
54    // Never reuse ASan threads: we store pointer to AsanThreadContext
55    // in TSD and can't reliably tell when no more TSD destructors will
56    // be called. It would be wrong to reuse AsanThreadContext for another
57    // thread before all TSD destructors will be called for it.
58    asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
59        GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
60    initialized = true;
61  }
62  return *asan_thread_registry;
63}
64
65AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
66  return static_cast<AsanThreadContext *>(
67      asanThreadRegistry().GetThreadLocked(tid));
68}
69
70// AsanThread implementation.
71
72AsanThread *AsanThread::Create(thread_callback_t start_routine,
73                               void *arg) {
74  uptr PageSize = GetPageSizeCached();
75  uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
76  AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
77  thread->start_routine_ = start_routine;
78  thread->arg_ = arg;
79  thread->context_ = 0;
80
81  return thread;
82}
83
84void AsanThread::TSDDtor(void *tsd) {
85  AsanThreadContext *context = (AsanThreadContext*)tsd;
86  if (flags()->verbosity >= 1)
87    Report("T%d TSDDtor\n", context->tid);
88  if (context->thread)
89    context->thread->Destroy();
90}
91
92void AsanThread::Destroy() {
93  if (flags()->verbosity >= 1) {
94    Report("T%d exited\n", tid());
95  }
96
97  asanThreadRegistry().FinishThread(tid());
98  FlushToAccumulatedStats(&stats_);
99  // We also clear the shadow on thread destruction because
100  // some code may still be executing in later TSD destructors
101  // and we don't want it to have any poisoned stack.
102  ClearShadowForThreadStack();
103  fake_stack().Cleanup();
104  uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
105  UnmapOrDie(this, size);
106}
107
108void AsanThread::Init() {
109  SetThreadStackTopAndBottom();
110  CHECK(AddrIsInMem(stack_bottom_));
111  CHECK(AddrIsInMem(stack_top_ - 1));
112  ClearShadowForThreadStack();
113  if (flags()->verbosity >= 1) {
114    int local = 0;
115    Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
116           tid(), (void*)stack_bottom_, (void*)stack_top_,
117           stack_top_ - stack_bottom_, &local);
118  }
119  fake_stack_.Init(stack_size());
120  AsanPlatformThreadInit();
121}
122
123thread_return_t AsanThread::ThreadStart(uptr os_id) {
124  Init();
125  asanThreadRegistry().StartThread(tid(), os_id, 0);
126  if (flags()->use_sigaltstack) SetAlternateSignalStack();
127
128  if (!start_routine_) {
129    // start_routine_ == 0 if we're on the main thread or on one of the
130    // OS X libdispatch worker threads. But nobody is supposed to call
131    // ThreadStart() for the worker threads.
132    CHECK(tid() == 0);
133    return 0;
134  }
135
136  thread_return_t res = start_routine_(arg_);
137  malloc_storage().CommitBack();
138  if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
139
140  this->Destroy();
141
142  return res;
143}
144
145void AsanThread::SetThreadStackTopAndBottom() {
146  GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_);
147  int local;
148  CHECK(AddrIsInStack((uptr)&local));
149}
150
151void AsanThread::ClearShadowForThreadStack() {
152  PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
153}
154
155const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
156                                           uptr *frame_pc) {
157  uptr bottom = 0;
158  if (AddrIsInStack(addr)) {
159    bottom = stack_bottom();
160  } else {
161    bottom = fake_stack().AddrIsInFakeStack(addr);
162    CHECK(bottom);
163    *offset = addr - bottom;
164    *frame_pc = ((uptr*)bottom)[2];
165    return  (const char *)((uptr*)bottom)[1];
166  }
167  uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1);  // align addr.
168  u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
169  u8 *shadow_bottom = (u8*)MemToShadow(bottom);
170
171  while (shadow_ptr >= shadow_bottom &&
172         *shadow_ptr != kAsanStackLeftRedzoneMagic) {
173    shadow_ptr--;
174  }
175
176  while (shadow_ptr >= shadow_bottom &&
177         *shadow_ptr == kAsanStackLeftRedzoneMagic) {
178    shadow_ptr--;
179  }
180
181  if (shadow_ptr < shadow_bottom) {
182    *offset = 0;
183    return "UNKNOWN";
184  }
185
186  uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
187  CHECK(ptr[0] == kCurrentStackFrameMagic);
188  *offset = addr - (uptr)ptr;
189  *frame_pc = ptr[2];
190  return (const char*)ptr[1];
191}
192
193static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
194                                       void *addr) {
195  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
196  AsanThread *t = tctx->thread;
197  return (t && t->fake_stack().StackSize() &&
198          (t->fake_stack().AddrIsInFakeStack((uptr)addr) ||
199           t->AddrIsInStack((uptr)addr)));
200}
201
202AsanThread *GetCurrentThread() {
203  AsanThreadContext *context = (AsanThreadContext*)AsanTSDGet();
204  if (!context) {
205    if (SANITIZER_ANDROID) {
206      // On Android, libc constructor is called _after_ asan_init, and cleans up
207      // TSD. Try to figure out if this is still the main thread by the stack
208      // address. We are not entirely sure that we have correct main thread
209      // limits, so only do this magic on Android, and only if the found thread
210      // is the main thread.
211      AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
212      if (ThreadStackContainsAddress(tctx, &context)) {
213        SetCurrentThread(tctx->thread);
214        return tctx->thread;
215      }
216    }
217    return 0;
218  }
219  return context->thread;
220}
221
222void SetCurrentThread(AsanThread *t) {
223  CHECK(t->context());
224  if (flags()->verbosity >= 2) {
225    Report("SetCurrentThread: %p for thread %p\n",
226           t->context(), (void*)GetThreadSelf());
227  }
228  // Make sure we do not reset the current AsanThread.
229  CHECK_EQ(0, AsanTSDGet());
230  AsanTSDSet(t->context());
231  CHECK_EQ(t->context(), AsanTSDGet());
232}
233
234u32 GetCurrentTidOrInvalid() {
235  AsanThread *t = GetCurrentThread();
236  return t ? t->tid() : kInvalidTid;
237}
238
239AsanThread *FindThreadByStackAddress(uptr addr) {
240  asanThreadRegistry().CheckLocked();
241  AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
242      asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
243                                                   (void *)addr));
244  return tctx ? tctx->thread : 0;
245}
246
247}  // namespace __asan
248