[FreeBSD] Port sanitizers' syscalls.

Patch by Viktor Kutuzov!

llvm-svn: 203227
This commit is contained in:
Alexey Samsonov 2014-03-07 10:03:54 +00:00
parent f852f08fb1
commit 78a6d2073f
5 changed files with 141 additions and 67 deletions

View File

@ -13,7 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "sanitizer_platform.h" #include "sanitizer_platform.h"
#if SANITIZER_LINUX #if SANITIZER_FREEBSD || SANITIZER_LINUX
#include "sanitizer_common.h" #include "sanitizer_common.h"
#include "sanitizer_flags.h" #include "sanitizer_flags.h"
@ -26,7 +26,10 @@
#include "sanitizer_stacktrace.h" #include "sanitizer_stacktrace.h"
#include "sanitizer_symbolizer.h" #include "sanitizer_symbolizer.h"
#if !SANITIZER_FREEBSD
#include <asm/param.h> #include <asm/param.h>
#endif
#include <dlfcn.h> #include <dlfcn.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@ -45,6 +48,15 @@
#include <unistd.h> #include <unistd.h>
#include <unwind.h> #include <unwind.h>
#if SANITIZER_FREEBSD
#include <machine/atomic.h>
extern "C" {
// <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on
// FreeBSD 9.2 and 10.0.
#include <sys/umtx.h>
}
#endif // SANITIZER_FREEBSD
#if !SANITIZER_ANDROID #if !SANITIZER_ANDROID
#include <sys/signal.h> #include <sys/signal.h>
#endif #endif
@ -54,6 +66,7 @@
#include <sys/system_properties.h> #include <sys/system_properties.h>
#endif #endif
#if SANITIZER_LINUX
// <linux/time.h> // <linux/time.h>
struct kernel_timeval { struct kernel_timeval {
long tv_sec; long tv_sec;
@ -63,11 +76,12 @@ struct kernel_timeval {
// <linux/futex.h> is broken on some linux distributions. // <linux/futex.h> is broken on some linux distributions.
const int FUTEX_WAIT = 0; const int FUTEX_WAIT = 0;
const int FUTEX_WAKE = 1; const int FUTEX_WAKE = 1;
#endif // SANITIZER_LINUX
// Are we using 32-bit or 64-bit syscalls? // Are we using 32-bit or 64-bit Linux syscalls?
// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
// but it still needs to use 64-bit syscalls. // but it still needs to use 64-bit syscalls.
#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64 #if SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_WORDSIZE == 64)
# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
#else #else
# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
@ -75,7 +89,7 @@ const int FUTEX_WAKE = 1;
namespace __sanitizer { namespace __sanitizer {
#ifdef __x86_64__ #if SANITIZER_LINUX && defined(__x86_64__)
#include "sanitizer_syscall_linux_x86_64.inc" #include "sanitizer_syscall_linux_x86_64.inc"
#else #else
#include "sanitizer_syscall_generic.inc" #include "sanitizer_syscall_generic.inc"
@ -84,35 +98,37 @@ namespace __sanitizer {
// --------------- sanitizer_libc.h // --------------- sanitizer_libc.h
uptr internal_mmap(void *addr, uptr length, int prot, int flags, uptr internal_mmap(void *addr, uptr length, int prot, int flags,
int fd, u64 offset) { int fd, u64 offset) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
return internal_syscall(__NR_mmap, (uptr)addr, length, prot, flags, fd, return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd,
offset); offset);
#else #else
return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); return internal_syscall(SYSCALL(mmap2), addr, length, prot, flags, fd,
offset);
#endif #endif
} }
uptr internal_munmap(void *addr, uptr length) { uptr internal_munmap(void *addr, uptr length) {
return internal_syscall(__NR_munmap, (uptr)addr, length); return internal_syscall(SYSCALL(munmap), (uptr)addr, length);
} }
uptr internal_close(fd_t fd) { uptr internal_close(fd_t fd) {
return internal_syscall(__NR_close, fd); return internal_syscall(SYSCALL(close), fd);
} }
uptr internal_open(const char *filename, int flags) { uptr internal_open(const char *filename, int flags) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(__NR_openat, AT_FDCWD, (uptr)filename, flags); return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags);
#else #else
return internal_syscall(__NR_open, (uptr)filename, flags); return internal_syscall(SYSCALL(open), (uptr)filename, flags);
#endif #endif
} }
uptr internal_open(const char *filename, int flags, u32 mode) { uptr internal_open(const char *filename, int flags, u32 mode) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(__NR_openat, AT_FDCWD, (uptr)filename, flags, mode); return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags,
mode);
#else #else
return internal_syscall(__NR_open, (uptr)filename, flags, mode); return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode);
#endif #endif
} }
@ -123,17 +139,19 @@ uptr OpenFile(const char *filename, bool write) {
uptr internal_read(fd_t fd, void *buf, uptr count) { uptr internal_read(fd_t fd, void *buf, uptr count) {
sptr res; sptr res;
HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, (uptr)buf, count)); HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf,
count));
return res; return res;
} }
uptr internal_write(fd_t fd, const void *buf, uptr count) { uptr internal_write(fd_t fd, const void *buf, uptr count) {
sptr res; sptr res;
HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, (uptr)buf, count)); HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf,
count));
return res; return res;
} }
#if !SANITIZER_LINUX_USES_64BIT_SYSCALLS #if !SANITIZER_LINUX_USES_64BIT_SYSCALLS && !SANITIZER_FREEBSD
static void stat64_to_stat(struct stat64 *in, struct stat *out) { static void stat64_to_stat(struct stat64 *in, struct stat *out) {
internal_memset(out, 0, sizeof(*out)); internal_memset(out, 0, sizeof(*out));
out->st_dev = in->st_dev; out->st_dev = in->st_dev;
@ -154,38 +172,43 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) {
#endif #endif
uptr internal_stat(const char *path, void *buf) { uptr internal_stat(const char *path, void *buf) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_FREEBSD
return internal_syscall(__NR_newfstatat, AT_FDCWD, (uptr)path, (uptr)buf, 0); return internal_syscall(SYSCALL(stat), path, buf);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
(uptr)buf, 0);
#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
return internal_syscall(__NR_stat, (uptr)path, (uptr)buf); return internal_syscall(SYSCALL(stat), (uptr)path, (uptr)buf);
#else #else
struct stat64 buf64; struct stat64 buf64;
int res = internal_syscall(__NR_stat64, path, &buf64); int res = internal_syscall(SYSCALL(stat64), path, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf); stat64_to_stat(&buf64, (struct stat *)buf);
return res; return res;
#endif #endif
} }
uptr internal_lstat(const char *path, void *buf) { uptr internal_lstat(const char *path, void *buf) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_FREEBSD
return internal_syscall(__NR_newfstatat, AT_FDCWD, (uptr)path, return internal_syscall(SYSCALL(lstat), path, buf);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
(uptr)buf, AT_SYMLINK_NOFOLLOW); (uptr)buf, AT_SYMLINK_NOFOLLOW);
#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS
return internal_syscall(__NR_lstat, (uptr)path, (uptr)buf); return internal_syscall(SYSCALL(lstat), (uptr)path, (uptr)buf);
#else #else
struct stat64 buf64; struct stat64 buf64;
int res = internal_syscall(__NR_lstat64, path, &buf64); int res = internal_syscall(SYSCALL(lstat64), path, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf); stat64_to_stat(&buf64, (struct stat *)buf);
return res; return res;
#endif #endif
} }
uptr internal_fstat(fd_t fd, void *buf) { uptr internal_fstat(fd_t fd, void *buf) {
#if SANITIZER_LINUX_USES_64BIT_SYSCALLS #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS
return internal_syscall(__NR_fstat, fd, (uptr)buf); return internal_syscall(SYSCALL(fstat), fd, (uptr)buf);
#else #else
struct stat64 buf64; struct stat64 buf64;
int res = internal_syscall(__NR_fstat64, fd, &buf64); int res = internal_syscall(SYSCALL(fstat64), fd, &buf64);
stat64_to_stat(&buf64, (struct stat *)buf); stat64_to_stat(&buf64, (struct stat *)buf);
return res; return res;
#endif #endif
@ -200,48 +223,53 @@ uptr internal_filesize(fd_t fd) {
uptr internal_dup2(int oldfd, int newfd) { uptr internal_dup2(int oldfd, int newfd) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(__NR_dup3, oldfd, newfd, 0); return internal_syscall(SYSCALL(dup3), oldfd, newfd, 0);
#else #else
return internal_syscall(__NR_dup2, oldfd, newfd); return internal_syscall(SYSCALL(dup2), oldfd, newfd);
#endif #endif
} }
uptr internal_readlink(const char *path, char *buf, uptr bufsize) { uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(__NR_readlinkat, AT_FDCWD, return internal_syscall(SYSCALL(readlinkat), AT_FDCWD,
(uptr)path, (uptr)buf, bufsize); (uptr)path, (uptr)buf, bufsize);
#else #else
return internal_syscall(__NR_readlink, (uptr)path, (uptr)buf, bufsize); return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize);
#endif #endif
} }
uptr internal_unlink(const char *path) { uptr internal_unlink(const char *path) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(__NR_unlinkat, AT_FDCWD, (uptr)path, 0); return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0);
#else #else
return internal_syscall(__NR_unlink, (uptr)path); return internal_syscall(SYSCALL(unlink), (uptr)path);
#endif #endif
} }
uptr internal_sched_yield() { uptr internal_sched_yield() {
return internal_syscall(__NR_sched_yield); return internal_syscall(SYSCALL(sched_yield));
} }
void internal__exit(int exitcode) { void internal__exit(int exitcode) {
internal_syscall(__NR_exit_group, exitcode); #if SANITIZER_FREEBSD
internal_syscall(SYSCALL(exit), exitcode);
#else
internal_syscall(SYSCALL(exit_group), exitcode);
#endif
Die(); // Unreachable. Die(); // Unreachable.
} }
uptr internal_execve(const char *filename, char *const argv[], uptr internal_execve(const char *filename, char *const argv[],
char *const envp[]) { char *const envp[]) {
return internal_syscall(__NR_execve, (uptr)filename, (uptr)argv, (uptr)envp); return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv,
(uptr)envp);
} }
// ----------------- sanitizer_common.h // ----------------- sanitizer_common.h
bool FileExists(const char *filename) { bool FileExists(const char *filename) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
struct stat st; struct stat st;
if (internal_syscall(__NR_newfstatat, AT_FDCWD, filename, &st, 0)) if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
return false; return false;
#else #else
struct stat st; struct stat st;
@ -253,13 +281,21 @@ bool FileExists(const char *filename) {
} }
uptr GetTid() { uptr GetTid() {
return internal_syscall(__NR_gettid); #if SANITIZER_FREEBSD
return (uptr)pthread_self();
#else
return internal_syscall(SYSCALL(gettid));
#endif
} }
u64 NanoTime() { u64 NanoTime() {
#if SANITIZER_FREEBSD
timeval tv;
#else
kernel_timeval tv; kernel_timeval tv;
#endif
internal_memset(&tv, 0, sizeof(tv)); internal_memset(&tv, 0, sizeof(tv));
internal_syscall(__NR_gettimeofday, (uptr)&tv, 0); internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0);
return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
} }
@ -374,16 +410,26 @@ void BlockingMutex::Lock() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
return; return;
while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) {
internal_syscall(__NR_futex, (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); #if SANITIZER_FREEBSD
_umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0);
#else
internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
#endif
}
} }
void BlockingMutex::Unlock() { void BlockingMutex::Unlock() {
atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
CHECK_NE(v, MtxUnlocked); CHECK_NE(v, MtxUnlocked);
if (v == MtxSleeping) if (v == MtxSleeping) {
internal_syscall(__NR_futex, (uptr)m, FUTEX_WAKE, 1, 0, 0, 0); #if SANITIZER_FREEBSD
_umtx_op(m, UMTX_OP_WAKE, 1, 0, 0);
#else
internal_syscall(SYSCALL(futex), (uptr)m, FUTEX_WAKE, 1, 0, 0, 0);
#endif
}
} }
void BlockingMutex::CheckLocked() { void BlockingMutex::CheckLocked() {
@ -404,43 +450,47 @@ struct linux_dirent {
// Syscall wrappers. // Syscall wrappers.
uptr internal_ptrace(int request, int pid, void *addr, void *data) { uptr internal_ptrace(int request, int pid, void *addr, void *data) {
return internal_syscall(__NR_ptrace, request, pid, (uptr)addr, (uptr)data); return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr,
(uptr)data);
} }
uptr internal_waitpid(int pid, int *status, int options) { uptr internal_waitpid(int pid, int *status, int options) {
return internal_syscall(__NR_wait4, pid, (uptr)status, options, return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options,
0 /* rusage */); 0 /* rusage */);
} }
uptr internal_getpid() { uptr internal_getpid() {
return internal_syscall(__NR_getpid); return internal_syscall(SYSCALL(getpid));
} }
uptr internal_getppid() { uptr internal_getppid() {
return internal_syscall(__NR_getppid); return internal_syscall(SYSCALL(getppid));
} }
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(__NR_getdents64, fd, (uptr)dirp, count); return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
#else #else
return internal_syscall(__NR_getdents, fd, (uptr)dirp, count); return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
#endif #endif
} }
uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { uptr internal_lseek(fd_t fd, OFF_T offset, int whence) {
return internal_syscall(__NR_lseek, fd, offset, whence); return internal_syscall(SYSCALL(lseek), fd, offset, whence);
} }
#if SANITIZER_LINUX
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5); return internal_syscall(SYSCALL(prctl), option, arg2, arg3, arg4, arg5);
} }
#endif
uptr internal_sigaltstack(const struct sigaltstack *ss, uptr internal_sigaltstack(const struct sigaltstack *ss,
struct sigaltstack *oss) { struct sigaltstack *oss) {
return internal_syscall(__NR_sigaltstack, (uptr)ss, (uptr)oss); return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss);
} }
#if SANITIZER_LINUX
// Doesn't set sa_restorer, use with caution (see below). // Doesn't set sa_restorer, use with caution (see below).
int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
__sanitizer_kernel_sigaction_t k_act, k_oldact; __sanitizer_kernel_sigaction_t k_act, k_oldact;
@ -465,7 +515,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
k_act.sa_restorer = u_act->sa_restorer; k_act.sa_restorer = u_act->sa_restorer;
} }
uptr result = internal_syscall(__NR_rt_sigaction, (uptr)signum, uptr result = internal_syscall(SYSCALL(rt_sigaction), (uptr)signum,
(uptr)(u_act ? &k_act : NULL), (uptr)(u_act ? &k_act : NULL),
(uptr)(u_oldact ? &k_oldact : NULL), (uptr)(u_oldact ? &k_oldact : NULL),
(uptr)sizeof(__sanitizer_kernel_sigset_t)); (uptr)sizeof(__sanitizer_kernel_sigset_t));
@ -480,19 +530,25 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) {
} }
return result; return result;
} }
#endif // SANITIZER_LINUX
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset) { __sanitizer_sigset_t *oldset) {
#if SANITIZER_FREEBSD
return internal_syscall(SYSCALL(sigprocmask), how, set, oldset);
#else
__sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
__sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset;
return internal_syscall(__NR_rt_sigprocmask, (uptr)how, &k_set->sig[0], return internal_syscall(SYSCALL(rt_sigprocmask), (uptr)how, &k_set->sig[0],
&k_oldset->sig[0], sizeof(__sanitizer_kernel_sigset_t)); &k_oldset->sig[0], sizeof(__sanitizer_kernel_sigset_t));
#endif
} }
void internal_sigfillset(__sanitizer_sigset_t *set) { void internal_sigfillset(__sanitizer_sigset_t *set) {
internal_memset(set, 0xff, sizeof(*set)); internal_memset(set, 0xff, sizeof(*set));
} }
#if SANITIZER_LINUX
void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
signum -= 1; signum -= 1;
CHECK_GE(signum, 0); CHECK_GE(signum, 0);
@ -502,6 +558,7 @@ void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
k_set->sig[idx] &= ~(1 << bit); k_set->sig[idx] &= ~(1 << bit);
} }
#endif // SANITIZER_LINUX
// ThreadLister implementation. // ThreadLister implementation.
ThreadLister::ThreadLister(int pid) ThreadLister::ThreadLister(int pid)
@ -572,7 +629,7 @@ bool ThreadLister::GetDirectoryEntries() {
} }
uptr GetPageSize() { uptr GetPageSize() {
#if defined(__x86_64__) || defined(__i386__) #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__i386__))
return EXEC_PAGESIZE; return EXEC_PAGESIZE;
#else #else
return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. return sysconf(_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy.
@ -627,8 +684,10 @@ bool LibraryNameIs(const char *full_name, const char *base_name) {
#if !SANITIZER_ANDROID #if !SANITIZER_ANDROID
// Call cb for each region mapped by map. // Call cb for each region mapped by map.
void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
#if !SANITIZER_FREEBSD
typedef ElfW(Phdr) Elf_Phdr; typedef ElfW(Phdr) Elf_Phdr;
typedef ElfW(Ehdr) Elf_Ehdr; typedef ElfW(Ehdr) Elf_Ehdr;
#endif // !SANITIZER_FREEBSD
char *base = (char *)map->l_addr; char *base = (char *)map->l_addr;
Elf_Ehdr *ehdr = (Elf_Ehdr *)base; Elf_Ehdr *ehdr = (Elf_Ehdr *)base;
char *phdrs = base + ehdr->e_phoff; char *phdrs = base + ehdr->e_phoff;
@ -662,7 +721,7 @@ void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) {
} }
#endif #endif
#if defined(__x86_64__) #if defined(__x86_64__) && SANITIZER_LINUX
// We cannot use glibc's clone wrapper, because it messes with the child // We cannot use glibc's clone wrapper, because it messes with the child
// task's TLS. It writes the PID and TID of the child task to its thread // task's TLS. It writes the PID and TID of the child task to its thread
// descriptor, but in our case the child task shares the thread descriptor with // descriptor, but in our case the child task shares the thread descriptor with
@ -681,7 +740,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
register void *r8 __asm__("r8") = newtls; register void *r8 __asm__("r8") = newtls;
register int *r10 __asm__("r10") = child_tidptr; register int *r10 __asm__("r10") = child_tidptr;
__asm__ __volatile__( __asm__ __volatile__(
/* %rax = syscall(%rax = __NR_clone, /* %rax = syscall(%rax = SYSCALL(clone),
* %rdi = flags, * %rdi = flags,
* %rsi = child_stack, * %rsi = child_stack,
* %rdx = parent_tidptr, * %rdx = parent_tidptr,
@ -715,7 +774,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
/* Return to parent. */ /* Return to parent. */
"1:\n" "1:\n"
: "=a" (res) : "=a" (res)
: "a"(__NR_clone), "i"(__NR_exit), : "a"(SYSCALL(clone)), "i"(SYSCALL(exit)),
"S"(child_stack), "S"(child_stack),
"D"(flags), "D"(flags),
"d"(parent_tidptr), "d"(parent_tidptr),
@ -724,7 +783,7 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
: "rsp", "memory", "r11", "rcx"); : "rsp", "memory", "r11", "rcx");
return res; return res;
} }
#endif // defined(__x86_64__) #endif // defined(__x86_64__) && SANITIZER_LINUX
#if SANITIZER_ANDROID #if SANITIZER_ANDROID
// This thing is not, strictly speaking, async signal safe, but it does not seem // This thing is not, strictly speaking, async signal safe, but it does not seem
@ -758,4 +817,4 @@ bool IsDeadlySignal(int signum) {
} // namespace __sanitizer } // namespace __sanitizer
#endif // SANITIZER_LINUX #endif // SANITIZER_FREEBSD || SANITIZER_LINUX

