#include "tsan_rtl.h"
#include "sanitizer_common/sanitizer_atomic.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_file.h"
#include "sanitizer_common/sanitizer_interface_internal.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
#include "tsan_defs.h"
#include "tsan_interface.h"
#include "tsan_mman.h"
#include "tsan_platform.h"
#include "tsan_suppressions.h"
#include "tsan_symbolize.h"
#include "ubsan/ubsan_init.h"
volatile int __tsan_resumed = …;
extern "C" void __tsan_resume() { … }
#if SANITIZER_APPLE
SANITIZER_WEAK_DEFAULT_IMPL
void __tsan_test_only_on_fork() {}
#endif
namespace __tsan {
#if !SANITIZER_GO
void (*on_initialize)(void);
int (*on_finalize)(int);
#endif
#if !SANITIZER_GO && !SANITIZER_APPLE
alignas(SANITIZER_CACHE_LINE_SIZE) THREADLOCAL __attribute__((tls_model(
"initial-exec"))) char cur_thread_placeholder[sizeof(ThreadState)];
#endif
alignas(SANITIZER_CACHE_LINE_SIZE) static char ctx_placeholder[sizeof(Context)];
Context *ctx;
#ifdef TSAN_EXTERNAL_HOOKS
bool OnFinalize(bool failed);
void OnInitialize();
#else
SANITIZER_WEAK_CXX_DEFAULT_IMPL
bool OnFinalize(bool failed) { … }
SANITIZER_WEAK_CXX_DEFAULT_IMPL
void OnInitialize() { … }
#endif
static TracePart* TracePartAlloc(ThreadState* thr) { … }
static void TracePartFree(TracePart* part) SANITIZER_REQUIRES(ctx->slot_mtx) { … }
void TraceResetForTesting() { … }
static void DoResetImpl(uptr epoch) { … }
void DoReset(ThreadState* thr, uptr epoch) SANITIZER_NO_THREAD_SAFETY_ANALYSIS { … }
void FlushShadowMemory() { … }
static TidSlot* FindSlotAndLock(ThreadState* thr)
SANITIZER_ACQUIRE(thr->slot->mtx) SANITIZER_NO_THREAD_SAFETY_ANALYSIS { … }
void SlotAttachAndLock(ThreadState* thr) { … }
static void SlotDetachImpl(ThreadState* thr, bool exiting) { … }
void SlotDetach(ThreadState* thr) { … }
void SlotLock(ThreadState* thr) SANITIZER_NO_THREAD_SAFETY_ANALYSIS { … }
void SlotUnlock(ThreadState* thr) { … }
Context::Context()
: … { … }
TidSlot::TidSlot() : … { … }
ThreadState::ThreadState(Tid tid)
: … { … }
#if !SANITIZER_GO
void MemoryProfiler(u64 uptime) { … }
static bool InitializeMemoryProfiler() { … }
static void *BackgroundThread(void *arg) { … }
static void StartBackgroundThread() { … }
#ifndef __mips__
static void StopBackgroundThread() { … }
#endif
#endif
void DontNeedShadowFor(uptr addr, uptr size) { … }
#if !SANITIZER_GO
static bool IsValidMmapRange(uptr addr, uptr size) { … }
void UnmapShadow(ThreadState *thr, uptr addr, uptr size) { … }
#endif
void MapShadow(uptr addr, uptr size) { … }
#if !SANITIZER_GO
static void OnStackUnwind(const SignalContext &sig, const void *,
BufferedStackTrace *stack) { … }
static void TsanOnDeadlySignal(int signo, void *siginfo, void *context) { … }
#endif
void CheckUnwind() { … }
bool is_initialized;
void Initialize(ThreadState *thr) { … }
void MaybeSpawnBackgroundThread() { … }
int Finalize(ThreadState *thr) { … }
#if !SANITIZER_GO
void ForkBefore(ThreadState* thr, uptr pc) SANITIZER_NO_THREAD_SAFETY_ANALYSIS { … }
static void ForkAfter(ThreadState* thr,
bool child) SANITIZER_NO_THREAD_SAFETY_ANALYSIS { … }
void ForkParentAfter(ThreadState* thr, uptr pc) { … }
void ForkChildAfter(ThreadState* thr, uptr pc, bool start_thread) { … }
#endif
#if SANITIZER_GO
NOINLINE
void GrowShadowStack(ThreadState *thr) {
const int sz = thr->shadow_stack_end - thr->shadow_stack;
const int newsz = 2 * sz;
auto *newstack = (uptr *)Alloc(newsz * sizeof(uptr));
internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
Free(thr->shadow_stack);
thr->shadow_stack = newstack;
thr->shadow_stack_pos = newstack + sz;
thr->shadow_stack_end = newstack + newsz;
}
#endif
StackID CurrentStackId(ThreadState *thr, uptr pc) { … }
static bool TraceSkipGap(ThreadState* thr) { … }
NOINLINE
void TraceSwitchPart(ThreadState* thr) { … }
void TraceSwitchPartImpl(ThreadState* thr) { … }
void ThreadIgnoreBegin(ThreadState* thr, uptr pc) { … }
void ThreadIgnoreEnd(ThreadState *thr) { … }
#if !SANITIZER_GO
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
uptr __tsan_testonly_shadow_stack_current_size() { … }
#endif
void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) { … }
void ThreadIgnoreSyncEnd(ThreadState *thr) { … }
bool MD5Hash::operator==(const MD5Hash &other) const { … }
#if SANITIZER_DEBUG
void build_consistency_debug() {}
#else
void build_consistency_release() { … }
#endif
}
#if SANITIZER_CHECK_DEADLOCKS
namespace __sanitizer {
using namespace __tsan;
MutexMeta mutex_meta[] = {
{MutexInvalid, "Invalid", {}},
{MutexThreadRegistry,
"ThreadRegistry",
{MutexTypeSlots, MutexTypeTrace, MutexTypeReport}},
{MutexTypeReport, "Report", {MutexTypeTrace}},
{MutexTypeSyncVar, "SyncVar", {MutexTypeReport, MutexTypeTrace}},
{MutexTypeAnnotations, "Annotations", {}},
{MutexTypeAtExit, "AtExit", {}},
{MutexTypeFired, "Fired", {MutexLeaf}},
{MutexTypeRacy, "Racy", {MutexLeaf}},
{MutexTypeGlobalProc, "GlobalProc", {MutexTypeSlot, MutexTypeSlots}},
{MutexTypeInternalAlloc, "InternalAlloc", {MutexLeaf}},
{MutexTypeTrace, "Trace", {}},
{MutexTypeSlot,
"Slot",
{MutexMulti, MutexTypeTrace, MutexTypeSyncVar, MutexThreadRegistry,
MutexTypeSlots}},
{MutexTypeSlots, "Slots", {MutexTypeTrace, MutexTypeReport}},
{},
};
void PrintMutexPC(uptr pc) { StackTrace(&pc, 1).Print(); }
}
#endif