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