1 //===-- tsan_rtl.cpp ------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 //
11 // Main file (entry points) for the TSan run-time.
12 //===----------------------------------------------------------------------===//
13
14 #include "tsan_rtl.h"
15
16 #include "sanitizer_common/sanitizer_atomic.h"
17 #include "sanitizer_common/sanitizer_common.h"
18 #include "sanitizer_common/sanitizer_file.h"
19 #include "sanitizer_common/sanitizer_libc.h"
20 #include "sanitizer_common/sanitizer_placement_new.h"
21 #include "sanitizer_common/sanitizer_stackdepot.h"
22 #include "sanitizer_common/sanitizer_symbolizer.h"
23 #include "tsan_defs.h"
24 #include "tsan_interface.h"
25 #include "tsan_mman.h"
26 #include "tsan_platform.h"
27 #include "tsan_suppressions.h"
28 #include "tsan_symbolize.h"
29 #include "ubsan/ubsan_init.h"
30
31 volatile int __tsan_resumed = 0;
32
__tsan_resume()33 extern "C" void __tsan_resume() {
34 __tsan_resumed = 1;
35 }
36
37 SANITIZER_WEAK_DEFAULT_IMPL
__tsan_test_only_on_fork()38 void __tsan_test_only_on_fork() {}
39
40 namespace __tsan {
41
42 #if !SANITIZER_GO
43 void (*on_initialize)(void);
44 int (*on_finalize)(int);
45 #endif
46
47 #if !SANITIZER_GO && !SANITIZER_APPLE
48 __attribute__((tls_model("initial-exec")))
49 THREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(
50 SANITIZER_CACHE_LINE_SIZE);
51 #endif
52 static char ctx_placeholder[sizeof(Context)] ALIGNED(SANITIZER_CACHE_LINE_SIZE);
53 Context *ctx;
54
55 // Can be overriden by a front-end.
56 #ifdef TSAN_EXTERNAL_HOOKS
57 bool OnFinalize(bool failed);
58 void OnInitialize();
59 #else
60 #include <dlfcn.h>
61 SANITIZER_WEAK_CXX_DEFAULT_IMPL
OnFinalize(bool failed)62 bool OnFinalize(bool failed) {
63 #if !SANITIZER_GO
64 if (on_finalize)
65 return on_finalize(failed);
66 #endif
67 return failed;
68 }
69 SANITIZER_WEAK_CXX_DEFAULT_IMPL
OnInitialize()70 void OnInitialize() {
71 #if !SANITIZER_GO
72 if (on_initialize)
73 on_initialize();
74 #endif
75 }
76 #endif
77
CreateThreadContext(Tid tid)78 static ThreadContextBase *CreateThreadContext(Tid tid) {
79 // Map thread trace when context is created.
80 char name[50];
81 internal_snprintf(name, sizeof(name), "trace %u", tid);
82 MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event), name);
83 const uptr hdr = GetThreadTraceHeader(tid);
84 internal_snprintf(name, sizeof(name), "trace header %u", tid);
85 MapThreadTrace(hdr, sizeof(Trace), name);
86 new((void*)hdr) Trace();
87 // We are going to use only a small part of the trace with the default
88 // value of history_size. However, the constructor writes to the whole trace.
89 // Release the unused part.
90 uptr hdr_end = hdr + sizeof(Trace);
91 hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts());
92 hdr_end = RoundUp(hdr_end, GetPageSizeCached());
93 if (hdr_end < hdr + sizeof(Trace)) {
94 ReleaseMemoryPagesToOS(hdr_end, hdr + sizeof(Trace));
95 uptr unused = hdr + sizeof(Trace) - hdr_end;
96 if (hdr_end != (uptr)MmapFixedNoAccess(hdr_end, unused)) {
97 Report("ThreadSanitizer: failed to mprotect [0x%zx-0x%zx) \n", hdr_end,
98 unused);
99 CHECK("unable to mprotect" && 0);
100 }
101 }
102 return New<ThreadContext>(tid);
103 }
104
105 #if !SANITIZER_GO
106 static const u32 kThreadQuarantineSize = 16;
107 #else
108 static const u32 kThreadQuarantineSize = 64;
109 #endif
110
Context()111 Context::Context()
112 : initialized(),
113 report_mtx(MutexTypeReport),
114 nreported(),
115 thread_registry(CreateThreadContext, kMaxTid, kThreadQuarantineSize,
116 kMaxTidReuse),
117 racy_mtx(MutexTypeRacy),
118 racy_stacks(),
119 racy_addresses(),
120 fired_suppressions_mtx(MutexTypeFired),
121 clock_alloc(LINKER_INITIALIZED, "clock allocator") {
122 fired_suppressions.reserve(8);
123 }
124
125 // The objects are allocated in TLS, so one may rely on zero-initialization.
ThreadState(Context * ctx,Tid tid,int unique_id,u64 epoch,unsigned reuse_count,uptr stk_addr,uptr stk_size,uptr tls_addr,uptr tls_size)126 ThreadState::ThreadState(Context *ctx, Tid tid, int unique_id, u64 epoch,
127 unsigned reuse_count, uptr stk_addr, uptr stk_size,
128 uptr tls_addr, uptr tls_size)
129 : fast_state(tid, epoch)
130 // Do not touch these, rely on zero initialization,
131 // they may be accessed before the ctor.
132 // , ignore_reads_and_writes()
133 // , ignore_interceptors()
134 ,
135 clock(tid, reuse_count)
136 #if !SANITIZER_GO
137 ,
138 jmp_bufs()
139 #endif
140 ,
141 tid(tid),
142 unique_id(unique_id),
143 stk_addr(stk_addr),
144 stk_size(stk_size),
145 tls_addr(tls_addr),
146 tls_size(tls_size)
147 #if !SANITIZER_GO
148 ,
149 last_sleep_clock(tid)
150 #endif
151 {
152 CHECK_EQ(reinterpret_cast<uptr>(this) % SANITIZER_CACHE_LINE_SIZE, 0);
153 #if !SANITIZER_GO
154 // C/C++ uses fixed size shadow stack.
155 const int kInitStackSize = kShadowStackSize;
156 shadow_stack = static_cast<uptr *>(
157 MmapNoReserveOrDie(kInitStackSize * sizeof(uptr), "shadow stack"));
158 SetShadowRegionHugePageMode(reinterpret_cast<uptr>(shadow_stack),
159 kInitStackSize * sizeof(uptr));
160 #else
161 // Go uses malloc-allocated shadow stack with dynamic size.
162 const int kInitStackSize = 8;
163 shadow_stack = static_cast<uptr *>(Alloc(kInitStackSize * sizeof(uptr)));
164 #endif
165 shadow_stack_pos = shadow_stack;
166 shadow_stack_end = shadow_stack + kInitStackSize;
167 }
168
169 #if !SANITIZER_GO
MemoryProfiler(u64 uptime)170 void MemoryProfiler(u64 uptime) {
171 if (ctx->memprof_fd == kInvalidFd)
172 return;
173 InternalMmapVector<char> buf(4096);
174 WriteMemoryProfile(buf.data(), buf.size(), uptime);
175 WriteToFile(ctx->memprof_fd, buf.data(), internal_strlen(buf.data()));
176 }
177
InitializeMemoryProfiler()178 void InitializeMemoryProfiler() {
179 ctx->memprof_fd = kInvalidFd;
180 const char *fname = flags()->profile_memory;
181 if (!fname || !fname[0])
182 return;
183 if (internal_strcmp(fname, "stdout") == 0) {
184 ctx->memprof_fd = 1;
185 } else if (internal_strcmp(fname, "stderr") == 0) {
186 ctx->memprof_fd = 2;
187 } else {
188 InternalScopedString filename;
189 filename.append("%s.%d", fname, (int)internal_getpid());
190 ctx->memprof_fd = OpenFile(filename.data(), WrOnly);
191 if (ctx->memprof_fd == kInvalidFd) {
192 Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
193 filename.data());
194 return;
195 }
196 }
197 MemoryProfiler(0);
198 MaybeSpawnBackgroundThread();
199 }
200
BackgroundThread(void * arg)201 static void *BackgroundThread(void *arg) {
202 // This is a non-initialized non-user thread, nothing to see here.
203 // We don't use ScopedIgnoreInterceptors, because we want ignores to be
204 // enabled even when the thread function exits (e.g. during pthread thread
205 // shutdown code).
206 cur_thread_init()->ignore_interceptors++;
207 const u64 kMs2Ns = 1000 * 1000;
208 const u64 start = NanoTime();
209
210 u64 last_flush = NanoTime();
211 uptr last_rss = 0;
212 for (int i = 0;
213 atomic_load(&ctx->stop_background_thread, memory_order_relaxed) == 0;
214 i++) {
215 SleepForMillis(100);
216 u64 now = NanoTime();
217
218 // Flush memory if requested.
219 if (flags()->flush_memory_ms > 0) {
220 if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
221 VPrintf(1, "ThreadSanitizer: periodic memory flush\n");
222 FlushShadowMemory();
223 last_flush = NanoTime();
224 }
225 }
226 if (flags()->memory_limit_mb > 0) {
227 uptr rss = GetRSS();
228 uptr limit = uptr(flags()->memory_limit_mb) << 20;
229 VPrintf(1, "ThreadSanitizer: memory flush check"
230 " RSS=%llu LAST=%llu LIMIT=%llu\n",
231 (u64)rss >> 20, (u64)last_rss >> 20, (u64)limit >> 20);
232 if (2 * rss > limit + last_rss) {
233 VPrintf(1, "ThreadSanitizer: flushing memory due to RSS\n");
234 FlushShadowMemory();
235 rss = GetRSS();
236 VPrintf(1, "ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
237 }
238 last_rss = rss;
239 }
240
241 MemoryProfiler(now - start);
242
243 // Flush symbolizer cache if requested.
244 if (flags()->flush_symbolizer_ms > 0) {
245 u64 last = atomic_load(&ctx->last_symbolize_time_ns,
246 memory_order_relaxed);
247 if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) {
248 Lock l(&ctx->report_mtx);
249 ScopedErrorReportLock l2;
250 SymbolizeFlush();
251 atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed);
252 }
253 }
254 }
255 return nullptr;
256 }
257
StartBackgroundThread()258 static void StartBackgroundThread() {
259 ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
260 }
261
262 #ifndef __mips__
StopBackgroundThread()263 static void StopBackgroundThread() {
264 atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
265 internal_join_thread(ctx->background_thread);
266 ctx->background_thread = 0;
267 }
268 #endif
269 #endif
270
DontNeedShadowFor(uptr addr,uptr size)271 void DontNeedShadowFor(uptr addr, uptr size) {
272 ReleaseMemoryPagesToOS(reinterpret_cast<uptr>(MemToShadow(addr)),
273 reinterpret_cast<uptr>(MemToShadow(addr + size)));
274 }
275
276 #if !SANITIZER_GO
277 // We call UnmapShadow before the actual munmap, at that point we don't yet
278 // know if the provided address/size are sane. We can't call UnmapShadow
279 // after the actual munmap becuase at that point the memory range can
280 // already be reused for something else, so we can't rely on the munmap
281 // return value to understand is the values are sane.
282 // While calling munmap with insane values (non-canonical address, negative
283 // size, etc) is an error, the kernel won't crash. We must also try to not
284 // crash as the failure mode is very confusing (paging fault inside of the
285 // runtime on some derived shadow address).
IsValidMmapRange(uptr addr,uptr size)286 static bool IsValidMmapRange(uptr addr, uptr size) {
287 if (size == 0)
288 return true;
289 if (static_cast<sptr>(size) < 0)
290 return false;
291 if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
292 return false;
293 // Check that if the start of the region belongs to one of app ranges,
294 // end of the region belongs to the same region.
295 const uptr ranges[][2] = {
296 {LoAppMemBeg(), LoAppMemEnd()},
297 {MidAppMemBeg(), MidAppMemEnd()},
298 {HiAppMemBeg(), HiAppMemEnd()},
299 };
300 for (auto range : ranges) {
301 if (addr >= range[0] && addr < range[1])
302 return addr + size <= range[1];
303 }
304 return false;
305 }
306
UnmapShadow(ThreadState * thr,uptr addr,uptr size)307 void UnmapShadow(ThreadState *thr, uptr addr, uptr size) {
308 if (size == 0 || !IsValidMmapRange(addr, size))
309 return;
310 DontNeedShadowFor(addr, size);
311 ScopedGlobalProcessor sgp;
312 ctx->metamap.ResetRange(thr->proc(), addr, size);
313 }
314 #endif
315
MapShadow(uptr addr,uptr size)316 void MapShadow(uptr addr, uptr size) {
317 // Global data is not 64K aligned, but there are no adjacent mappings,
318 // so we can get away with unaligned mapping.
319 // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
320 const uptr kPageSize = GetPageSizeCached();
321 uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize);
322 uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize);
323 if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin,
324 "shadow"))
325 Die();
326
327 // Meta shadow is 2:1, so tread carefully.
328 static bool data_mapped = false;
329 static uptr mapped_meta_end = 0;
330 uptr meta_begin = (uptr)MemToMeta(addr);
331 uptr meta_end = (uptr)MemToMeta(addr + size);
332 meta_begin = RoundDownTo(meta_begin, 64 << 10);
333 meta_end = RoundUpTo(meta_end, 64 << 10);
334 if (!data_mapped) {
335 // First call maps data+bss.
336 data_mapped = true;
337 if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin,
338 "meta shadow"))
339 Die();
340 } else {
341 // Mapping continuous heap.
342 // Windows wants 64K alignment.
343 meta_begin = RoundDownTo(meta_begin, 64 << 10);
344 meta_end = RoundUpTo(meta_end, 64 << 10);
345 if (meta_end <= mapped_meta_end)
346 return;
347 if (meta_begin < mapped_meta_end)
348 meta_begin = mapped_meta_end;
349 if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin,
350 "meta shadow"))
351 Die();
352 mapped_meta_end = meta_end;
353 }
354 VPrintf(2, "mapped meta shadow for (0x%zx-0x%zx) at (0x%zx-0x%zx)\n", addr,
355 addr + size, meta_begin, meta_end);
356 }
357
MapThreadTrace(uptr addr,uptr size,const char * name)358 void MapThreadTrace(uptr addr, uptr size, const char *name) {
359 DPrintf("#0: Mapping trace at 0x%zx-0x%zx(0x%zx)\n", addr, addr + size, size);
360 CHECK_GE(addr, TraceMemBeg());
361 CHECK_LE(addr + size, TraceMemEnd());
362 CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment
363 if (!MmapFixedSuperNoReserve(addr, size, name)) {
364 Printf("FATAL: ThreadSanitizer can not mmap thread trace (0x%zx/0x%zx)\n",
365 addr, size);
366 Die();
367 }
368 }
369
370 #if !SANITIZER_GO
OnStackUnwind(const SignalContext & sig,const void *,BufferedStackTrace * stack)371 static void OnStackUnwind(const SignalContext &sig, const void *,
372 BufferedStackTrace *stack) {
373 stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
374 common_flags()->fast_unwind_on_fatal);
375 }
376
TsanOnDeadlySignal(int signo,void * siginfo,void * context)377 static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) {
378 HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr);
379 }
380 #endif
381
CheckUnwind()382 void CheckUnwind() {
383 // There is high probability that interceptors will check-fail as well,
384 // on the other hand there is no sense in processing interceptors
385 // since we are going to die soon.
386 ScopedIgnoreInterceptors ignore;
387 #if !SANITIZER_GO
388 cur_thread()->ignore_sync++;
389 cur_thread()->ignore_reads_and_writes++;
390 #endif
391 PrintCurrentStackSlow(StackTrace::GetCurrentPc());
392 }
393
394 bool is_initialized;
395
Initialize(ThreadState * thr)396 void Initialize(ThreadState *thr) {
397 // Thread safe because done before all threads exist.
398 if (is_initialized)
399 return;
400 is_initialized = true;
401 // We are not ready to handle interceptors yet.
402 ScopedIgnoreInterceptors ignore;
403 SanitizerToolName = "ThreadSanitizer";
404 // Install tool-specific callbacks in sanitizer_common.
405 SetCheckUnwindCallback(CheckUnwind);
406
407 ctx = new(ctx_placeholder) Context;
408 const char *env_name = SANITIZER_GO ? "GORACE" : "TSAN_OPTIONS";
409 const char *options = GetEnv(env_name);
410 CacheBinaryName();
411 CheckASLR();
412 InitializeFlags(&ctx->flags, options, env_name);
413 AvoidCVE_2016_2143();
414 __sanitizer::InitializePlatformEarly();
415 __tsan::InitializePlatformEarly();
416
417 #if !SANITIZER_GO
418 // Re-exec ourselves if we need to set additional env or command line args.
419 MaybeReexec();
420
421 InitializeAllocator();
422 ReplaceSystemMalloc();
423 #endif
424 if (common_flags()->detect_deadlocks)
425 ctx->dd = DDetector::Create(flags());
426 Processor *proc = ProcCreate();
427 ProcWire(proc, thr);
428 InitializeInterceptors();
429 InitializePlatform();
430 InitializeDynamicAnnotations();
431 #if !SANITIZER_GO
432 InitializeShadowMemory();
433 InitializeAllocatorLate();
434 InstallDeadlySignalHandlers(TsanOnDeadlySignal);
435 #endif
436 // Setup correct file descriptor for error reports.
437 __sanitizer_set_report_path(common_flags()->log_path);
438 InitializeSuppressions();
439 #if !SANITIZER_GO
440 InitializeLibIgnore();
441 Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
442 #endif
443
444 VPrintf(1, "***** Running under ThreadSanitizer v2 (pid %d) *****\n",
445 (int)internal_getpid());
446
447 // Initialize thread 0.
448 Tid tid = ThreadCreate(thr, 0, 0, true);
449 CHECK_EQ(tid, kMainTid);
450 ThreadStart(thr, tid, GetTid(), ThreadType::Regular);
451 #if TSAN_CONTAINS_UBSAN
452 __ubsan::InitAsPlugin();
453 #endif
454 ctx->initialized = true;
455
456 #if !SANITIZER_GO
457 Symbolizer::LateInitialize();
458 InitializeMemoryProfiler();
459 #endif
460
461 if (flags()->stop_on_start) {
462 Printf("ThreadSanitizer is suspended at startup (pid %d)."
463 " Call __tsan_resume().\n",
464 (int)internal_getpid());
465 while (__tsan_resumed == 0) {}
466 }
467
468 OnInitialize();
469 }
470
MaybeSpawnBackgroundThread()471 void MaybeSpawnBackgroundThread() {
472 // On MIPS, TSan initialization is run before
473 // __pthread_initialize_minimal_internal() is finished, so we can not spawn
474 // new threads.
475 #if !SANITIZER_GO && !defined(__mips__)
476 static atomic_uint32_t bg_thread = {};
477 if (atomic_load(&bg_thread, memory_order_relaxed) == 0 &&
478 atomic_exchange(&bg_thread, 1, memory_order_relaxed) == 0) {
479 StartBackgroundThread();
480 SetSandboxingCallback(StopBackgroundThread);
481 }
482 #endif
483 }
484
485
Finalize(ThreadState * thr)486 int Finalize(ThreadState *thr) {
487 bool failed = false;
488
489 if (common_flags()->print_module_map == 1)
490 DumpProcessMap();
491
492 if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
493 SleepForMillis(flags()->atexit_sleep_ms);
494
495 // Wait for pending reports.
496 ctx->report_mtx.Lock();
497 { ScopedErrorReportLock l; }
498 ctx->report_mtx.Unlock();
499
500 #if !SANITIZER_GO
501 if (Verbosity()) AllocatorPrintStats();
502 #endif
503
504 ThreadFinalize(thr);
505
506 if (ctx->nreported) {
507 failed = true;
508 #if !SANITIZER_GO
509 Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
510 #else
511 Printf("Found %d data race(s)\n", ctx->nreported);
512 #endif
513 }
514
515 if (common_flags()->print_suppressions)
516 PrintMatchedSuppressions();
517
518 failed = OnFinalize(failed);
519
520 return failed ? common_flags()->exitcode : 0;
521 }
522
523 #if !SANITIZER_GO
ForkBefore(ThreadState * thr,uptr pc)524 void ForkBefore(ThreadState *thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
525 ctx->thread_registry.Lock();
526 ctx->report_mtx.Lock();
527 ScopedErrorReportLock::Lock();
528 AllocatorLock();
529 // Suppress all reports in the pthread_atfork callbacks.
530 // Reports will deadlock on the report_mtx.
531 // We could ignore sync operations as well,
532 // but so far it's unclear if it will do more good or harm.
533 // Unnecessarily ignoring things can lead to false positives later.
534 thr->suppress_reports++;
535 // On OS X, REAL(fork) can call intercepted functions (OSSpinLockLock), and
536 // we'll assert in CheckNoLocks() unless we ignore interceptors.
537 // On OS X libSystem_atfork_prepare/parent/child callbacks are called
538 // after/before our callbacks and they call free.
539 thr->ignore_interceptors++;
540 // Disables memory write in OnUserAlloc/Free.
541 thr->ignore_reads_and_writes++;
542
543 __tsan_test_only_on_fork();
544 }
545
ForkParentAfter(ThreadState * thr,uptr pc)546 void ForkParentAfter(ThreadState *thr,
547 uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
548 thr->suppress_reports--; // Enabled in ForkBefore.
549 thr->ignore_interceptors--;
550 thr->ignore_reads_and_writes--;
551 AllocatorUnlock();
552 ScopedErrorReportLock::Unlock();
553 ctx->report_mtx.Unlock();
554 ctx->thread_registry.Unlock();
555 }
556
ForkChildAfter(ThreadState * thr,uptr pc,bool start_thread)557 void ForkChildAfter(ThreadState *thr, uptr pc,
558 bool start_thread) SANITIZER_NO_THREAD_SAFETY_ANALYSIS {
559 thr->suppress_reports--; // Enabled in ForkBefore.
560 thr->ignore_interceptors--;
561 thr->ignore_reads_and_writes--;
562 AllocatorUnlock();
563 ScopedErrorReportLock::Unlock();
564 ctx->report_mtx.Unlock();
565 ctx->thread_registry.Unlock();
566
567 uptr nthread = 0;
568 ctx->thread_registry.GetNumberOfThreads(0, 0, &nthread /* alive threads */);
569 VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
570 " parent had %d threads\n", (int)internal_getpid(), (int)nthread);
571 if (nthread == 1) {
572 if (start_thread)
573 StartBackgroundThread();
574 } else {
575 // We've just forked a multi-threaded process. We cannot reasonably function
576 // after that (some mutexes may be locked before fork). So just enable
577 // ignores for everything in the hope that we will exec soon.
578 ctx->after_multithreaded_fork = true;
579 thr->ignore_interceptors++;
580 ThreadIgnoreBegin(thr, pc);
581 ThreadIgnoreSyncBegin(thr, pc);
582 }
583 }
584 #endif
585
586 #if SANITIZER_GO
587 NOINLINE
GrowShadowStack(ThreadState * thr)588 void GrowShadowStack(ThreadState *thr) {
589 const int sz = thr->shadow_stack_end - thr->shadow_stack;
590 const int newsz = 2 * sz;
591 auto *newstack = (uptr *)Alloc(newsz * sizeof(uptr));
592 internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
593 Free(thr->shadow_stack);
594 thr->shadow_stack = newstack;
595 thr->shadow_stack_pos = newstack + sz;
596 thr->shadow_stack_end = newstack + newsz;
597 }
598 #endif
599
CurrentStackId(ThreadState * thr,uptr pc)600 StackID CurrentStackId(ThreadState *thr, uptr pc) {
601 if (!thr->is_inited) // May happen during bootstrap.
602 return kInvalidStackID;
603 if (pc != 0) {
604 #if !SANITIZER_GO
605 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
606 #else
607 if (thr->shadow_stack_pos == thr->shadow_stack_end)
608 GrowShadowStack(thr);
609 #endif
610 thr->shadow_stack_pos[0] = pc;
611 thr->shadow_stack_pos++;
612 }
613 StackID id = StackDepotPut(
614 StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
615 if (pc != 0)
616 thr->shadow_stack_pos--;
617 return id;
618 }
619
620 namespace v3 {
621
622 NOINLINE
TraceSwitchPart(ThreadState * thr)623 void TraceSwitchPart(ThreadState *thr) {
624 Trace *trace = &thr->tctx->trace;
625 Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos));
626 DCHECK_EQ(reinterpret_cast<uptr>(pos + 1) & TracePart::kAlignment, 0);
627 auto *part = trace->parts.Back();
628 DPrintf("TraceSwitchPart part=%p pos=%p\n", part, pos);
629 if (part) {
630 // We can get here when we still have space in the current trace part.
631 // The fast-path check in TraceAcquire has false positives in the middle of
632 // the part. Check if we are indeed at the end of the current part or not,
633 // and fill any gaps with NopEvent's.
634 Event *end = &part->events[TracePart::kSize];
635 DCHECK_GE(pos, &part->events[0]);
636 DCHECK_LE(pos, end);
637 if (pos + 1 < end) {
638 if ((reinterpret_cast<uptr>(pos) & TracePart::kAlignment) ==
639 TracePart::kAlignment)
640 *pos++ = NopEvent;
641 *pos++ = NopEvent;
642 DCHECK_LE(pos + 2, end);
643 atomic_store_relaxed(&thr->trace_pos, reinterpret_cast<uptr>(pos));
644 // Ensure we setup trace so that the next TraceAcquire
645 // won't detect trace part end.
646 Event *ev;
647 CHECK(TraceAcquire(thr, &ev));
648 return;
649 }
650 // We are indeed at the end.
651 for (; pos < end; pos++) *pos = NopEvent;
652 }
653 #if !SANITIZER_GO
654 if (ctx->after_multithreaded_fork) {
655 // We just need to survive till exec.
656 CHECK(part);
657 atomic_store_relaxed(&thr->trace_pos,
658 reinterpret_cast<uptr>(&part->events[0]));
659 return;
660 }
661 #endif
662 part = new (MmapOrDie(sizeof(TracePart), "TracePart")) TracePart();
663 part->trace = trace;
664 thr->trace_prev_pc = 0;
665 {
666 Lock lock(&trace->mtx);
667 trace->parts.PushBack(part);
668 atomic_store_relaxed(&thr->trace_pos,
669 reinterpret_cast<uptr>(&part->events[0]));
670 }
671 // Make this part self-sufficient by restoring the current stack
672 // and mutex set in the beginning of the trace.
673 TraceTime(thr);
674 for (uptr *pos = &thr->shadow_stack[0]; pos < thr->shadow_stack_pos; pos++)
675 CHECK(TryTraceFunc(thr, *pos));
676 for (uptr i = 0; i < thr->mset.Size(); i++) {
677 MutexSet::Desc d = thr->mset.Get(i);
678 TraceMutexLock(thr, d.write ? EventType::kLock : EventType::kRLock, 0,
679 d.addr, d.stack_id);
680 }
681 }
682
683 } // namespace v3
684
TraceSwitch(ThreadState * thr)685 void TraceSwitch(ThreadState *thr) {
686 #if !SANITIZER_GO
687 if (ctx->after_multithreaded_fork)
688 return;
689 #endif
690 thr->nomalloc++;
691 Trace *thr_trace = ThreadTrace(thr->tid);
692 Lock l(&thr_trace->mtx);
693 unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
694 TraceHeader *hdr = &thr_trace->headers[trace];
695 hdr->epoch0 = thr->fast_state.epoch();
696 ObtainCurrentStack(thr, 0, &hdr->stack0);
697 hdr->mset0 = thr->mset;
698 thr->nomalloc--;
699 }
700
ThreadTrace(Tid tid)701 Trace *ThreadTrace(Tid tid) { return (Trace *)GetThreadTraceHeader(tid); }
702
TraceTopPC(ThreadState * thr)703 uptr TraceTopPC(ThreadState *thr) {
704 Event *events = (Event*)GetThreadTrace(thr->tid);
705 uptr pc = events[thr->fast_state.GetTracePos()];
706 return pc;
707 }
708
TraceSize()709 uptr TraceSize() {
710 return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
711 }
712
TraceParts()713 uptr TraceParts() {
714 return TraceSize() / kTracePartSize;
715 }
716
717 #if !SANITIZER_GO
__tsan_trace_switch()718 extern "C" void __tsan_trace_switch() {
719 TraceSwitch(cur_thread());
720 }
721
__tsan_report_race()722 extern "C" void __tsan_report_race() {
723 ReportRace(cur_thread());
724 }
725 #endif
726
ThreadIgnoreBegin(ThreadState * thr,uptr pc)727 void ThreadIgnoreBegin(ThreadState *thr, uptr pc) {
728 DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
729 thr->ignore_reads_and_writes++;
730 CHECK_GT(thr->ignore_reads_and_writes, 0);
731 thr->fast_state.SetIgnoreBit();
732 #if !SANITIZER_GO
733 if (pc && !ctx->after_multithreaded_fork)
734 thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
735 #endif
736 }
737
ThreadIgnoreEnd(ThreadState * thr)738 void ThreadIgnoreEnd(ThreadState *thr) {
739 DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
740 CHECK_GT(thr->ignore_reads_and_writes, 0);
741 thr->ignore_reads_and_writes--;
742 if (thr->ignore_reads_and_writes == 0) {
743 thr->fast_state.ClearIgnoreBit();
744 #if !SANITIZER_GO
745 thr->mop_ignore_set.Reset();
746 #endif
747 }
748 }
749
750 #if !SANITIZER_GO
751 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
__tsan_testonly_shadow_stack_current_size()752 uptr __tsan_testonly_shadow_stack_current_size() {
753 ThreadState *thr = cur_thread();
754 return thr->shadow_stack_pos - thr->shadow_stack;
755 }
756 #endif
757
ThreadIgnoreSyncBegin(ThreadState * thr,uptr pc)758 void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) {
759 DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid);
760 thr->ignore_sync++;
761 CHECK_GT(thr->ignore_sync, 0);
762 #if !SANITIZER_GO
763 if (pc && !ctx->after_multithreaded_fork)
764 thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
765 #endif
766 }
767
ThreadIgnoreSyncEnd(ThreadState * thr)768 void ThreadIgnoreSyncEnd(ThreadState *thr) {
769 DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid);
770 CHECK_GT(thr->ignore_sync, 0);
771 thr->ignore_sync--;
772 #if !SANITIZER_GO
773 if (thr->ignore_sync == 0)
774 thr->sync_ignore_set.Reset();
775 #endif
776 }
777
operator ==(const MD5Hash & other) const778 bool MD5Hash::operator==(const MD5Hash &other) const {
779 return hash[0] == other.hash[0] && hash[1] == other.hash[1];
780 }
781
782 #if SANITIZER_DEBUG
build_consistency_debug()783 void build_consistency_debug() {}
784 #else
build_consistency_release()785 void build_consistency_release() {}
786 #endif
787
788 } // namespace __tsan
789
790 #if SANITIZER_CHECK_DEADLOCKS
791 namespace __sanitizer {
792 using namespace __tsan;
793 MutexMeta mutex_meta[] = {
794 {MutexInvalid, "Invalid", {}},
795 {MutexThreadRegistry, "ThreadRegistry", {}},
796 {MutexTypeTrace, "Trace", {}},
797 {MutexTypeReport,
798 "Report",
799 {MutexTypeSyncVar, MutexTypeGlobalProc, MutexTypeTrace}},
800 {MutexTypeSyncVar, "SyncVar", {MutexTypeTrace}},
801 {MutexTypeAnnotations, "Annotations", {}},
802 {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}},
803 {MutexTypeFired, "Fired", {MutexLeaf}},
804 {MutexTypeRacy, "Racy", {MutexLeaf}},
805 {MutexTypeGlobalProc, "GlobalProc", {}},
806 {MutexTypeInternalAlloc, "InternalAlloc", {MutexLeaf}},
807 {},
808 };
809
PrintMutexPC(uptr pc)810 void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); }
811 } // namespace __sanitizer
812 #endif
813