Index: lib/sanitizer_common/CMakeLists.txt =================================================================== --- lib/sanitizer_common/CMakeLists.txt +++ lib/sanitizer_common/CMakeLists.txt @@ -16,6 +16,7 @@ sanitizer_linux.cc sanitizer_linux_s390.cc sanitizer_mac.cc + sanitizer_netbsd.cc sanitizer_openbsd.cc sanitizer_persistent_allocator.cc sanitizer_platform_limits_linux.cc Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -31,10 +31,6 @@ #include #endif -#if SANITIZER_NETBSD -#include -#endif - // For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat' // format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To // access stat from asm/stat.h, without conflicting with definition in @@ -174,14 +170,11 @@ #endif // --------------- sanitizer_libc.h -#if !SANITIZER_SOLARIS +#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD #if !SANITIZER_S390 && !SANITIZER_OPENBSD uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, OFF_T offset) { -#if SANITIZER_NETBSD - return internal_syscall64(SYSCALL(mmap), addr, length, prot, flags, fd, - (long)0, offset); -#elif SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS +#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS return internal_syscall(SYSCALL(mmap), (uptr)addr, length, prot, flags, fd, offset); #else @@ -240,12 +233,8 @@ uptr internal_ftruncate(fd_t fd, uptr size) { sptr res; -#if SANITIZER_NETBSD - HANDLE_EINTR(res, internal_syscall64(SYSCALL(ftruncate), fd, 0, (s64)size)); -#else HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, (OFF_T)size)); -#endif return res; } @@ -317,7 +306,7 @@ #endif uptr internal_stat(const char *path, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD return internal_syscall_ptr(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS @@ -342,9 +331,7 @@ } uptr internal_lstat(const char *path, void *buf) { -#if SANITIZER_NETBSD - return internal_syscall_ptr(SYSCALL(lstat), path, buf); -#elif SANITIZER_FREEBSD || SANITIZER_OPENBSD +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS @@ -369,9 +356,9 @@ } uptr internal_fstat(fd_t fd, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \ +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD || \ SANITIZER_LINUX_USES_64BIT_SYSCALLS -#if SANITIZER_MIPS64 && !SANITIZER_NETBSD && !SANITIZER_OPENBSD +#if SANITIZER_MIPS64 && !SANITIZER_OPENBSD // For mips64, fstat syscall fills buffer in the format of kernel_stat struct kernel_stat kbuf; int res = internal_syscall(SYSCALL(fstat), fd, &kbuf); @@ -437,7 +424,7 @@ } void internal__exit(int exitcode) { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD internal_syscall(SYSCALL(exit), exitcode); #else internal_syscall(SYSCALL(exit_group), exitcode); @@ -459,7 +446,7 @@ return internal_syscall_ptr(SYSCALL(execve), (uptr)filename, (uptr)argv, (uptr)envp); } -#endif // !SANITIZER_SOLARIS +#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD // ----------------- sanitizer_common.h bool FileExists(const char *filename) { @@ -474,6 +461,7 @@ return S_ISREG(st.st_mode); } +#if !SANITIZER_NETBSD tid_t GetTid() { #if SANITIZER_FREEBSD long Tid; @@ -481,8 +469,6 @@ return Tid; #elif SANITIZER_OPENBSD return internal_syscall(SYSCALL(getthrid)); -#elif SANITIZER_NETBSD - return _lwp_self(); #elif SANITIZER_SOLARIS return thr_self(); #else @@ -498,18 +484,16 @@ #elif SANITIZER_OPENBSD (void)pid; return internal_syscall(SYSCALL(thrkill), tid, sig, nullptr); -#elif SANITIZER_NETBSD - (void)pid; - return _lwp_kill(tid, sig); #elif SANITIZER_SOLARIS (void)pid; return thr_kill(tid, sig); #endif } +#endif -#if !SANITIZER_SOLARIS +#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD u64 NanoTime() { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD timeval tv; #else kernel_timeval tv; @@ -522,13 +506,13 @@ uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { return internal_syscall_ptr(SYSCALL(clock_gettime), clk_id, tp); } -#endif // !SANITIZER_SOLARIS +#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD // Like getenv, but reads env directly from /proc (on Linux) or parses the // 'environ' array (on some others) and does not use libc. This function // should be called first inside __asan_init. const char *GetEnv(const char *name) { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \ +#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD || \ SANITIZER_SOLARIS if (::environ != 0) { uptr NameLen = internal_strlen(name); @@ -721,7 +705,9 @@ // The actual size of this structure is specified by d_reclen. // Note that getdents64 uses a different structure format. We only provide the // 32-bit syscall here. -#if SANITIZER_NETBSD || SANITIZER_OPENBSD +#if SANITIZER_NETBSD +// Not used +#elif SANITIZER_OPENBSD // struct dirent is different for Linux and us. At this moment, we use only // d_fileno (Linux call this d_ino), d_reclen, and d_name. struct linux_dirent { @@ -748,23 +734,11 @@ }; #endif -#if !SANITIZER_SOLARIS +#if !SANITIZER_SOLARIS && !SANITIZER_NETBSD // Syscall wrappers. uptr internal_ptrace(int request, int pid, void *addr, void *data) { -#if SANITIZER_NETBSD - // XXX We need additional work for ptrace: - // - for request, we use PT_FOO whereas Linux uses PTRACE_FOO - // - data is int for us, but void * for Linux - // - Linux sometimes uses data in the case where we use addr instead - // At this moment, this function is used only within - // "#if SANITIZER_LINUX && defined(__x86_64__)" block in - // sanitizer_stoptheworld_linux_libcdep.cc. - return internal_syscall_ptr(SYSCALL(ptrace), request, pid, (uptr)addr, - (uptr)data); -#else return internal_syscall(SYSCALL(ptrace), request, pid, (uptr)addr, (uptr)data); -#endif } uptr internal_waitpid(int pid, int *status, int options) { @@ -791,11 +765,7 @@ } uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { -#if SANITIZER_NETBSD - return internal_syscall64(SYSCALL(lseek), fd, 0, offset, whence); -#else return internal_syscall(SYSCALL(lseek), fd, offset, whence); -#endif } #if SANITIZER_LINUX @@ -816,7 +786,7 @@ #endif } -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD int internal_sysctl(const int *name, unsigned int namelen, void *oldp, uptr *oldlenp, const void *newp, uptr newlen) { #if SANITIZER_OPENBSD @@ -897,7 +867,7 @@ uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) { -#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_OPENBSD +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD return internal_syscall_ptr(SYSCALL(sigprocmask), how, set, oldset); #else __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; @@ -937,8 +907,9 @@ return k_set->sig[idx] & (1 << bit); } #endif // SANITIZER_LINUX -#endif // !SANITIZER_SOLARIS +#endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD +#if !SANITIZER_NETBSD // ThreadLister implementation. ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) { char task_directory_path[80]; @@ -1025,6 +996,7 @@ if (!internal_iserror(descriptor_)) internal_close(descriptor_); } +#endif #if SANITIZER_WORDSIZE == 32 // Take care of unusable kernel area in top gigabyte. Index: lib/sanitizer_common/sanitizer_netbsd.cc =================================================================== --- /dev/null +++ lib/sanitizer_common/sanitizer_netbsd.cc @@ -0,0 +1,397 @@ +//===-- sanitizer_netbsd.cc -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "sanitizer_platform.h" + +#if SANITIZER_NETBSD + +#include "sanitizer_common.h" +#include "sanitizer_flags.h" +#include "sanitizer_getauxval.h" +#include "sanitizer_internal_defs.h" +#include "sanitizer_libc.h" +#include "sanitizer_linux.h" +#include "sanitizer_mutex.h" +#include "sanitizer_placement_new.h" +#include "sanitizer_procmaps.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" void *__mmap(void *, size_t, int, int, int, int, + off_t) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int __sysctl(const int *, unsigned int, void *, size_t *, + const void *, size_t) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys_close(int) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys_open(const char *, int, ...) SANITIZER_WEAK_ATTRIBUTE; +extern "C" ssize_t _sys_read(int, void *, size_t) SANITIZER_WEAK_ATTRIBUTE; +extern "C" ssize_t _sys_write(int, const void *, + size_t) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int __ftruncate(int, int, off_t) SANITIZER_WEAK_ATTRIBUTE; +extern "C" ssize_t _sys_readlink(const char *, char *, + size_t) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys_sched_yield() SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys___nanosleep50(const void *, + void *) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys_execve(const char *, char *const[], + char *const[]) SANITIZER_WEAK_ATTRIBUTE; +extern "C" off_t __lseek(int, int, off_t, int) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int __fork() SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys___sigprocmask14(int, const void *, + void *) SANITIZER_WEAK_ATTRIBUTE; +extern "C" int _sys___wait450(int wpid, int *, int, + void *) SANITIZER_WEAK_ATTRIBUTE; + +namespace __sanitizer { + +static void *GetRealLibcAddress(const char *symbol) { + void *real = dlsym(RTLD_NEXT, symbol); + if (!real) + real = dlsym(RTLD_DEFAULT, symbol); + if (!real) { + Printf("GetRealLibcAddress failed for symbol=%s", symbol); + Die(); + } + return real; +} + +// --------------- sanitizer_libc.h +uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, + OFF_T offset) { + CHECK(&__mmap); + return (uptr)__mmap(addr, length, prot, flags, fd, 0, offset); +} + +uptr internal_munmap(void *addr, uptr length) { + static int (*real_munmap)(void *a, uptr b) = NULL; + if (!real_munmap) { + real_munmap = (int (*)(void *a, uptr b))GetRealLibcAddress("munmap"); + } + CHECK(real_munmap); + return (*real_munmap)(addr, length); +} + +int internal_mprotect(void *addr, uptr length, int prot) { + static int (*real_mprotect)(void *a, uptr b, int c) = NULL; + if (!real_mprotect) { + real_mprotect = + (int (*)(void *a, uptr b, int c))GetRealLibcAddress("mprotect"); + } + CHECK(real_mprotect); + return (*real_mprotect)(addr, length, prot); +} + +uptr internal_close(fd_t fd) { + CHECK(&_sys_close); + return _sys_close(fd); +} + +uptr internal_open(const char *filename, int flags) { + CHECK(&_sys_open); + return _sys_open(filename, flags); +} + +uptr internal_open(const char *filename, int flags, u32 mode) { + CHECK(&_sys_open); + return _sys_open(filename, flags, mode); +} + +uptr internal_read(fd_t fd, void *buf, uptr count) { + sptr res; + CHECK(&_sys_read); + HANDLE_EINTR(res, (sptr)_sys_read(fd, buf, (size_t)count)); + return res; +} + +uptr internal_write(fd_t fd, const void *buf, uptr count) { + sptr res; + CHECK(&_sys_write); + HANDLE_EINTR(res, (sptr)_sys_write(fd, buf, count)); + return res; +} + +uptr internal_ftruncate(fd_t fd, uptr size) { + sptr res; + CHECK(&__ftruncate); + HANDLE_EINTR(res, __ftruncate(fd, 0, (s64)size)); + return res; +} + +uptr internal_stat(const char *path, void *buf) { + static int (*real_stat)(const char *a, void *b) = NULL; + if (!real_stat) { + real_stat = (int (*)(const char *a, void *b))GetRealLibcAddress("__stat50"); + } + CHECK(real_stat); + return (*real_stat)(path, buf); +} + +uptr internal_lstat(const char *path, void *buf) { + static int (*real_lstat)(const char *a, void *b) = NULL; + if (!real_lstat) { + real_lstat = + (int (*)(const char *a, void *b))GetRealLibcAddress("__lstat50"); + } + CHECK(real_lstat); + return (*real_lstat)(path, buf); +} + +uptr internal_fstat(fd_t fd, void *buf) { + static int (*real_fstat)(int a, void *b) = NULL; + if (!real_fstat) { + real_fstat = (int (*)(int a, void *b))GetRealLibcAddress("__fstat50"); + } + CHECK(real_fstat); + return (*real_fstat)(fd, buf); +} + +uptr internal_filesize(fd_t fd) { + struct stat st; + if (internal_fstat(fd, &st)) + return -1; + return (uptr)st.st_size; +} + +uptr internal_dup2(int oldfd, int newfd) { + static int (*real_dup2)(int a, int b) = NULL; + if (!real_dup2) { + real_dup2 = (int (*)(int a, int b))GetRealLibcAddress("dup2"); + } + CHECK(real_dup2); + return (*real_dup2)(oldfd, newfd); +} + +uptr internal_readlink(const char *path, char *buf, uptr bufsize) { + CHECK(&_sys_readlink); + return (uptr)_sys_readlink(path, buf, bufsize); +} + +uptr internal_unlink(const char *path) { + static int (*real_unlink)(const char *a) = NULL; + if (!real_unlink) { + real_unlink = (int (*)(const char *a))GetRealLibcAddress("unlink"); + } + CHECK(real_unlink); + return (*real_unlink)(path); +} + +uptr internal_rename(const char *oldpath, const char *newpath) { + static int (*real_rename)(const char *a, const char *b) = NULL; + if (!real_rename) { + real_rename = + (int (*)(const char *a, const char *b))GetRealLibcAddress("rename"); + } + CHECK(real_rename); + return (*real_rename)(oldpath, newpath); +} + +uptr internal_sched_yield() { + CHECK(&_sys_sched_yield); + return _sys_sched_yield(); +} + +void internal__exit(int exitcode) { + static void (*real__exit)(int a) = NULL; + if (!real__exit) { + real__exit = (void (*)(int a))GetRealLibcAddress("_exit"); + } + CHECK(real__exit); + (*real__exit)(exitcode); + Die(); // Unreachable. +} + +unsigned int internal_sleep(unsigned int seconds) { + struct timespec ts; + ts.tv_sec = 1; + ts.tv_nsec = 0; + CHECK(&_sys___nanosleep50); + int res = _sys___nanosleep50(&ts, &ts); + if (res) return ts.tv_sec; + return 0; +} + +uptr internal_execve(const char *filename, char *const argv[], + char *const envp[]) { + CHECK(&_sys_execve); + return _sys_execve(filename, argv, envp); +} + +tid_t GetTid() { + static int (*real__lwp_self)() = NULL; + if (!real__lwp_self) { + real__lwp_self = (int (*)())GetRealLibcAddress("_lwp_self"); + } + CHECK(real__lwp_self); + return (*real__lwp_self)(); +} + +int TgKill(pid_t pid, tid_t tid, int sig) { + static int (*real__lwp_kill)(int a, int b) = NULL; + if (!real__lwp_kill) { + real__lwp_kill = (int (*)(int a, int b))GetRealLibcAddress("_lwp_kill"); + } + CHECK(real__lwp_kill); + (void)pid; + return (*real__lwp_kill)(tid, sig); +} + +u64 NanoTime() { + timeval tv; + internal_memset(&tv, 0, sizeof(tv)); + + static int (*real_gettimeofday)(void *a, void *b) = NULL; + if (!real_gettimeofday) { + real_gettimeofday = + (int (*)(void *a, void *b))GetRealLibcAddress("__gettimeofday50"); + } + CHECK(real_gettimeofday); + (*real_gettimeofday)(&tv, 0); + + return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; +} + +uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { + static int (*real_clock_gettime)(__sanitizer_clockid_t a, void *b) = NULL; + if (!real_clock_gettime) { + real_clock_gettime = + (int (*)(__sanitizer_clockid_t a, void *b))GetRealLibcAddress( + "__clock_gettime50"); + } + CHECK(real_clock_gettime); + return (*real_clock_gettime)(clk_id, tp); +} + +uptr internal_ptrace(int request, int pid, void *addr, void *data) { + Printf("internal_ptrace not implemented for NetBSD"); + Die(); + return 0; +} + +uptr internal_waitpid(int pid, int *status, int options) { + CHECK(&_sys___wait450); + return _sys___wait450(pid, status, options, 0 /* rusage */); +} + +uptr internal_getpid() { + static int (*real_getpid)() = NULL; + if (!real_getpid) { + real_getpid = (int (*)())GetRealLibcAddress("getpid"); + } + CHECK(real_getpid); + return (*real_getpid)(); +} + +uptr internal_getppid() { + static int (*real_getppid)() = NULL; + if (!real_getppid) { + real_getppid = (int (*)())GetRealLibcAddress("getppid"); + } + CHECK(real_getppid); + return (*real_getppid)(); +} + +uptr internal_getdents(fd_t fd, void *dirp, unsigned int count) { + static int (*real_getdents)(int a, void *b, size_t c) = NULL; + if (!real_getdents) { + real_getdents = + (int (*)(int a, void *b, size_t c))GetRealLibcAddress("__getdents30"); + } + CHECK(real_getdents); + return (*real_getdents)(fd, dirp, count); +} + +uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { + CHECK(&__lseek); + return __lseek(fd, 0, offset, whence); +} + +uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { + Printf("internal_prctl not implemented for NetBSD"); + Die(); + return 0; +} + +uptr internal_sigaltstack(const void *ss, void *oss) { + static int (*real_sigaltstack)(const void *a, void *b) = NULL; + if (!real_sigaltstack) { + real_sigaltstack = + (int (*)(const void *a, void *b))GetRealLibcAddress("__sigaltstack14"); + } + CHECK(real_sigaltstack); + return (*real_sigaltstack)(ss, oss); +} + +int internal_fork() { + CHECK(&__fork); + return __fork(); +} + +int internal_sysctl(const int *name, unsigned int namelen, void *oldp, + uptr *oldlenp, const void *newp, uptr newlen) { + CHECK(&__sysctl); + return __sysctl(name, namelen, oldp, (size_t *)oldlenp, newp, (size_t)newlen); +} + +uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, + __sanitizer_sigset_t *oldset) { + CHECK(&_sys___sigprocmask14); + return _sys___sigprocmask14(how, set, oldset); +} + +void internal_sigfillset(__sanitizer_sigset_t *set) { + static int (*real_sigfillset)(const void *a) = NULL; + if (!real_sigfillset) { + real_sigfillset = + (int (*)(const void *a))GetRealLibcAddress("__sigfillset14"); + } + CHECK(real_sigfillset); + (void)(*real_sigfillset)(set); +} + +void internal_sigemptyset(__sanitizer_sigset_t *set) { + static int (*real_sigemptyset)(const void *a) = NULL; + if (!real_sigemptyset) { + real_sigemptyset = + (int (*)(const void *a))GetRealLibcAddress("__sigemptyset14"); + } + CHECK(real_sigemptyset); + (void)(*real_sigemptyset)(set); +} + +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + int *parent_tidptr, void *newtls, int *child_tidptr) { + Printf("internal_clone not implemented for NetBSD"); + Die(); + return 0; +} + +} // namespace __sanitizer + +#endif Index: lib/tsan/go/buildgo.sh =================================================================== --- lib/tsan/go/buildgo.sh +++ lib/tsan/go/buildgo.sh @@ -94,6 +94,7 @@ ../../sanitizer_common/sanitizer_procmaps_common.cc ../../sanitizer_common/sanitizer_linux.cc ../../sanitizer_common/sanitizer_linux_libcdep.cc + ../../sanitizer_common/sanitizer_netbsd.cc ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc " elif [ "`uname -a | grep Darwin`" != "" ]; then