View File

@ -29,22 +29,25 @@ struct linux_dirent;
// Syscall wrappers. // Syscall wrappers.
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count);
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
uptr internal_sigaltstack(const struct sigaltstack* ss, uptr internal_sigaltstack(const struct sigaltstack* ss,
struct sigaltstack* oss); struct sigaltstack* oss);
uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset); __sanitizer_sigset_t *oldset);
void internal_sigfillset(__sanitizer_sigset_t *set); void internal_sigfillset(__sanitizer_sigset_t *set);
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
// Linux-only syscalls.
#if SANITIZER_LINUX
uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5);
// Used only by sanitizer_stoptheworld. Signal handlers that are actually used // Used only by sanitizer_stoptheworld. Signal handlers that are actually used
// (like the process-wide error reporting SEGV handler) must use // (like the process-wide error reporting SEGV handler) must use
// internal_sigaction instead. // internal_sigaction instead.
int internal_sigaction_norestorer(int signum, const void *act, void *oldact); int internal_sigaction_norestorer(int signum, const void *act, void *oldact);
void internal_sigdelset(__sanitizer_sigset_t *set, int signum);
#ifdef __x86_64__ #if defined(__x86_64__)
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr); int *parent_tidptr, void *newtls, int *child_tidptr);
#endif #endif
#endif // SANITIZER_LINUX
// This class reads thread IDs from /proc/<pid>/task using only syscalls. // This class reads thread IDs from /proc/<pid>/task using only syscalls.
class ThreadLister { class ThreadLister {

View File

@ -96,7 +96,7 @@
// the upstream linux community for all new ports. Other ports may still // the upstream linux community for all new ports. Other ports may still
// use legacy syscalls. // use legacy syscalls.
#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
# ifdef __aarch64__ # if defined(__aarch64__) && SANITIZER_LINUX
# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1 # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1
# else # else
# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0 # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0

View File

@ -11,7 +11,17 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#if SANITIZER_FREEBSD
# define SYSCALL(name) SYS_ ## name
#else
# define SYSCALL(name) __NR_ ## name
#endif
#if SANITIZER_FREEBSD && defined(__x86_64__)
# define internal_syscall __syscall
# else
# define internal_syscall syscall # define internal_syscall syscall
#endif
bool internal_iserror(uptr retval, int *rverrno) { bool internal_iserror(uptr retval, int *rverrno) {
if (retval == (uptr)-1) { if (retval == (uptr)-1) {

View File

@ -11,6 +11,8 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#define SYSCALL(name) __NR_ ## name
static uptr internal_syscall(u64 nr) { static uptr internal_syscall(u64 nr) {
u64 retval; u64 retval;
asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11", asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11",