#include "sanitizer_platform.h"
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
SANITIZER_SOLARIS
# include "sanitizer_allocator_internal.h"
# include "sanitizer_atomic.h"
# include "sanitizer_common.h"
# include "sanitizer_file.h"
# include "sanitizer_flags.h"
# include "sanitizer_getauxval.h"
# include "sanitizer_glibc_version.h"
# include "sanitizer_linux.h"
# include "sanitizer_placement_new.h"
# include "sanitizer_procmaps.h"
# include "sanitizer_solaris.h"
# if SANITIZER_NETBSD
#define _RTLD_SOURCE …
# endif
# include <dlfcn.h>
# include <link.h>
# include <pthread.h>
# include <signal.h>
# include <sys/mman.h>
# include <sys/resource.h>
# include <syslog.h>
# if SANITIZER_GLIBC
# include <gnu/libc-version.h>
# endif
# if !defined(ElfW)
#define ElfW …
# endif
# if SANITIZER_FREEBSD
# include <pthread_np.h>
# include <sys/auxv.h>
# include <sys/sysctl.h>
#define pthread_getattr_np …
# undef MAP_NORESERVE
#define MAP_NORESERVE …
extern const Elf_Auxinfo *__elf_aux_vector;
extern "C" int __sys_sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
# endif
# if SANITIZER_NETBSD
# include <lwp.h>
# include <sys/sysctl.h>
# include <sys/tls.h>
# endif
# if SANITIZER_SOLARIS
# include <stddef.h>
# include <stdlib.h>
# include <thread.h>
# endif
# if SANITIZER_ANDROID
# include <android/api-level.h>
# if !defined(CPU_COUNT) && !defined(__aarch64__)
# include <dirent.h>
# include <fcntl.h>
struct __sanitizer::linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
# endif
# endif
# if !SANITIZER_ANDROID
# include <elf.h>
# include <unistd.h>
# endif
namespace __sanitizer {
SANITIZER_WEAK_ATTRIBUTE int real_sigaction(int signum, const void *act,
void *oldact);
int internal_sigaction(int signum, const void *act, void *oldact) { … }
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom) { … }
# if !SANITIZER_GO
bool SetEnv(const char *name, const char *value) { … }
# endif
__attribute__((unused)) static int g_use_dlpi_tls_data;
# if SANITIZER_GLIBC && !SANITIZER_GO
static void GetGLibcVersion(int *major, int *minor, int *patch) { … }
static uptr ThreadDescriptorSizeFallback() { … }
# endif
# if SANITIZER_FREEBSD && !SANITIZER_GO
static uptr ThreadDescriptorSizeFallback() {
# if defined(__s390__) || defined(__sparc__)
return FIRST_32_SECOND_64(524, 1552);
# endif
# if defined(__mips__)
return FIRST_32_SECOND_64(1152, 1776);
# endif
# if SANITIZER_LOONGARCH64
return 1856;
# endif
# if defined(__aarch64__)
return 1776;
# endif
# if defined(__powerpc64__)
return 1776;
# endif
return 0;
}
# endif
# if (SANITIZER_FREEBSD || SANITIZER_GLIBC) && !SANITIZER_GO
static uptr thread_descriptor_size;
uptr ThreadDescriptorSize() { … }
# if SANITIZER_GLIBC
__attribute__((unused)) static size_t g_tls_size;
# endif
void InitTlsSize() { … }
# if defined(__mips__) || defined(__powerpc64__) || SANITIZER_RISCV64 || \
SANITIZER_LOONGARCH64
static uptr TlsPreTcbSize() {
# if defined(__mips__)
const uptr kTcbHead = 16;
# elif defined(__powerpc64__)
const uptr kTcbHead = 88;
# elif SANITIZER_RISCV64
const uptr kTcbHead = 16;
# elif SANITIZER_LOONGARCH64
const uptr kTcbHead = 16;
# endif
const uptr kTlsAlign = 16;
const uptr kTlsPreTcbSize =
RoundUpTo(ThreadDescriptorSize() + kTcbHead, kTlsAlign);
return kTlsPreTcbSize;
}
# endif
# else
void InitTlsSize() {}
uptr ThreadDescriptorSize() { return 0; }
# endif
# if (SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_SOLARIS) && \
!SANITIZER_ANDROID && !SANITIZER_GO
namespace {
struct TlsBlock { … };
}
# ifdef __s390__
extern "C" uptr __tls_get_offset(void *arg);
static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
uptr tls_index[2] = {ti_module, ti_offset};
register uptr r2 asm("2") = 0;
register void *r12 asm("12") = tls_index;
asm("basr %%r14, %[__tls_get_offset]"
: "+r"(r2)
: [__tls_get_offset] "r"(__tls_get_offset), "r"(r12)
: "memory", "cc", "0", "1", "3", "4", "5", "14");
return r2;
}
# else
extern "C" void *__tls_get_addr(size_t *);
# endif
static size_t main_tls_modid;
static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
void *data) { … }
__attribute__((unused)) static void GetStaticTlsBoundary(uptr *addr, uptr *size,
uptr *align) { … }
# endif
# if SANITIZER_NETBSD
static struct tls_tcb *ThreadSelfTlsTcb() {
struct tls_tcb *tcb = nullptr;
# ifdef __HAVE___LWP_GETTCB_FAST
tcb = (struct tls_tcb *)__lwp_gettcb_fast();
# elif defined(__HAVE___LWP_GETPRIVATE_FAST)
tcb = (struct tls_tcb *)__lwp_getprivate_fast();
# endif
return tcb;
}
uptr ThreadSelf() { return (uptr)ThreadSelfTlsTcb()->tcb_pthread; }
int GetSizeFromHdr(struct dl_phdr_info *info, size_t size, void *data) {
const Elf_Phdr *hdr = info->dlpi_phdr;
const Elf_Phdr *last_hdr = hdr + info->dlpi_phnum;
for (; hdr != last_hdr; ++hdr) {
if (hdr->p_type == PT_TLS && info->dlpi_tls_modid == 1) {
*(uptr *)data = hdr->p_memsz;
break;
}
}
return 0;
}
# endif
# if SANITIZER_ANDROID
extern "C" SANITIZER_WEAK_ATTRIBUTE void __libc_get_static_tls_bounds(void **,
void **);
# endif
# if !SANITIZER_GO
static void GetTls(uptr *addr, uptr *size) { … }
# endif
# if !SANITIZER_GO
uptr GetTlsSize() { … }
# endif
void GetThreadStackAndTls(bool main, uptr *stk_begin, uptr *stk_end,
uptr *tls_begin, uptr *tls_end) { … }
# if !SANITIZER_FREEBSD
Elf_Phdr;
# endif
struct DlIteratePhdrData { … };
static int AddModuleSegments(const char *module_name, dl_phdr_info *info,
InternalMmapVectorNoCtor<LoadedModule> *modules) { … }
static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { … }
# if SANITIZER_ANDROID && __ANDROID_API__ < 21
extern "C" __attribute__((weak)) int dl_iterate_phdr(
int (*)(struct dl_phdr_info *, size_t, void *), void *);
# endif
static bool requiresProcmaps() { … }
static void procmapsInit(InternalMmapVectorNoCtor<LoadedModule> *modules) { … }
void ListOfModules::init() { … }
void ListOfModules::fallbackInit() { … }
static uptr GetRSSFromGetrusage() { … }
uptr GetRSS() { … }
u32 GetNumberOfCPUs() { … }
# if SANITIZER_LINUX
# if SANITIZER_ANDROID
static atomic_uint8_t android_log_initialized;
void AndroidLogInit() {
openlog(GetProcessName(), 0, LOG_USER);
atomic_store(&android_log_initialized, 1, memory_order_release);
}
static bool ShouldLogAfterPrintf() {
return atomic_load(&android_log_initialized, memory_order_acquire);
}
extern "C" SANITIZER_WEAK_ATTRIBUTE int async_safe_write_log(int pri,
const char *tag,
const char *msg);
extern "C" SANITIZER_WEAK_ATTRIBUTE int __android_log_write(int prio,
const char *tag,
const char *msg);
#define SANITIZER_ANDROID_LOG_INFO …
void WriteOneLineToSyslog(const char *s) {
if (&async_safe_write_log) {
async_safe_write_log(SANITIZER_ANDROID_LOG_INFO, GetProcessName(), s);
} else if (AndroidGetApiLevel() > ANDROID_KITKAT) {
syslog(LOG_INFO, "%s", s);
} else {
CHECK(&__android_log_write);
__android_log_write(SANITIZER_ANDROID_LOG_INFO, nullptr, s);
}
}
extern "C" SANITIZER_WEAK_ATTRIBUTE void android_set_abort_message(
const char *);
void SetAbortMessage(const char *str) {
if (&android_set_abort_message)
android_set_abort_message(str);
}
# else
void AndroidLogInit() { … }
static bool ShouldLogAfterPrintf() { … }
void WriteOneLineToSyslog(const char *s) { … }
void SetAbortMessage(const char *str) { … }
# endif
void LogMessageOnPrintf(const char *str) { … }
# endif
# if SANITIZER_GLIBC && !SANITIZER_GO
extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname;
inline bool CanUseVDSO() { … }
extern "C" SANITIZER_WEAK_ATTRIBUTE int real_clock_gettime(u32 clk_id,
void *tp);
u64 MonotonicNanoTime() { … }
# else
u64 MonotonicNanoTime() {
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (u64)ts.tv_sec * (1000ULL * 1000 * 1000) + ts.tv_nsec;
}
# endif
void ReExec() { … }
void UnmapFromTo(uptr from, uptr to) { … }
uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
uptr min_shadow_base_alignment, UNUSED uptr &high_mem_end,
uptr granularity) { … }
static uptr MmapSharedNoReserve(uptr addr, uptr size) { … }
static uptr MremapCreateAlias(uptr base_addr, uptr alias_addr,
uptr alias_size) { … }
static void CreateAliases(uptr start_addr, uptr alias_size, uptr num_aliases) { … }
uptr MapDynamicShadowAndAliases(uptr shadow_size, uptr alias_size,
uptr num_aliases, uptr ring_buffer_size) { … }
void InitializePlatformCommonFlags(CommonFlags *cf) { … }
}
#endif