1 //===-- tsan_rtl.h ----------------------------------------------*- C++ -*-===// 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 internal TSan header file. 12 // 13 // Ground rules: 14 // - C++ run-time should not be used (static CTORs, RTTI, exceptions, static 15 // function-scope locals) 16 // - All functions/classes/etc reside in namespace __tsan, except for those 17 // declared in tsan_interface.h. 18 // - Platform-specific files should be used instead of ifdefs (*). 19 // - No system headers included in header files (*). 20 // - Platform specific headres included only into platform-specific files (*). 21 // 22 // (*) Except when inlining is critical for performance. 23 //===----------------------------------------------------------------------===// 24 25 #ifndef TSAN_RTL_H 26 #define TSAN_RTL_H 27 28 #include "sanitizer_common/sanitizer_allocator.h" 29 #include "sanitizer_common/sanitizer_allocator_internal.h" 30 #include "sanitizer_common/sanitizer_asm.h" 31 #include "sanitizer_common/sanitizer_common.h" 32 #include "sanitizer_common/sanitizer_deadlock_detector_interface.h" 33 #include "sanitizer_common/sanitizer_libignore.h" 34 #include "sanitizer_common/sanitizer_suppressions.h" 35 #include "sanitizer_common/sanitizer_thread_registry.h" 36 #include "sanitizer_common/sanitizer_vector.h" 37 #include "tsan_defs.h" 38 #include "tsan_flags.h" 39 #include "tsan_ignoreset.h" 40 #include "tsan_ilist.h" 41 #include "tsan_mman.h" 42 #include "tsan_mutexset.h" 43 #include "tsan_platform.h" 44 #include "tsan_report.h" 45 #include "tsan_shadow.h" 46 #include "tsan_stack_trace.h" 47 #include "tsan_sync.h" 48 #include "tsan_trace.h" 49 #include "tsan_vector_clock.h" 50 51 #if SANITIZER_WORDSIZE != 64 52 # error "ThreadSanitizer is supported only on 64-bit platforms" 53 #endif 54 55 namespace __tsan { 56 57 #if !SANITIZER_GO 58 struct MapUnmapCallback; 59 #if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) 60 61 struct AP32 { 62 static const uptr kSpaceBeg = 0; 63 static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE; 64 static const uptr kMetadataSize = 0; 65 typedef __sanitizer::CompactSizeClassMap SizeClassMap; 66 static const uptr kRegionSizeLog = 20; 67 using AddressSpaceView = LocalAddressSpaceView; 68 typedef __tsan::MapUnmapCallback MapUnmapCallback; 69 static const uptr kFlags = 0; 70 }; 71 typedef SizeClassAllocator32<AP32> PrimaryAllocator; 72 #else 73 struct AP64 { // Allocator64 parameters. Deliberately using a short name. 74 # if defined(__s390x__) 75 typedef MappingS390x Mapping; 76 # else 77 typedef Mapping48AddressSpace Mapping; 78 # endif 79 static const uptr kSpaceBeg = Mapping::kHeapMemBeg; 80 static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg; 81 static const uptr kMetadataSize = 0; 82 typedef DefaultSizeClassMap SizeClassMap; 83 typedef __tsan::MapUnmapCallback MapUnmapCallback; 84 static const uptr kFlags = 0; 85 using AddressSpaceView = LocalAddressSpaceView; 86 }; 87 typedef SizeClassAllocator64<AP64> PrimaryAllocator; 88 #endif 89 typedef CombinedAllocator<PrimaryAllocator> Allocator; 90 typedef Allocator::AllocatorCache AllocatorCache; 91 Allocator *allocator(); 92 #endif 93 94 struct ThreadSignalContext; 95 96 struct JmpBuf { 97 uptr sp; 98 int int_signal_send; 99 bool in_blocking_func; 100 uptr in_signal_handler; 101 uptr *shadow_stack_pos; 102 }; 103 104 // A Processor represents a physical thread, or a P for Go. 105 // It is used to store internal resources like allocate cache, and does not 106 // participate in race-detection logic (invisible to end user). 107 // In C++ it is tied to an OS thread just like ThreadState, however ideally 108 // it should be tied to a CPU (this way we will have fewer allocator caches). 109 // In Go it is tied to a P, so there are significantly fewer Processor's than 110 // ThreadState's (which are tied to Gs). 111 // A ThreadState must be wired with a Processor to handle events. 112 struct Processor { 113 ThreadState *thr; // currently wired thread, or nullptr 114 #if !SANITIZER_GO 115 AllocatorCache alloc_cache; 116 InternalAllocatorCache internal_alloc_cache; 117 #endif 118 DenseSlabAllocCache block_cache; 119 DenseSlabAllocCache sync_cache; 120 DDPhysicalThread *dd_pt; 121 }; 122 123 #if !SANITIZER_GO 124 // ScopedGlobalProcessor temporary setups a global processor for the current 125 // thread, if it does not have one. Intended for interceptors that can run 126 // at the very thread end, when we already destroyed the thread processor. 127 struct ScopedGlobalProcessor { 128 ScopedGlobalProcessor(); 129 ~ScopedGlobalProcessor(); 130 }; 131 #endif 132 133 struct TidEpoch { 134 Tid tid; 135 Epoch epoch; 136 }; 137 138 struct TidSlot { 139 Mutex mtx; 140 Sid sid; 141 atomic_uint32_t raw_epoch; 142 ThreadState *thr; 143 Vector<TidEpoch> journal; 144 INode node; 145 146 Epoch epoch() const { 147 return static_cast<Epoch>(atomic_load(&raw_epoch, memory_order_relaxed)); 148 } 149 150 void SetEpoch(Epoch v) { 151 atomic_store(&raw_epoch, static_cast<u32>(v), memory_order_relaxed); 152 } 153 154 TidSlot(); 155 } ALIGNED(SANITIZER_CACHE_LINE_SIZE); 156 157 // This struct is stored in TLS. 158 struct ThreadState { 159 FastState fast_state; 160 int ignore_sync; 161 #if !SANITIZER_GO 162 int ignore_interceptors; 163 #endif 164 uptr *shadow_stack_pos; 165 166 // Current position in tctx->trace.Back()->events (Event*). 167 atomic_uintptr_t trace_pos; 168 // PC of the last memory access, used to compute PC deltas in the trace. 169 uptr trace_prev_pc; 170 171 // Technically `current` should be a separate THREADLOCAL variable; 172 // but it is placed here in order to share cache line with previous fields. 173 ThreadState* current; 174 175 atomic_sint32_t pending_signals; 176 177 VectorClock clock; 178 179 // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read. 180 // We do not distinguish beteween ignoring reads and writes 181 // for better performance. 182 int ignore_reads_and_writes; 183 int suppress_reports; 184 // Go does not support ignores. 185 #if !SANITIZER_GO 186 IgnoreSet mop_ignore_set; 187 IgnoreSet sync_ignore_set; 188 #endif 189 uptr *shadow_stack; 190 uptr *shadow_stack_end; 191 #if !SANITIZER_GO 192 Vector<JmpBuf> jmp_bufs; 193 int in_symbolizer; 194 bool in_ignored_lib; 195 bool is_inited; 196 #endif 197 MutexSet mset; 198 bool is_dead; 199 const Tid tid; 200 uptr stk_addr; 201 uptr stk_size; 202 uptr tls_addr; 203 uptr tls_size; 204 ThreadContext *tctx; 205 206 DDLogicalThread *dd_lt; 207 208 TidSlot *slot; 209 uptr slot_epoch; 210 bool slot_locked; 211 212 // Current wired Processor, or nullptr. Required to handle any events. 213 Processor *proc1; 214 #if !SANITIZER_GO 215 Processor *proc() { return proc1; } 216 #else 217 Processor *proc(); 218 #endif 219 220 atomic_uintptr_t in_signal_handler; 221 ThreadSignalContext *signal_ctx; 222 223 #if !SANITIZER_GO 224 StackID last_sleep_stack_id; 225 VectorClock last_sleep_clock; 226 #endif 227 228 // Set in regions of runtime that must be signal-safe and fork-safe. 229 // If set, malloc must not be called. 230 int nomalloc; 231 232 const ReportDesc *current_report; 233 234 explicit ThreadState(Tid tid); 235 } ALIGNED(SANITIZER_CACHE_LINE_SIZE); 236 237 #if !SANITIZER_GO 238 #if SANITIZER_APPLE || SANITIZER_ANDROID 239 ThreadState *cur_thread(); 240 void set_cur_thread(ThreadState *thr); 241 void cur_thread_finalize(); 242 inline ThreadState *cur_thread_init() { return cur_thread(); } 243 # else 244 __attribute__((tls_model("initial-exec"))) 245 extern THREADLOCAL char cur_thread_placeholder[]; 246 inline ThreadState *cur_thread() { 247 return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current; 248 } 249 inline ThreadState *cur_thread_init() { 250 ThreadState *thr = reinterpret_cast<ThreadState *>(cur_thread_placeholder); 251 if (UNLIKELY(!thr->current)) 252 thr->current = thr; 253 return thr->current; 254 } 255 inline void set_cur_thread(ThreadState *thr) { 256 reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr; 257 } 258 inline void cur_thread_finalize() { } 259 # endif // SANITIZER_APPLE || SANITIZER_ANDROID 260 #endif // SANITIZER_GO 261 262 class ThreadContext final : public ThreadContextBase { 263 public: 264 explicit ThreadContext(Tid tid); 265 ~ThreadContext(); 266 ThreadState *thr; 267 StackID creation_stack_id; 268 VectorClock *sync; 269 uptr sync_epoch; 270 Trace trace; 271 272 // Override superclass callbacks. 273 void OnDead() override; 274 void OnJoined(void *arg) override; 275 void OnFinished() override; 276 void OnStarted(void *arg) override; 277 void OnCreated(void *arg) override; 278 void OnReset() override; 279 void OnDetached(void *arg) override; 280 }; 281 282 struct RacyStacks { 283 MD5Hash hash[2]; 284 bool operator==(const RacyStacks &other) const; 285 }; 286 287 struct RacyAddress { 288 uptr addr_min; 289 uptr addr_max; 290 }; 291 292 struct FiredSuppression { 293 ReportType type; 294 uptr pc_or_addr; 295 Suppression *supp; 296 }; 297 298 struct Context { 299 Context(); 300 301 bool initialized; 302 #if !SANITIZER_GO 303 bool after_multithreaded_fork; 304 #endif 305 306 MetaMap metamap; 307 308 Mutex report_mtx; 309 int nreported; 310 atomic_uint64_t last_symbolize_time_ns; 311 312 void *background_thread; 313 atomic_uint32_t stop_background_thread; 314 315 ThreadRegistry thread_registry; 316 317 // This is used to prevent a very unlikely but very pathological behavior. 318 // Since memory access handling is not synchronized with DoReset, 319 // a thread running concurrently with DoReset can leave a bogus shadow value 320 // that will be later falsely detected as a race. For such false races 321 // RestoreStack will return false and we will not report it. 322 // However, consider that a thread leaves a whole lot of such bogus values 323 // and these values are later read by a whole lot of threads. 324 // This will cause massive amounts of ReportRace calls and lots of 325 // serialization. In very pathological cases the resulting slowdown 326 // can be >100x. This is very unlikely, but it was presumably observed 327 // in practice: https://github.com/google/sanitizers/issues/1552 328 // If this happens, previous access sid+epoch will be the same for all of 329 // these false races b/c if the thread will try to increment epoch, it will 330 // notice that DoReset has happened and will stop producing bogus shadow 331 // values. So, last_spurious_race is used to remember the last sid+epoch 332 // for which RestoreStack returned false. Then it is used to filter out 333 // races with the same sid+epoch very early and quickly. 334 // It is of course possible that multiple threads left multiple bogus shadow 335 // values and all of them are read by lots of threads at the same time. 336 // In such case last_spurious_race will only be able to deduplicate a few 337 // races from one thread, then few from another and so on. An alternative 338 // would be to hold an array of such sid+epoch, but we consider such scenario 339 // as even less likely. 340 // Note: this can lead to some rare false negatives as well: 341 // 1. When a legit access with the same sid+epoch participates in a race 342 // as the "previous" memory access, it will be wrongly filtered out. 343 // 2. When RestoreStack returns false for a legit memory access because it 344 // was already evicted from the thread trace, we will still remember it in 345 // last_spurious_race. Then if there is another racing memory access from 346 // the same thread that happened in the same epoch, but was stored in the 347 // next thread trace part (which is still preserved in the thread trace), 348 // we will also wrongly filter it out while RestoreStack would actually 349 // succeed for that second memory access. 350 RawShadow last_spurious_race; 351 352 Mutex racy_mtx; 353 Vector<RacyStacks> racy_stacks; 354 // Number of fired suppressions may be large enough. 355 Mutex fired_suppressions_mtx; 356 InternalMmapVector<FiredSuppression> fired_suppressions; 357 DDetector *dd; 358 359 Flags flags; 360 fd_t memprof_fd; 361 362 // The last slot index (kFreeSid) is used to denote freed memory. 363 TidSlot slots[kThreadSlotCount - 1]; 364 365 // Protects global_epoch, slot_queue, trace_part_recycle. 366 Mutex slot_mtx; 367 uptr global_epoch; // guarded by slot_mtx and by all slot mutexes 368 bool resetting; // global reset is in progress 369 IList<TidSlot, &TidSlot::node> slot_queue SANITIZER_GUARDED_BY(slot_mtx); 370 IList<TraceHeader, &TraceHeader::global, TracePart> trace_part_recycle 371 SANITIZER_GUARDED_BY(slot_mtx); 372 uptr trace_part_total_allocated SANITIZER_GUARDED_BY(slot_mtx); 373 uptr trace_part_recycle_finished SANITIZER_GUARDED_BY(slot_mtx); 374 uptr trace_part_finished_excess SANITIZER_GUARDED_BY(slot_mtx); 375 #if SANITIZER_GO 376 uptr mapped_shadow_begin; 377 uptr mapped_shadow_end; 378 #endif 379 }; 380 381 extern Context *ctx; // The one and the only global runtime context. 382 383 ALWAYS_INLINE Flags *flags() { 384 return &ctx->flags; 385 } 386 387 struct ScopedIgnoreInterceptors { 388 ScopedIgnoreInterceptors() { 389 #if !SANITIZER_GO 390 cur_thread()->ignore_interceptors++; 391 #endif 392 } 393 394 ~ScopedIgnoreInterceptors() { 395 #if !SANITIZER_GO 396 cur_thread()->ignore_interceptors--; 397 #endif 398 } 399 }; 400 401 const char *GetObjectTypeFromTag(uptr tag); 402 const char *GetReportHeaderFromTag(uptr tag); 403 uptr TagFromShadowStackFrame(uptr pc); 404 405 class ScopedReportBase { 406 public: 407 void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, Tid tid, 408 StackTrace stack, const MutexSet *mset); 409 void AddStack(StackTrace stack, bool suppressable = false); 410 void AddThread(const ThreadContext *tctx, bool suppressable = false); 411 void AddThread(Tid tid, bool suppressable = false); 412 void AddUniqueTid(Tid unique_tid); 413 int AddMutex(uptr addr, StackID creation_stack_id); 414 void AddLocation(uptr addr, uptr size); 415 void AddSleep(StackID stack_id); 416 void SetCount(int count); 417 void SetSigNum(int sig); 418 419 const ReportDesc *GetReport() const; 420 421 protected: 422 ScopedReportBase(ReportType typ, uptr tag); 423 ~ScopedReportBase(); 424 425 private: 426 ReportDesc *rep_; 427 // Symbolizer makes lots of intercepted calls. If we try to process them, 428 // at best it will cause deadlocks on internal mutexes. 429 ScopedIgnoreInterceptors ignore_interceptors_; 430 431 ScopedReportBase(const ScopedReportBase &) = delete; 432 void operator=(const ScopedReportBase &) = delete; 433 }; 434 435 class ScopedReport : public ScopedReportBase { 436 public: 437 explicit ScopedReport(ReportType typ, uptr tag = kExternalTagNone); 438 ~ScopedReport(); 439 440 private: 441 ScopedErrorReportLock lock_; 442 }; 443 444 bool ShouldReport(ThreadState *thr, ReportType typ); 445 ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack); 446 447 // The stack could look like: 448 // <start> | <main> | <foo> | tag | <bar> 449 // This will extract the tag and keep: 450 // <start> | <main> | <foo> | <bar> 451 template<typename StackTraceTy> 452 void ExtractTagFromStack(StackTraceTy *stack, uptr *tag = nullptr) { 453 if (stack->size < 2) return; 454 uptr possible_tag_pc = stack->trace[stack->size - 2]; 455 uptr possible_tag = TagFromShadowStackFrame(possible_tag_pc); 456 if (possible_tag == kExternalTagNone) return; 457 stack->trace_buffer[stack->size - 2] = stack->trace_buffer[stack->size - 1]; 458 stack->size -= 1; 459 if (tag) *tag = possible_tag; 460 } 461 462 template<typename StackTraceTy> 463 void ObtainCurrentStack(ThreadState *thr, uptr toppc, StackTraceTy *stack, 464 uptr *tag = nullptr) { 465 uptr size = thr->shadow_stack_pos - thr->shadow_stack; 466 uptr start = 0; 467 if (size + !!toppc > kStackTraceMax) { 468 start = size + !!toppc - kStackTraceMax; 469 size = kStackTraceMax - !!toppc; 470 } 471 stack->Init(&thr->shadow_stack[start], size, toppc); 472 ExtractTagFromStack(stack, tag); 473 } 474 475 #define GET_STACK_TRACE_FATAL(thr, pc) \ 476 VarSizeStackTrace stack; \ 477 ObtainCurrentStack(thr, pc, &stack); \ 478 stack.ReverseOrder(); 479 480 void MapShadow(uptr addr, uptr size); 481 void MapThreadTrace(uptr addr, uptr size, const char *name); 482 void DontNeedShadowFor(uptr addr, uptr size); 483 void UnmapShadow(ThreadState *thr, uptr addr, uptr size); 484 void InitializeShadowMemory(); 485 void InitializeInterceptors(); 486 void InitializeLibIgnore(); 487 void InitializeDynamicAnnotations(); 488 489 void ForkBefore(ThreadState *thr, uptr pc); 490 void ForkParentAfter(ThreadState *thr, uptr pc); 491 void ForkChildAfter(ThreadState *thr, uptr pc, bool start_thread); 492 493 void ReportRace(ThreadState *thr, RawShadow *shadow_mem, Shadow cur, Shadow old, 494 AccessType typ); 495 bool OutputReport(ThreadState *thr, const ScopedReport &srep); 496 bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace); 497 bool IsExpectedReport(uptr addr, uptr size); 498 499 #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1 500 # define DPrintf Printf 501 #else 502 # define DPrintf(...) 503 #endif 504 505 #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 2 506 # define DPrintf2 Printf 507 #else 508 # define DPrintf2(...) 509 #endif 510 511 StackID CurrentStackId(ThreadState *thr, uptr pc); 512 ReportStack *SymbolizeStackId(StackID stack_id); 513 void PrintCurrentStack(ThreadState *thr, uptr pc); 514 void PrintCurrentStackSlow(uptr pc); // uses libunwind 515 MBlock *JavaHeapBlock(uptr addr, uptr *start); 516 517 void Initialize(ThreadState *thr); 518 void MaybeSpawnBackgroundThread(); 519 int Finalize(ThreadState *thr); 520 521 void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write); 522 void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write); 523 524 void MemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size, 525 AccessType typ); 526 void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size, 527 AccessType typ); 528 // This creates 2 non-inlined specialized versions of MemoryAccessRange. 529 template <bool is_read> 530 void MemoryAccessRangeT(ThreadState *thr, uptr pc, uptr addr, uptr size); 531 532 ALWAYS_INLINE 533 void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size, 534 bool is_write) { 535 if (size == 0) 536 return; 537 if (is_write) 538 MemoryAccessRangeT<false>(thr, pc, addr, size); 539 else 540 MemoryAccessRangeT<true>(thr, pc, addr, size); 541 } 542 543 void ShadowSet(RawShadow *p, RawShadow *end, RawShadow v); 544 void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size); 545 void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size); 546 void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size); 547 void MemoryRangeImitateWriteOrResetRange(ThreadState *thr, uptr pc, uptr addr, 548 uptr size); 549 550 void ThreadIgnoreBegin(ThreadState *thr, uptr pc); 551 void ThreadIgnoreEnd(ThreadState *thr); 552 void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc); 553 void ThreadIgnoreSyncEnd(ThreadState *thr); 554 555 Tid ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached); 556 void ThreadStart(ThreadState *thr, Tid tid, tid_t os_id, 557 ThreadType thread_type); 558 void ThreadFinish(ThreadState *thr); 559 Tid ThreadConsumeTid(ThreadState *thr, uptr pc, uptr uid); 560 void ThreadJoin(ThreadState *thr, uptr pc, Tid tid); 561 void ThreadDetach(ThreadState *thr, uptr pc, Tid tid); 562 void ThreadFinalize(ThreadState *thr); 563 void ThreadSetName(ThreadState *thr, const char *name); 564 int ThreadCount(ThreadState *thr); 565 void ProcessPendingSignalsImpl(ThreadState *thr); 566 void ThreadNotJoined(ThreadState *thr, uptr pc, Tid tid, uptr uid); 567 568 Processor *ProcCreate(); 569 void ProcDestroy(Processor *proc); 570 void ProcWire(Processor *proc, ThreadState *thr); 571 void ProcUnwire(Processor *proc, ThreadState *thr); 572 573 // Note: the parameter is called flagz, because flags is already taken 574 // by the global function that returns flags. 575 void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); 576 void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); 577 void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); 578 void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0, 579 int rec = 1); 580 int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); 581 void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); 582 void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0); 583 void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr); 584 void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr); 585 void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD 586 void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr); 587 588 void Acquire(ThreadState *thr, uptr pc, uptr addr); 589 // AcquireGlobal synchronizes the current thread with all other threads. 590 // In terms of happens-before relation, it draws a HB edge from all threads 591 // (where they happen to execute right now) to the current thread. We use it to 592 // handle Go finalizers. Namely, finalizer goroutine executes AcquireGlobal 593 // right before executing finalizers. This provides a coarse, but simple 594 // approximation of the actual required synchronization. 595 void AcquireGlobal(ThreadState *thr); 596 void Release(ThreadState *thr, uptr pc, uptr addr); 597 void ReleaseStoreAcquire(ThreadState *thr, uptr pc, uptr addr); 598 void ReleaseStore(ThreadState *thr, uptr pc, uptr addr); 599 void AfterSleep(ThreadState *thr, uptr pc); 600 void IncrementEpoch(ThreadState *thr); 601 602 #if !SANITIZER_GO 603 uptr ALWAYS_INLINE HeapEnd() { 604 return HeapMemEnd() + PrimaryAllocator::AdditionalSize(); 605 } 606 #endif 607 608 void SlotAttachAndLock(ThreadState *thr) SANITIZER_ACQUIRE(thr->slot->mtx); 609 void SlotDetach(ThreadState *thr); 610 void SlotLock(ThreadState *thr) SANITIZER_ACQUIRE(thr->slot->mtx); 611 void SlotUnlock(ThreadState *thr) SANITIZER_RELEASE(thr->slot->mtx); 612 void DoReset(ThreadState *thr, uptr epoch); 613 void FlushShadowMemory(); 614 615 ThreadState *FiberCreate(ThreadState *thr, uptr pc, unsigned flags); 616 void FiberDestroy(ThreadState *thr, uptr pc, ThreadState *fiber); 617 void FiberSwitch(ThreadState *thr, uptr pc, ThreadState *fiber, unsigned flags); 618 619 // These need to match __tsan_switch_to_fiber_* flags defined in 620 // tsan_interface.h. See documentation there as well. 621 enum FiberSwitchFlags { 622 FiberSwitchFlagNoSync = 1 << 0, // __tsan_switch_to_fiber_no_sync 623 }; 624 625 class SlotLocker { 626 public: 627 ALWAYS_INLINE 628 SlotLocker(ThreadState *thr, bool recursive = false) 629 : thr_(thr), locked_(recursive ? thr->slot_locked : false) { 630 if (!locked_) 631 SlotLock(thr_); 632 } 633 634 ALWAYS_INLINE 635 ~SlotLocker() { 636 if (!locked_) 637 SlotUnlock(thr_); 638 } 639 640 private: 641 ThreadState *thr_; 642 bool locked_; 643 }; 644 645 class SlotUnlocker { 646 public: 647 SlotUnlocker(ThreadState *thr) : thr_(thr), locked_(thr->slot_locked) { 648 if (locked_) 649 SlotUnlock(thr_); 650 } 651 652 ~SlotUnlocker() { 653 if (locked_) 654 SlotLock(thr_); 655 } 656 657 private: 658 ThreadState *thr_; 659 bool locked_; 660 }; 661 662 ALWAYS_INLINE void ProcessPendingSignals(ThreadState *thr) { 663 if (UNLIKELY(atomic_load_relaxed(&thr->pending_signals))) 664 ProcessPendingSignalsImpl(thr); 665 } 666 667 extern bool is_initialized; 668 669 ALWAYS_INLINE 670 void LazyInitialize(ThreadState *thr) { 671 // If we can use .preinit_array, assume that __tsan_init 672 // called from .preinit_array initializes runtime before 673 // any instrumented code. 674 #if !SANITIZER_CAN_USE_PREINIT_ARRAY 675 if (UNLIKELY(!is_initialized)) 676 Initialize(thr); 677 #endif 678 } 679 680 void TraceResetForTesting(); 681 void TraceSwitchPart(ThreadState *thr); 682 void TraceSwitchPartImpl(ThreadState *thr); 683 bool RestoreStack(EventType type, Sid sid, Epoch epoch, uptr addr, uptr size, 684 AccessType typ, Tid *ptid, VarSizeStackTrace *pstk, 685 MutexSet *pmset, uptr *ptag); 686 687 template <typename EventT> 688 ALWAYS_INLINE WARN_UNUSED_RESULT bool TraceAcquire(ThreadState *thr, 689 EventT **ev) { 690 // TraceSwitchPart accesses shadow_stack, but it's called infrequently, 691 // so we check it here proactively. 692 DCHECK(thr->shadow_stack); 693 Event *pos = reinterpret_cast<Event *>(atomic_load_relaxed(&thr->trace_pos)); 694 #if SANITIZER_DEBUG 695 // TraceSwitch acquires these mutexes, 696 // so we lock them here to detect deadlocks more reliably. 697 { Lock lock(&ctx->slot_mtx); } 698 { Lock lock(&thr->tctx->trace.mtx); } 699 TracePart *current = thr->tctx->trace.parts.Back(); 700 if (current) { 701 DCHECK_GE(pos, ¤t->events[0]); 702 DCHECK_LE(pos, ¤t->events[TracePart::kSize]); 703 } else { 704 DCHECK_EQ(pos, nullptr); 705 } 706 #endif 707 // TracePart is allocated with mmap and is at least 4K aligned. 708 // So the following check is a faster way to check for part end. 709 // It may have false positives in the middle of the trace, 710 // they are filtered out in TraceSwitch. 711 if (UNLIKELY(((uptr)(pos + 1) & TracePart::kAlignment) == 0)) 712 return false; 713 *ev = reinterpret_cast<EventT *>(pos); 714 return true; 715 } 716 717 template <typename EventT> 718 ALWAYS_INLINE void TraceRelease(ThreadState *thr, EventT *evp) { 719 DCHECK_LE(evp + 1, &thr->tctx->trace.parts.Back()->events[TracePart::kSize]); 720 atomic_store_relaxed(&thr->trace_pos, (uptr)(evp + 1)); 721 } 722 723 template <typename EventT> 724 void TraceEvent(ThreadState *thr, EventT ev) { 725 EventT *evp; 726 if (!TraceAcquire(thr, &evp)) { 727 TraceSwitchPart(thr); 728 UNUSED bool res = TraceAcquire(thr, &evp); 729 DCHECK(res); 730 } 731 *evp = ev; 732 TraceRelease(thr, evp); 733 } 734 735 ALWAYS_INLINE WARN_UNUSED_RESULT bool TryTraceFunc(ThreadState *thr, 736 uptr pc = 0) { 737 if (!kCollectHistory) 738 return true; 739 EventFunc *ev; 740 if (UNLIKELY(!TraceAcquire(thr, &ev))) 741 return false; 742 ev->is_access = 0; 743 ev->is_func = 1; 744 ev->pc = pc; 745 TraceRelease(thr, ev); 746 return true; 747 } 748 749 WARN_UNUSED_RESULT 750 bool TryTraceMemoryAccess(ThreadState *thr, uptr pc, uptr addr, uptr size, 751 AccessType typ); 752 WARN_UNUSED_RESULT 753 bool TryTraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size, 754 AccessType typ); 755 void TraceMemoryAccessRange(ThreadState *thr, uptr pc, uptr addr, uptr size, 756 AccessType typ); 757 void TraceFunc(ThreadState *thr, uptr pc = 0); 758 void TraceMutexLock(ThreadState *thr, EventType type, uptr pc, uptr addr, 759 StackID stk); 760 void TraceMutexUnlock(ThreadState *thr, uptr addr); 761 void TraceTime(ThreadState *thr); 762 763 void TraceRestartFuncExit(ThreadState *thr); 764 void TraceRestartFuncEntry(ThreadState *thr, uptr pc); 765 766 void GrowShadowStack(ThreadState *thr); 767 768 ALWAYS_INLINE 769 void FuncEntry(ThreadState *thr, uptr pc) { 770 DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.sid(), (void *)pc); 771 if (UNLIKELY(!TryTraceFunc(thr, pc))) 772 return TraceRestartFuncEntry(thr, pc); 773 DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack); 774 #if !SANITIZER_GO 775 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end); 776 #else 777 if (thr->shadow_stack_pos == thr->shadow_stack_end) 778 GrowShadowStack(thr); 779 #endif 780 thr->shadow_stack_pos[0] = pc; 781 thr->shadow_stack_pos++; 782 } 783 784 ALWAYS_INLINE 785 void FuncExit(ThreadState *thr) { 786 DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.sid()); 787 if (UNLIKELY(!TryTraceFunc(thr, 0))) 788 return TraceRestartFuncExit(thr); 789 DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack); 790 #if !SANITIZER_GO 791 DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end); 792 #endif 793 thr->shadow_stack_pos--; 794 } 795 796 #if !SANITIZER_GO 797 extern void (*on_initialize)(void); 798 extern int (*on_finalize)(int); 799 #endif 800 } // namespace __tsan 801 802 #endif // TSAN_RTL_H 803