#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_posix.h"
#include "sanitizer_common/sanitizer_procmaps.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_stoptheworld.h"
#include "tsan_flags.h"
#include "tsan_platform.h"
#include "tsan_rtl.h"
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/mman.h>
#if SANITIZER_LINUX
#include <sys/personality.h>
#include <setjmp.h>
#endif
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sched.h>
#include <dlfcn.h>
#if SANITIZER_LINUX
#define __need_res_state
#include <resolv.h>
#endif
#ifdef sa_handler
# undef sa_handler
#endif
#ifdef sa_sigaction
# undef sa_sigaction
#endif
#if SANITIZER_FREEBSD
extern "C" void *__libc_stack_end;
void *__libc_stack_end = 0;
#endif
#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__loongarch_lp64)) && \
!SANITIZER_GO
#define INIT_LONGJMP_XOR_KEY …
#else
#define INIT_LONGJMP_XOR_KEY …
#endif
#if INIT_LONGJMP_XOR_KEY
#include "interception/interception.h"
DECLARE_REAL(int, _setjmp, void *env)
#endif
namespace __tsan {
#if INIT_LONGJMP_XOR_KEY
static void InitializeLongjmpXorKey();
static uptr longjmp_xor_key;
#endif
uptr vmaSize;
enum { … };
void FillProfileCallback(uptr p, uptr rss, bool file, uptr *mem) { … }
void WriteMemoryProfile(char *buf, uptr buf_size, u64 uptime_ns) { … }
#if !SANITIZER_GO
static NOINLINE void MapRodata(char* buffer, uptr size) { … }
void InitializeShadowMemoryPlatform() { … }
#endif
# if !SANITIZER_GO
static void ReExecIfNeeded(bool ignore_heap) { … }
# endif
void InitializePlatformEarly() { … }
void InitializePlatform() { … }
#if !SANITIZER_GO
int ExtractResolvFDs(void *state, int *fds, int nfd) { … }
int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) { … }
static uptr UnmangleLongJmpSp(uptr mangled_sp) { … }
#if SANITIZER_NETBSD
# ifdef __x86_64__
#define LONG_JMP_SP_ENV_SLOT …
# else
# error unsupported
# endif
#elif defined(__powerpc__)
#define LONG_JMP_SP_ENV_SLOT …
#elif SANITIZER_FREEBSD
# ifdef __aarch64__
#define LONG_JMP_SP_ENV_SLOT …
# else
#define LONG_JMP_SP_ENV_SLOT …
# endif
#elif SANITIZER_LINUX
# ifdef __aarch64__
#define LONG_JMP_SP_ENV_SLOT …
# elif defined(__loongarch__)
#define LONG_JMP_SP_ENV_SLOT …
# elif defined(__mips64)
#define LONG_JMP_SP_ENV_SLOT …
# elif SANITIZER_RISCV64
#define LONG_JMP_SP_ENV_SLOT …
# elif defined(__s390x__)
#define LONG_JMP_SP_ENV_SLOT …
# else
#define LONG_JMP_SP_ENV_SLOT …
# endif
#endif
uptr ExtractLongJmpSp(uptr *env) { … }
#if INIT_LONGJMP_XOR_KEY
static void InitializeLongjmpXorKey() {
jmp_buf env;
REAL(_setjmp)(env);
uptr sp;
#ifdef __loongarch__
asm("move %0, $sp" : "=r" (sp));
#else
asm("mov %0, sp" : "=r" (sp));
#endif
uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT];
longjmp_xor_key = mangled_sp ^ sp;
}
#endif
extern "C" void __tsan_tls_initialization() { … }
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { … }
int call_pthread_cancel_with_cleanup(int (*fn)(void *arg),
void (*cleanup)(void *arg), void *arg) { … }
#endif
#if !SANITIZER_GO
void ReplaceSystemMalloc() { … }
#endif
#if !SANITIZER_GO
#if SANITIZER_ANDROID
static ThreadState *dead_thread_state = nullptr;
ThreadState *cur_thread() {
ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
if (thr == nullptr) {
__sanitizer_sigset_t emptyset;
internal_sigfillset(&emptyset);
__sanitizer_sigset_t oldset;
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
if (thr == nullptr) {
thr = reinterpret_cast<ThreadState*>(MmapOrDie(sizeof(ThreadState),
"ThreadState"));
*get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
if (dead_thread_state == nullptr) {
dead_thread_state = reinterpret_cast<ThreadState*>(
MmapOrDie(sizeof(ThreadState), "ThreadState"));
dead_thread_state->fast_state.SetIgnoreBit();
dead_thread_state->ignore_interceptors = 1;
dead_thread_state->is_dead = true;
*const_cast<u32*>(&dead_thread_state->tid) = -1;
CHECK_EQ(0, internal_mprotect(dead_thread_state, sizeof(ThreadState),
PROT_READ));
}
}
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
}
return thr;
}
void set_cur_thread(ThreadState *thr) {
*get_android_tls_ptr() = reinterpret_cast<uptr>(thr);
}
void cur_thread_finalize() {
__sanitizer_sigset_t emptyset;
internal_sigfillset(&emptyset);
__sanitizer_sigset_t oldset;
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &emptyset, &oldset));
ThreadState* thr = reinterpret_cast<ThreadState*>(*get_android_tls_ptr());
if (thr != dead_thread_state) {
*get_android_tls_ptr() = reinterpret_cast<uptr>(dead_thread_state);
UnmapOrDie(thr, sizeof(ThreadState));
}
CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK, &oldset, nullptr));
}
#endif
#endif
}
#endif