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 SANITIZER_WEAK_DEFAULT_IMPL 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_MAC 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 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 70 void OnInitialize() { 71 #if !SANITIZER_GO 72 if (on_initialize) 73 on_initialize(); 74 #endif 75 } 76 #endif 77 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 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. 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 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 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 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 258 static void StartBackgroundThread() { 259 ctx->background_thread = internal_start_thread(&BackgroundThread, 0); 260 } 261 262 #ifndef __mips__ 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 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). 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 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 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 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 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 377 static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) { 378 HandleDeadlySignal(siginfo, context, GetTid(), &OnStackUnwind, nullptr); 379 } 380 #endif 381 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 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 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 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 524 void ForkBefore(ThreadState *thr, uptr pc) 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 546 void ForkParentAfter(ThreadState *thr, uptr pc) NO_THREAD_SAFETY_ANALYSIS { 547 thr->suppress_reports--; // Enabled in ForkBefore. 548 thr->ignore_interceptors--; 549 thr->ignore_reads_and_writes--; 550 AllocatorUnlock(); 551 ScopedErrorReportLock::Unlock(); 552 ctx->report_mtx.Unlock(); 553 ctx->thread_registry.Unlock(); 554 } 555 556 void ForkChildAfter(ThreadState *thr, uptr pc, 557 bool start_thread) NO_THREAD_SAFETY_ANALYSIS { 558 thr->suppress_reports--; // Enabled in ForkBefore. 559 thr->ignore_interceptors--; 560 thr->ignore_reads_and_writes--; 561 AllocatorUnlock(); 562 ScopedErrorReportLock::Unlock(); 563 ctx->report_mtx.Unlock(); 564 ctx->thread_registry.Unlock(); 565 566 uptr nthread = 0; 567 ctx->thread_registry.GetNumberOfThreads(0, 0, &nthread /* alive threads */); 568 VPrintf(1, "ThreadSanitizer: forked new process with pid %d," 569 " parent had %d threads\n", (int)internal_getpid(), (int)nthread); 570 if (nthread == 1) { 571 if (start_thread) 572 StartBackgroundThread(); 573 } else { 574 // We've just forked a multi-threaded process. We cannot reasonably function 575 // after that (some mutexes may be locked before fork). So just enable 576 // ignores for everything in the hope that we will exec soon. 577 ctx->after_multithreaded_fork = true; 578 thr->ignore_interceptors++; 579 ThreadIgnoreBegin(thr, pc); 580 ThreadIgnoreSyncBegin(thr, pc); 581 } 582 } 583 #endif 584 585 #if SANITIZER_GO 586 NOINLINE 587 void GrowShadowStack(ThreadState *thr) { 588 const int sz = thr->shadow_stack_end - thr->shadow_stack; 589 const int newsz = 2 * sz; 590 auto *newstack = (uptr *)Alloc(newsz * sizeof(uptr)); 591 internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr)); 592 Free(thr->shadow_stack); 593 thr->shadow_stack = newstack; 594 thr->shadow_stack_pos = newstack + sz; 595 thr->shadow_stack_end = newstack + newsz; 596 } 597 #endif 598 599 StackID CurrentStackId(ThreadState *thr, uptr pc) { 600 if (!thr->is_inited) // May happen during bootstrap. 601 return kInvalidStackID; 602 if (pc != 0) { 603 #if !SANITIZER_GO 604 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end); 605 #else 606 if (thr->shadow_stack_pos == thr->shadow_stack_end) 607 GrowShadowStack(thr); 608 #endif 609 thr->shadow_stack_pos[0] = pc; 610 thr->shadow_stack_pos++; 611 } 612 StackID id = StackDepotPut( 613 StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack)); 614 if (pc != 0) 615 thr->shadow_stack_pos--; 616 return id; 617 } 618 619 namespace v3 { 620 621 NOINLINE 622 void TraceSwitchPart(ThreadState *thr) { 623 Trace *trace = &thr->tctx->trace; 624 Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos)); 625 DCHECK_EQ(reinterpret_cast<uptr>(pos + 1) & TracePart::kAlignment, 0); 626 auto *part = trace->parts.Back(); 627 DPrintf("TraceSwitchPart part=%p pos=%p\n", part, pos); 628 if (part) { 629 // We can get here when we still have space in the current trace part. 630 // The fast-path check in TraceAcquire has false positives in the middle of 631 // the part. Check if we are indeed at the end of the current part or not, 632 // and fill any gaps with NopEvent's. 633 Event *end = &part->events[TracePart::kSize]; 634 DCHECK_GE(pos, &part->events[0]); 635 DCHECK_LE(pos, end); 636 if (pos + 1 < end) { 637 if ((reinterpret_cast<uptr>(pos) & TracePart::kAlignment) == 638 TracePart::kAlignment) 639 *pos++ = NopEvent; 640 *pos++ = NopEvent; 641 DCHECK_LE(pos + 2, end); 642 atomic_store_relaxed(&thr->trace_pos, reinterpret_cast<uptr>(pos)); 643 // Ensure we setup trace so that the next TraceAcquire 644 // won't detect trace part end. 645 Event *ev; 646 CHECK(TraceAcquire(thr, &ev)); 647 return; 648 } 649 // We are indeed at the end. 650 for (; pos < end; pos++) *pos = NopEvent; 651 } 652 #if !SANITIZER_GO 653 if (ctx->after_multithreaded_fork) { 654 // We just need to survive till exec. 655 CHECK(part); 656 atomic_store_relaxed(&thr->trace_pos, 657 reinterpret_cast<uptr>(&part->events[0])); 658 return; 659 } 660 #endif 661 part = new (MmapOrDie(sizeof(TracePart), "TracePart")) TracePart(); 662 part->trace = trace; 663 thr->trace_prev_pc = 0; 664 { 665 Lock lock(&trace->mtx); 666 trace->parts.PushBack(part); 667 atomic_store_relaxed(&thr->trace_pos, 668 reinterpret_cast<uptr>(&part->events[0])); 669 } 670 // Make this part self-sufficient by restoring the current stack 671 // and mutex set in the beginning of the trace. 672 TraceTime(thr); 673 for (uptr *pos = &thr->shadow_stack[0]; pos < thr->shadow_stack_pos; pos++) 674 CHECK(TryTraceFunc(thr, *pos)); 675 for (uptr i = 0; i < thr->mset.Size(); i++) { 676 MutexSet::Desc d = thr->mset.Get(i); 677 TraceMutexLock(thr, d.write ? EventType::kLock : EventType::kRLock, 0, 678 d.addr, d.stack_id); 679 } 680 } 681 682 } // namespace v3 683 684 void TraceSwitch(ThreadState *thr) { 685 #if !SANITIZER_GO 686 if (ctx->after_multithreaded_fork) 687 return; 688 #endif 689 thr->nomalloc++; 690 Trace *thr_trace = ThreadTrace(thr->tid); 691 Lock l(&thr_trace->mtx); 692 unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts(); 693 TraceHeader *hdr = &thr_trace->headers[trace]; 694 hdr->epoch0 = thr->fast_state.epoch(); 695 ObtainCurrentStack(thr, 0, &hdr->stack0); 696 hdr->mset0 = thr->mset; 697 thr->nomalloc--; 698 } 699 700 Trace *ThreadTrace(Tid tid) { return (Trace *)GetThreadTraceHeader(tid); } 701 702 uptr TraceTopPC(ThreadState *thr) { 703 Event *events = (Event*)GetThreadTrace(thr->tid); 704 uptr pc = events[thr->fast_state.GetTracePos()]; 705 return pc; 706 } 707 708 uptr TraceSize() { 709 return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1)); 710 } 711 712 uptr TraceParts() { 713 return TraceSize() / kTracePartSize; 714 } 715 716 #if !SANITIZER_GO 717 extern "C" void __tsan_trace_switch() { 718 TraceSwitch(cur_thread()); 719 } 720 721 extern "C" void __tsan_report_race() { 722 ReportRace(cur_thread()); 723 } 724 #endif 725 726 void ThreadIgnoreBegin(ThreadState *thr, uptr pc) { 727 DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid); 728 thr->ignore_reads_and_writes++; 729 CHECK_GT(thr->ignore_reads_and_writes, 0); 730 thr->fast_state.SetIgnoreBit(); 731 #if !SANITIZER_GO 732 if (pc && !ctx->after_multithreaded_fork) 733 thr->mop_ignore_set.Add(CurrentStackId(thr, pc)); 734 #endif 735 } 736 737 void ThreadIgnoreEnd(ThreadState *thr) { 738 DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid); 739 CHECK_GT(thr->ignore_reads_and_writes, 0); 740 thr->ignore_reads_and_writes--; 741 if (thr->ignore_reads_and_writes == 0) { 742 thr->fast_state.ClearIgnoreBit(); 743 #if !SANITIZER_GO 744 thr->mop_ignore_set.Reset(); 745 #endif 746 } 747 } 748 749 #if !SANITIZER_GO 750 extern "C" SANITIZER_INTERFACE_ATTRIBUTE 751 uptr __tsan_testonly_shadow_stack_current_size() { 752 ThreadState *thr = cur_thread(); 753 return thr->shadow_stack_pos - thr->shadow_stack; 754 } 755 #endif 756 757 void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) { 758 DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid); 759 thr->ignore_sync++; 760 CHECK_GT(thr->ignore_sync, 0); 761 #if !SANITIZER_GO 762 if (pc && !ctx->after_multithreaded_fork) 763 thr->sync_ignore_set.Add(CurrentStackId(thr, pc)); 764 #endif 765 } 766 767 void ThreadIgnoreSyncEnd(ThreadState *thr) { 768 DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid); 769 CHECK_GT(thr->ignore_sync, 0); 770 thr->ignore_sync--; 771 #if !SANITIZER_GO 772 if (thr->ignore_sync == 0) 773 thr->sync_ignore_set.Reset(); 774 #endif 775 } 776 777 bool MD5Hash::operator==(const MD5Hash &other) const { 778 return hash[0] == other.hash[0] && hash[1] == other.hash[1]; 779 } 780 781 #if SANITIZER_DEBUG 782 void build_consistency_debug() {} 783 #else 784 void build_consistency_release() {} 785 #endif 786 787 } // namespace __tsan 788 789 #if SANITIZER_CHECK_DEADLOCKS 790 namespace __sanitizer { 791 using namespace __tsan; 792 MutexMeta mutex_meta[] = { 793 {MutexInvalid, "Invalid", {}}, 794 {MutexThreadRegistry, "ThreadRegistry", {}}, 795 {MutexTypeTrace, "Trace", {}}, 796 {MutexTypeReport, 797 "Report", 798 {MutexTypeSyncVar, MutexTypeGlobalProc, MutexTypeTrace}}, 799 {MutexTypeSyncVar, "SyncVar", {MutexTypeTrace}}, 800 {MutexTypeAnnotations, "Annotations", {}}, 801 {MutexTypeAtExit, "AtExit", {MutexTypeSyncVar}}, 802 {MutexTypeFired, "Fired", {MutexLeaf}}, 803 {MutexTypeRacy, "Racy", {MutexLeaf}}, 804 {MutexTypeGlobalProc, "GlobalProc", {}}, 805 {MutexTypeInternalAlloc, "InternalAlloc", {MutexLeaf}}, 806 {}, 807 }; 808 809 void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); } 810 } // namespace __sanitizer 811 #endif 812