asan_thread.cpp revision 1.1 1 1.1 mrg //===-- asan_thread.cpp ---------------------------------------------------===//
2 1.1 mrg //
3 1.1 mrg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 1.1 mrg // See https://llvm.org/LICENSE.txt for license information.
5 1.1 mrg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 1.1 mrg //
7 1.1 mrg //===----------------------------------------------------------------------===//
8 1.1 mrg //
9 1.1 mrg // This file is a part of AddressSanitizer, an address sanity checker.
10 1.1 mrg //
11 1.1 mrg // Thread-related code.
12 1.1 mrg //===----------------------------------------------------------------------===//
13 1.1 mrg #include "asan_allocator.h"
14 1.1 mrg #include "asan_interceptors.h"
15 1.1 mrg #include "asan_poisoning.h"
16 1.1 mrg #include "asan_stack.h"
17 1.1 mrg #include "asan_thread.h"
18 1.1 mrg #include "asan_mapping.h"
19 1.1 mrg #include "sanitizer_common/sanitizer_common.h"
20 1.1 mrg #include "sanitizer_common/sanitizer_placement_new.h"
21 1.1 mrg #include "sanitizer_common/sanitizer_stackdepot.h"
22 1.1 mrg #include "sanitizer_common/sanitizer_tls_get_addr.h"
23 1.1 mrg #include "lsan/lsan_common.h"
24 1.1 mrg
25 1.1 mrg namespace __asan {
26 1.1 mrg
27 1.1 mrg // AsanThreadContext implementation.
28 1.1 mrg
29 1.1 mrg void AsanThreadContext::OnCreated(void *arg) {
30 1.1 mrg CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
31 1.1 mrg if (args->stack)
32 1.1 mrg stack_id = StackDepotPut(*args->stack);
33 1.1 mrg thread = args->thread;
34 1.1 mrg thread->set_context(this);
35 1.1 mrg }
36 1.1 mrg
37 1.1 mrg void AsanThreadContext::OnFinished() {
38 1.1 mrg // Drop the link to the AsanThread object.
39 1.1 mrg thread = nullptr;
40 1.1 mrg }
41 1.1 mrg
42 1.1 mrg // MIPS requires aligned address
43 1.1 mrg static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
44 1.1 mrg static ThreadRegistry *asan_thread_registry;
45 1.1 mrg
46 1.1 mrg static Mutex mu_for_thread_context;
47 1.1 mrg static LowLevelAllocator allocator_for_thread_context;
48 1.1 mrg
49 1.1 mrg static ThreadContextBase *GetAsanThreadContext(u32 tid) {
50 1.1 mrg Lock lock(&mu_for_thread_context);
51 1.1 mrg return new(allocator_for_thread_context) AsanThreadContext(tid);
52 1.1 mrg }
53 1.1 mrg
54 1.1 mrg ThreadRegistry &asanThreadRegistry() {
55 1.1 mrg static bool initialized;
56 1.1 mrg // Don't worry about thread_safety - this should be called when there is
57 1.1 mrg // a single thread.
58 1.1 mrg if (!initialized) {
59 1.1 mrg // Never reuse ASan threads: we store pointer to AsanThreadContext
60 1.1 mrg // in TSD and can't reliably tell when no more TSD destructors will
61 1.1 mrg // be called. It would be wrong to reuse AsanThreadContext for another
62 1.1 mrg // thread before all TSD destructors will be called for it.
63 1.1 mrg asan_thread_registry =
64 1.1 mrg new (thread_registry_placeholder) ThreadRegistry(GetAsanThreadContext);
65 1.1 mrg initialized = true;
66 1.1 mrg }
67 1.1 mrg return *asan_thread_registry;
68 1.1 mrg }
69 1.1 mrg
70 1.1 mrg AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
71 1.1 mrg return static_cast<AsanThreadContext *>(
72 1.1 mrg asanThreadRegistry().GetThreadLocked(tid));
73 1.1 mrg }
74 1.1 mrg
75 1.1 mrg // AsanThread implementation.
76 1.1 mrg
77 1.1 mrg AsanThread *AsanThread::Create(thread_callback_t start_routine, void *arg,
78 1.1 mrg u32 parent_tid, StackTrace *stack,
79 1.1 mrg bool detached) {
80 1.1 mrg uptr PageSize = GetPageSizeCached();
81 1.1 mrg uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
82 1.1 mrg AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__);
83 1.1 mrg thread->start_routine_ = start_routine;
84 1.1 mrg thread->arg_ = arg;
85 1.1 mrg AsanThreadContext::CreateThreadContextArgs args = {thread, stack};
86 1.1 mrg asanThreadRegistry().CreateThread(*reinterpret_cast<uptr *>(thread), detached,
87 1.1 mrg parent_tid, &args);
88 1.1 mrg
89 1.1 mrg return thread;
90 1.1 mrg }
91 1.1 mrg
92 1.1 mrg void AsanThread::TSDDtor(void *tsd) {
93 1.1 mrg AsanThreadContext *context = (AsanThreadContext*)tsd;
94 1.1 mrg VReport(1, "T%d TSDDtor\n", context->tid);
95 1.1 mrg if (context->thread)
96 1.1 mrg context->thread->Destroy();
97 1.1 mrg }
98 1.1 mrg
99 1.1 mrg void AsanThread::Destroy() {
100 1.1 mrg int tid = this->tid();
101 1.1 mrg VReport(1, "T%d exited\n", tid);
102 1.1 mrg
103 1.1 mrg bool was_running =
104 1.1 mrg (asanThreadRegistry().FinishThread(tid) == ThreadStatusRunning);
105 1.1 mrg if (was_running) {
106 1.1 mrg if (AsanThread *thread = GetCurrentThread())
107 1.1 mrg CHECK_EQ(this, thread);
108 1.1 mrg malloc_storage().CommitBack();
109 1.1 mrg if (common_flags()->use_sigaltstack)
110 1.1 mrg UnsetAlternateSignalStack();
111 1.1 mrg FlushToDeadThreadStats(&stats_);
112 1.1 mrg // We also clear the shadow on thread destruction because
113 1.1 mrg // some code may still be executing in later TSD destructors
114 1.1 mrg // and we don't want it to have any poisoned stack.
115 1.1 mrg ClearShadowForThreadStackAndTLS();
116 1.1 mrg DeleteFakeStack(tid);
117 1.1 mrg } else {
118 1.1 mrg CHECK_NE(this, GetCurrentThread());
119 1.1 mrg }
120 1.1 mrg uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
121 1.1 mrg UnmapOrDie(this, size);
122 1.1 mrg if (was_running)
123 1.1 mrg DTLS_Destroy();
124 1.1 mrg }
125 1.1 mrg
126 1.1 mrg void AsanThread::StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom,
127 1.1 mrg uptr size) {
128 1.1 mrg if (atomic_load(&stack_switching_, memory_order_relaxed)) {
129 1.1 mrg Report("ERROR: starting fiber switch while in fiber switch\n");
130 1.1 mrg Die();
131 1.1 mrg }
132 1.1 mrg
133 1.1 mrg next_stack_bottom_ = bottom;
134 1.1 mrg next_stack_top_ = bottom + size;
135 1.1 mrg atomic_store(&stack_switching_, 1, memory_order_release);
136 1.1 mrg
137 1.1 mrg FakeStack *current_fake_stack = fake_stack_;
138 1.1 mrg if (fake_stack_save)
139 1.1 mrg *fake_stack_save = fake_stack_;
140 1.1 mrg fake_stack_ = nullptr;
141 1.1 mrg SetTLSFakeStack(nullptr);
142 1.1 mrg // if fake_stack_save is null, the fiber will die, delete the fakestack
143 1.1 mrg if (!fake_stack_save && current_fake_stack)
144 1.1 mrg current_fake_stack->Destroy(this->tid());
145 1.1 mrg }
146 1.1 mrg
147 1.1 mrg void AsanThread::FinishSwitchFiber(FakeStack *fake_stack_save,
148 1.1 mrg uptr *bottom_old,
149 1.1 mrg uptr *size_old) {
150 1.1 mrg if (!atomic_load(&stack_switching_, memory_order_relaxed)) {
151 1.1 mrg Report("ERROR: finishing a fiber switch that has not started\n");
152 1.1 mrg Die();
153 1.1 mrg }
154 1.1 mrg
155 1.1 mrg if (fake_stack_save) {
156 1.1 mrg SetTLSFakeStack(fake_stack_save);
157 1.1 mrg fake_stack_ = fake_stack_save;
158 1.1 mrg }
159 1.1 mrg
160 1.1 mrg if (bottom_old)
161 1.1 mrg *bottom_old = stack_bottom_;
162 1.1 mrg if (size_old)
163 1.1 mrg *size_old = stack_top_ - stack_bottom_;
164 1.1 mrg stack_bottom_ = next_stack_bottom_;
165 1.1 mrg stack_top_ = next_stack_top_;
166 1.1 mrg atomic_store(&stack_switching_, 0, memory_order_release);
167 1.1 mrg next_stack_top_ = 0;
168 1.1 mrg next_stack_bottom_ = 0;
169 1.1 mrg }
170 1.1 mrg
171 1.1 mrg inline AsanThread::StackBounds AsanThread::GetStackBounds() const {
172 1.1 mrg if (!atomic_load(&stack_switching_, memory_order_acquire)) {
173 1.1 mrg // Make sure the stack bounds are fully initialized.
174 1.1 mrg if (stack_bottom_ >= stack_top_) return {0, 0};
175 1.1 mrg return {stack_bottom_, stack_top_};
176 1.1 mrg }
177 1.1 mrg char local;
178 1.1 mrg const uptr cur_stack = (uptr)&local;
179 1.1 mrg // Note: need to check next stack first, because FinishSwitchFiber
180 1.1 mrg // may be in process of overwriting stack_top_/bottom_. But in such case
181 1.1 mrg // we are already on the next stack.
182 1.1 mrg if (cur_stack >= next_stack_bottom_ && cur_stack < next_stack_top_)
183 1.1 mrg return {next_stack_bottom_, next_stack_top_};
184 1.1 mrg return {stack_bottom_, stack_top_};
185 1.1 mrg }
186 1.1 mrg
187 1.1 mrg uptr AsanThread::stack_top() {
188 1.1 mrg return GetStackBounds().top;
189 1.1 mrg }
190 1.1 mrg
191 1.1 mrg uptr AsanThread::stack_bottom() {
192 1.1 mrg return GetStackBounds().bottom;
193 1.1 mrg }
194 1.1 mrg
195 1.1 mrg uptr AsanThread::stack_size() {
196 1.1 mrg const auto bounds = GetStackBounds();
197 1.1 mrg return bounds.top - bounds.bottom;
198 1.1 mrg }
199 1.1 mrg
200 1.1 mrg // We want to create the FakeStack lazily on the first use, but not earlier
201 1.1 mrg // than the stack size is known and the procedure has to be async-signal safe.
202 1.1 mrg FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
203 1.1 mrg uptr stack_size = this->stack_size();
204 1.1 mrg if (stack_size == 0) // stack_size is not yet available, don't use FakeStack.
205 1.1 mrg return nullptr;
206 1.1 mrg uptr old_val = 0;
207 1.1 mrg // fake_stack_ has 3 states:
208 1.1 mrg // 0 -- not initialized
209 1.1 mrg // 1 -- being initialized
210 1.1 mrg // ptr -- initialized
211 1.1 mrg // This CAS checks if the state was 0 and if so changes it to state 1,
212 1.1 mrg // if that was successful, it initializes the pointer.
213 1.1 mrg if (atomic_compare_exchange_strong(
214 1.1 mrg reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
215 1.1 mrg memory_order_relaxed)) {
216 1.1 mrg uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
217 1.1 mrg CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
218 1.1 mrg stack_size_log =
219 1.1 mrg Min(stack_size_log, static_cast<uptr>(flags()->max_uar_stack_size_log));
220 1.1 mrg stack_size_log =
221 1.1 mrg Max(stack_size_log, static_cast<uptr>(flags()->min_uar_stack_size_log));
222 1.1 mrg fake_stack_ = FakeStack::Create(stack_size_log);
223 1.1 mrg DCHECK_EQ(GetCurrentThread(), this);
224 1.1 mrg SetTLSFakeStack(fake_stack_);
225 1.1 mrg return fake_stack_;
226 1.1 mrg }
227 1.1 mrg return nullptr;
228 1.1 mrg }
229 1.1 mrg
230 1.1 mrg void AsanThread::Init(const InitOptions *options) {
231 1.1 mrg DCHECK_NE(tid(), kInvalidTid);
232 1.1 mrg next_stack_top_ = next_stack_bottom_ = 0;
233 1.1 mrg atomic_store(&stack_switching_, false, memory_order_release);
234 1.1 mrg CHECK_EQ(this->stack_size(), 0U);
235 1.1 mrg SetThreadStackAndTls(options);
236 1.1 mrg if (stack_top_ != stack_bottom_) {
237 1.1 mrg CHECK_GT(this->stack_size(), 0U);
238 1.1 mrg CHECK(AddrIsInMem(stack_bottom_));
239 1.1 mrg CHECK(AddrIsInMem(stack_top_ - 1));
240 1.1 mrg }
241 1.1 mrg ClearShadowForThreadStackAndTLS();
242 1.1 mrg fake_stack_ = nullptr;
243 1.1 mrg if (__asan_option_detect_stack_use_after_return &&
244 1.1 mrg tid() == GetCurrentTidOrInvalid()) {
245 1.1 mrg // AsyncSignalSafeLazyInitFakeStack makes use of threadlocals and must be
246 1.1 mrg // called from the context of the thread it is initializing, not its parent.
247 1.1 mrg // Most platforms call AsanThread::Init on the newly-spawned thread, but
248 1.1 mrg // Fuchsia calls this function from the parent thread. To support that
249 1.1 mrg // approach, we avoid calling AsyncSignalSafeLazyInitFakeStack here; it will
250 1.1 mrg // be called by the new thread when it first attempts to access the fake
251 1.1 mrg // stack.
252 1.1 mrg AsyncSignalSafeLazyInitFakeStack();
253 1.1 mrg }
254 1.1 mrg int local = 0;
255 1.1 mrg VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
256 1.1 mrg (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
257 1.1 mrg (void *)&local);
258 1.1 mrg }
259 1.1 mrg
260 1.1 mrg // Fuchsia doesn't use ThreadStart.
261 1.1 mrg // asan_fuchsia.c definies CreateMainThread and SetThreadStackAndTls.
262 1.1 mrg #if !SANITIZER_FUCHSIA
263 1.1 mrg
264 1.1 mrg thread_return_t AsanThread::ThreadStart(tid_t os_id) {
265 1.1 mrg Init();
266 1.1 mrg asanThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular, nullptr);
267 1.1 mrg
268 1.1 mrg if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
269 1.1 mrg
270 1.1 mrg if (!start_routine_) {
271 1.1 mrg // start_routine_ == 0 if we're on the main thread or on one of the
272 1.1 mrg // OS X libdispatch worker threads. But nobody is supposed to call
273 1.1 mrg // ThreadStart() for the worker threads.
274 1.1 mrg CHECK_EQ(tid(), 0);
275 1.1 mrg return 0;
276 1.1 mrg }
277 1.1 mrg
278 1.1 mrg thread_return_t res = start_routine_(arg_);
279 1.1 mrg
280 1.1 mrg // On POSIX systems we defer this to the TSD destructor. LSan will consider
281 1.1 mrg // the thread's memory as non-live from the moment we call Destroy(), even
282 1.1 mrg // though that memory might contain pointers to heap objects which will be
283 1.1 mrg // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
284 1.1 mrg // the TSD destructors have run might cause false positives in LSan.
285 1.1 mrg if (!SANITIZER_POSIX)
286 1.1 mrg this->Destroy();
287 1.1 mrg
288 1.1 mrg return res;
289 1.1 mrg }
290 1.1 mrg
291 1.1 mrg AsanThread *CreateMainThread() {
292 1.1 mrg AsanThread *main_thread = AsanThread::Create(
293 1.1 mrg /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid,
294 1.1 mrg /* stack */ nullptr, /* detached */ true);
295 1.1 mrg SetCurrentThread(main_thread);
296 1.1 mrg main_thread->ThreadStart(internal_getpid());
297 1.1 mrg return main_thread;
298 1.1 mrg }
299 1.1 mrg
300 1.1 mrg // This implementation doesn't use the argument, which is just passed down
301 1.1 mrg // from the caller of Init (which see, above). It's only there to support
302 1.1 mrg // OS-specific implementations that need more information passed through.
303 1.1 mrg void AsanThread::SetThreadStackAndTls(const InitOptions *options) {
304 1.1 mrg DCHECK_EQ(options, nullptr);
305 1.1 mrg uptr tls_size = 0;
306 1.1 mrg uptr stack_size = 0;
307 1.1 mrg GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
308 1.1 mrg &tls_begin_, &tls_size);
309 1.1 mrg stack_top_ = RoundDownTo(stack_bottom_ + stack_size, SHADOW_GRANULARITY);
310 1.1 mrg tls_end_ = tls_begin_ + tls_size;
311 1.1 mrg dtls_ = DTLS_Get();
312 1.1 mrg
313 1.1 mrg if (stack_top_ != stack_bottom_) {
314 1.1 mrg int local;
315 1.1 mrg CHECK(AddrIsInStack((uptr)&local));
316 1.1 mrg }
317 1.1 mrg }
318 1.1 mrg
319 1.1 mrg #endif // !SANITIZER_FUCHSIA
320 1.1 mrg
321 1.1 mrg void AsanThread::ClearShadowForThreadStackAndTLS() {
322 1.1 mrg if (stack_top_ != stack_bottom_)
323 1.1 mrg PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
324 1.1 mrg if (tls_begin_ != tls_end_) {
325 1.1 mrg uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY);
326 1.1 mrg uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY);
327 1.1 mrg FastPoisonShadowPartialRightRedzone(tls_begin_aligned,
328 1.1 mrg tls_end_ - tls_begin_aligned,
329 1.1 mrg tls_end_aligned - tls_end_, 0);
330 1.1 mrg }
331 1.1 mrg }
332 1.1 mrg
333 1.1 mrg bool AsanThread::GetStackFrameAccessByAddr(uptr addr,
334 1.1 mrg StackFrameAccess *access) {
335 1.1 mrg if (stack_top_ == stack_bottom_)
336 1.1 mrg return false;
337 1.1 mrg
338 1.1 mrg uptr bottom = 0;
339 1.1 mrg if (AddrIsInStack(addr)) {
340 1.1 mrg bottom = stack_bottom();
341 1.1 mrg } else if (FakeStack *fake_stack = get_fake_stack()) {
342 1.1 mrg bottom = fake_stack->AddrIsInFakeStack(addr);
343 1.1 mrg CHECK(bottom);
344 1.1 mrg access->offset = addr - bottom;
345 1.1 mrg access->frame_pc = ((uptr*)bottom)[2];
346 1.1 mrg access->frame_descr = (const char *)((uptr*)bottom)[1];
347 1.1 mrg return true;
348 1.1 mrg }
349 1.1 mrg uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
350 1.1 mrg uptr mem_ptr = RoundDownTo(aligned_addr, SHADOW_GRANULARITY);
351 1.1 mrg u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
352 1.1 mrg u8 *shadow_bottom = (u8*)MemToShadow(bottom);
353 1.1 mrg
354 1.1 mrg while (shadow_ptr >= shadow_bottom &&
355 1.1 mrg *shadow_ptr != kAsanStackLeftRedzoneMagic) {
356 1.1 mrg shadow_ptr--;
357 1.1 mrg mem_ptr -= SHADOW_GRANULARITY;
358 1.1 mrg }
359 1.1 mrg
360 1.1 mrg while (shadow_ptr >= shadow_bottom &&
361 1.1 mrg *shadow_ptr == kAsanStackLeftRedzoneMagic) {
362 1.1 mrg shadow_ptr--;
363 1.1 mrg mem_ptr -= SHADOW_GRANULARITY;
364 1.1 mrg }
365 1.1 mrg
366 1.1 mrg if (shadow_ptr < shadow_bottom) {
367 1.1 mrg return false;
368 1.1 mrg }
369 1.1 mrg
370 1.1 mrg uptr* ptr = (uptr*)(mem_ptr + SHADOW_GRANULARITY);
371 1.1 mrg CHECK(ptr[0] == kCurrentStackFrameMagic);
372 1.1 mrg access->offset = addr - (uptr)ptr;
373 1.1 mrg access->frame_pc = ptr[2];
374 1.1 mrg access->frame_descr = (const char*)ptr[1];
375 1.1 mrg return true;
376 1.1 mrg }
377 1.1 mrg
378 1.1 mrg uptr AsanThread::GetStackVariableShadowStart(uptr addr) {
379 1.1 mrg uptr bottom = 0;
380 1.1 mrg if (AddrIsInStack(addr)) {
381 1.1 mrg bottom = stack_bottom();
382 1.1 mrg } else if (FakeStack *fake_stack = get_fake_stack()) {
383 1.1 mrg bottom = fake_stack->AddrIsInFakeStack(addr);
384 1.1 mrg if (bottom == 0) {
385 1.1 mrg return 0;
386 1.1 mrg }
387 1.1 mrg } else {
388 1.1 mrg return 0;
389 1.1 mrg }
390 1.1 mrg
391 1.1 mrg uptr aligned_addr = RoundDownTo(addr, SANITIZER_WORDSIZE / 8); // align addr.
392 1.1 mrg u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
393 1.1 mrg u8 *shadow_bottom = (u8*)MemToShadow(bottom);
394 1.1 mrg
395 1.1 mrg while (shadow_ptr >= shadow_bottom &&
396 1.1 mrg (*shadow_ptr != kAsanStackLeftRedzoneMagic &&
397 1.1 mrg *shadow_ptr != kAsanStackMidRedzoneMagic &&
398 1.1 mrg *shadow_ptr != kAsanStackRightRedzoneMagic))
399 1.1 mrg shadow_ptr--;
400 1.1 mrg
401 1.1 mrg return (uptr)shadow_ptr + 1;
402 1.1 mrg }
403 1.1 mrg
404 1.1 mrg bool AsanThread::AddrIsInStack(uptr addr) {
405 1.1 mrg const auto bounds = GetStackBounds();
406 1.1 mrg return addr >= bounds.bottom && addr < bounds.top;
407 1.1 mrg }
408 1.1 mrg
409 1.1 mrg static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
410 1.1 mrg void *addr) {
411 1.1 mrg AsanThreadContext *tctx = static_cast<AsanThreadContext *>(tctx_base);
412 1.1 mrg AsanThread *t = tctx->thread;
413 1.1 mrg if (!t)
414 1.1 mrg return false;
415 1.1 mrg if (t->AddrIsInStack((uptr)addr))
416 1.1 mrg return true;
417 1.1 mrg FakeStack *fake_stack = t->get_fake_stack();
418 1.1 mrg if (!fake_stack)
419 1.1 mrg return false;
420 1.1 mrg return fake_stack->AddrIsInFakeStack((uptr)addr);
421 1.1 mrg }
422 1.1 mrg
423 1.1 mrg AsanThread *GetCurrentThread() {
424 1.1 mrg AsanThreadContext *context =
425 1.1 mrg reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
426 1.1 mrg if (!context) {
427 1.1 mrg if (SANITIZER_ANDROID) {
428 1.1 mrg // On Android, libc constructor is called _after_ asan_init, and cleans up
429 1.1 mrg // TSD. Try to figure out if this is still the main thread by the stack
430 1.1 mrg // address. We are not entirely sure that we have correct main thread
431 1.1 mrg // limits, so only do this magic on Android, and only if the found thread
432 1.1 mrg // is the main thread.
433 1.1 mrg AsanThreadContext *tctx = GetThreadContextByTidLocked(kMainTid);
434 1.1 mrg if (tctx && ThreadStackContainsAddress(tctx, &context)) {
435 1.1 mrg SetCurrentThread(tctx->thread);
436 1.1 mrg return tctx->thread;
437 1.1 mrg }
438 1.1 mrg }
439 1.1 mrg return nullptr;
440 1.1 mrg }
441 1.1 mrg return context->thread;
442 1.1 mrg }
443 1.1 mrg
444 1.1 mrg void SetCurrentThread(AsanThread *t) {
445 1.1 mrg CHECK(t->context());
446 1.1 mrg VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(),
447 1.1 mrg (void *)GetThreadSelf());
448 1.1 mrg // Make sure we do not reset the current AsanThread.
449 1.1 mrg CHECK_EQ(0, AsanTSDGet());
450 1.1 mrg AsanTSDSet(t->context());
451 1.1 mrg CHECK_EQ(t->context(), AsanTSDGet());
452 1.1 mrg }
453 1.1 mrg
454 1.1 mrg u32 GetCurrentTidOrInvalid() {
455 1.1 mrg AsanThread *t = GetCurrentThread();
456 1.1 mrg return t ? t->tid() : kInvalidTid;
457 1.1 mrg }
458 1.1 mrg
459 1.1 mrg AsanThread *FindThreadByStackAddress(uptr addr) {
460 1.1 mrg asanThreadRegistry().CheckLocked();
461 1.1 mrg AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
462 1.1 mrg asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
463 1.1 mrg (void *)addr));
464 1.1 mrg return tctx ? tctx->thread : nullptr;
465 1.1 mrg }
466 1.1 mrg
467 1.1 mrg void EnsureMainThreadIDIsCorrect() {
468 1.1 mrg AsanThreadContext *context =
469 1.1 mrg reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
470 1.1 mrg if (context && (context->tid == kMainTid))
471 1.1 mrg context->os_id = GetTid();
472 1.1 mrg }
473 1.1 mrg
474 1.1 mrg __asan::AsanThread *GetAsanThreadByOsIDLocked(tid_t os_id) {
475 1.1 mrg __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
476 1.1 mrg __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
477 1.1 mrg if (!context) return nullptr;
478 1.1 mrg return context->thread;
479 1.1 mrg }
480 1.1 mrg } // namespace __asan
481 1.1 mrg
482 1.1 mrg // --- Implementation of LSan-specific functions --- {{{1
483 1.1 mrg namespace __lsan {
484 1.1 mrg bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
485 1.1 mrg uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
486 1.1 mrg uptr *cache_end, DTLS **dtls) {
487 1.1 mrg __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
488 1.1 mrg if (!t) return false;
489 1.1 mrg *stack_begin = t->stack_bottom();
490 1.1 mrg *stack_end = t->stack_top();
491 1.1 mrg *tls_begin = t->tls_begin();
492 1.1 mrg *tls_end = t->tls_end();
493 1.1 mrg // ASan doesn't keep allocator caches in TLS, so these are unused.
494 1.1 mrg *cache_begin = 0;
495 1.1 mrg *cache_end = 0;
496 1.1 mrg *dtls = t->dtls();
497 1.1 mrg return true;
498 1.1 mrg }
499 1.1 mrg
500 1.1 mrg void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {}
501 1.1 mrg
502 1.1 mrg void ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback,
503 1.1 mrg void *arg) {
504 1.1 mrg __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
505 1.1 mrg if (!t)
506 1.1 mrg return;
507 1.1 mrg __asan::FakeStack *fake_stack = t->get_fake_stack();
508 1.1 mrg if (!fake_stack)
509 1.1 mrg return;
510 1.1 mrg fake_stack->ForEachFakeFrame(callback, arg);
511 1.1 mrg }
512 1.1 mrg
513 1.1 mrg void LockThreadRegistry() {
514 1.1 mrg __asan::asanThreadRegistry().Lock();
515 1.1 mrg }
516 1.1 mrg
517 1.1 mrg void UnlockThreadRegistry() {
518 1.1 mrg __asan::asanThreadRegistry().Unlock();
519 1.1 mrg }
520 1.1 mrg
521 1.1 mrg ThreadRegistry *GetThreadRegistryLocked() {
522 1.1 mrg __asan::asanThreadRegistry().CheckLocked();
523 1.1 mrg return &__asan::asanThreadRegistry();
524 1.1 mrg }
525 1.1 mrg
526 1.1 mrg void EnsureMainThreadIDIsCorrect() {
527 1.1 mrg __asan::EnsureMainThreadIDIsCorrect();
528 1.1 mrg }
529 1.1 mrg } // namespace __lsan
530 1.1 mrg
531 1.1 mrg // ---------------------- Interface ---------------- {{{1
532 1.1 mrg using namespace __asan;
533 1.1 mrg
534 1.1 mrg extern "C" {
535 1.1 mrg SANITIZER_INTERFACE_ATTRIBUTE
536 1.1 mrg void __sanitizer_start_switch_fiber(void **fakestacksave, const void *bottom,
537 1.1 mrg uptr size) {
538 1.1 mrg AsanThread *t = GetCurrentThread();
539 1.1 mrg if (!t) {
540 1.1 mrg VReport(1, "__asan_start_switch_fiber called from unknown thread\n");
541 1.1 mrg return;
542 1.1 mrg }
543 1.1 mrg t->StartSwitchFiber((FakeStack**)fakestacksave, (uptr)bottom, size);
544 1.1 mrg }
545 1.1 mrg
546 1.1 mrg SANITIZER_INTERFACE_ATTRIBUTE
547 1.1 mrg void __sanitizer_finish_switch_fiber(void* fakestack,
548 1.1 mrg const void **bottom_old,
549 1.1 mrg uptr *size_old) {
550 1.1 mrg AsanThread *t = GetCurrentThread();
551 1.1 mrg if (!t) {
552 1.1 mrg VReport(1, "__asan_finish_switch_fiber called from unknown thread\n");
553 1.1 mrg return;
554 1.1 mrg }
555 1.1 mrg t->FinishSwitchFiber((FakeStack*)fakestack,
556 1.1 mrg (uptr*)bottom_old,
557 1.1 mrg (uptr*)size_old);
558 1.1 mrg }
559 1.1 mrg }
560