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
epochTidSlot146 Epoch epoch() const {
147 return static_cast<Epoch>(atomic_load(&raw_epoch, memory_order_relaxed));
148 }
149
SetEpochTidSlot150 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
procThreadState215 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();
cur_thread_init()242 inline ThreadState *cur_thread_init() { return cur_thread(); }
243 # else
244 __attribute__((tls_model("initial-exec")))
245 extern THREADLOCAL char cur_thread_placeholder[];
cur_thread()246 inline ThreadState *cur_thread() {
247 return reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current;
248 }
cur_thread_init()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 }
set_cur_thread(ThreadState * thr)255 inline void set_cur_thread(ThreadState *thr) {
256 reinterpret_cast<ThreadState *>(cur_thread_placeholder)->current = thr;
257 }
cur_thread_finalize()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
flags()383 ALWAYS_INLINE Flags *flags() {
384 return &ctx->flags;
385 }
386
387 struct ScopedIgnoreInterceptors {
ScopedIgnoreInterceptorsScopedIgnoreInterceptors388 ScopedIgnoreInterceptors() {
389 #if !SANITIZER_GO
390 cur_thread()->ignore_interceptors++;
391 #endif
392 }
393
~ScopedIgnoreInterceptorsScopedIgnoreInterceptors394 ~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
MemoryAccessRange(ThreadState * thr,uptr pc,uptr addr,uptr size,bool is_write)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
HeapEnd()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)
thr_(thr)629 : thr_(thr), locked_(recursive ? thr->slot_locked : false) {
630 if (!locked_)
631 SlotLock(thr_);
632 }
633
634 ALWAYS_INLINE
~SlotLocker()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:
SlotUnlocker(ThreadState * thr)647 SlotUnlocker(ThreadState *thr) : thr_(thr), locked_(thr->slot_locked) {
648 if (locked_)
649 SlotUnlock(thr_);
650 }
651
~SlotUnlocker()652 ~SlotUnlocker() {
653 if (locked_)
654 SlotLock(thr_);
655 }
656
657 private:
658 ThreadState *thr_;
659 bool locked_;
660 };
661
ProcessPendingSignals(ThreadState * thr)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
LazyInitialize(ThreadState * thr)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>
TraceAcquire(ThreadState * thr,EventT ** ev)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>
TraceRelease(ThreadState * thr,EventT * evp)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>
TraceEvent(ThreadState * thr,EventT ev)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
FuncEntry(ThreadState * thr,uptr pc)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
FuncExit(ThreadState * thr)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