llvm/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp

//===-- tsan_rtl.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of ThreadSanitizer (TSan), a race detector.
//
// Main file (entry points) for the TSan run-time.
//===----------------------------------------------------------------------===//

#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;

// Can be overriden by a front-end.
#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) {}

// Clang does not understand locking all slots in the loop:
// error: expecting mutex 'slot.mtx' to be held at start of each loop
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() :{}

// The objects are allocated in TLS, so one may rely on zero-initialization.
ThreadState::ThreadState(Tid tid)
    // Do not touch these, rely on zero initialization,
    // they may be accessed before the ctor.
    // ignore_reads_and_writes()
    // ignore_interceptors()
    :{}

#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
// We call UnmapShadow before the actual munmap, at that point we don't yet
// know if the provided address/size are sane. We can't call UnmapShadow
// after the actual munmap becuase at that point the memory range can
// already be reused for something else, so we can't rely on the munmap
// return value to understand is the values are sane.
// While calling munmap with insane values (non-canonical address, negative
// size, etc) is an error, the kernel won't crash. We must also try to not
// crash as the failure mode is very confusing (paging fault inside of the
// runtime on some derived shadow address).
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
}  // namespace __tsan

#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(); }

}  // namespace __sanitizer
#endif