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