Index: lib/asan/asan_interceptors.cc =================================================================== --- lib/asan/asan_interceptors.cc +++ lib/asan/asan_interceptors.cc @@ -118,9 +118,15 @@ // But asan does not remember UserId's for threads (pthread_t); // and remembers all ever existed threads, so the linear search by UserId // can be slow. +#if !SANITIZER_NETBSD #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ do { \ } while (false) +#else +#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name, arg) \ + do { \ + } while (false) +#endif #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) // Strict init-order checking is dlopen-hostile: // https://github.com/google/sanitizers/issues/178 Index: lib/msan/msan_interceptors.cc =================================================================== --- lib/msan/msan_interceptors.cc +++ lib/msan/msan_interceptors.cc @@ -118,7 +118,7 @@ #define CHECK_UNPOISONED_STRING(x, n) \ CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n)) -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) { ENSURE_MSAN_INITED(); @@ -168,7 +168,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) { GET_MALLOC_STACK_TRACE; return msan_memalign(alignment, size, &stack); @@ -196,7 +196,7 @@ return msan_valloc(size, &stack); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(void *, pvalloc, SIZE_T size) { GET_MALLOC_STACK_TRACE; return msan_pvalloc(size, &stack); @@ -212,7 +212,7 @@ MsanDeallocate(&stack, ptr); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(void, cfree, void *ptr) { GET_MALLOC_STACK_TRACE; if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; @@ -227,7 +227,7 @@ return __sanitizer_get_allocated_size(ptr); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD // This function actually returns a struct by value, but we can't unpoison a // temporary! The following is equivalent on all supported platforms but // aarch64 (which uses a different register for sret value). We have a test @@ -246,7 +246,7 @@ #define MSAN_MAYBE_INTERCEPT_MALLINFO #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, mallopt, int cmd, int value) { return -1; } @@ -255,7 +255,7 @@ #define MSAN_MAYBE_INTERCEPT_MALLOPT #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(void, malloc_stats, void) { // FIXME: implement, but don't call REAL(malloc_stats)! } @@ -308,7 +308,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(char *, __strdup, char *src) { ENSURE_MSAN_INITED(); GET_STORE_STACK_TRACE; @@ -473,7 +473,7 @@ INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format, __sanitizer_tm *tm, void *loc) { INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm, @@ -495,7 +495,7 @@ loc); } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format, __sanitizer_tm *tm, void *loc) { INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm, @@ -614,7 +614,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) { ENSURE_MSAN_INITED(); int res = REAL(__fxstat)(magic, fd, buf); @@ -627,7 +627,7 @@ #define MSAN_MAYBE_INTERCEPT___FXSTAT #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) { ENSURE_MSAN_INITED(); int res = REAL(__fxstat64)(magic, fd, buf); @@ -640,7 +640,7 @@ #define MSAN_MAYBE_INTERCEPT___FXSTAT64 #endif -#if SANITIZER_FREEBSD +#if SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) { ENSURE_MSAN_INITED(); int res = REAL(fstatat)(fd, pathname, buf, flags); @@ -659,7 +659,7 @@ # define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat) #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf, int flags) { ENSURE_MSAN_INITED(); @@ -706,7 +706,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) { ENSURE_MSAN_INITED(); char *res = REAL(fgets_unlocked)(s, size, stream); @@ -729,7 +729,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, getrlimit64, int resource, void *rlim) { if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim); ENSURE_MSAN_INITED(); @@ -805,7 +805,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents, int timeout) { ENSURE_MSAN_INITED(); @@ -820,7 +820,7 @@ #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT #endif -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents, int timeout, void *sigmask) { ENSURE_MSAN_INITED(); @@ -909,7 +909,7 @@ return res; } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags, int fd, OFF64_T offset) { ENSURE_MSAN_INITED(); @@ -1255,9 +1255,15 @@ #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ do { \ } while (false) // FIXME +#if !SANITIZER_NETBSD #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ do { \ } while (false) // FIXME +#else +#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name, arg) \ + do { \ + } while (false) // FIXME +#endif #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \ Index: lib/msan/msan_linux.cc =================================================================== --- lib/msan/msan_linux.cc +++ lib/msan/msan_linux.cc @@ -9,11 +9,11 @@ // // This file is a part of MemorySanitizer. // -// Linux- and FreeBSD-specific code. +// Linux-, NetBSD- and FreeBSD-specific code. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_FREEBSD || SANITIZER_LINUX +#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD #include "msan.h" #include "msan_thread.h" @@ -213,4 +213,4 @@ } // namespace __msan -#endif // SANITIZER_FREEBSD || SANITIZER_LINUX +#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD Index: lib/sanitizer_common/sanitizer_common_interceptors.inc =================================================================== --- lib/sanitizer_common/sanitizer_common_interceptors.inc +++ lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -4405,7 +4405,7 @@ #define INIT_TEMPNAM #endif -#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP +#if SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && !SANITIZER_NETBSD INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name); @@ -4414,6 +4414,15 @@ return REAL(pthread_setname_np)(thread, name); } #define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np); +#elif SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP && SANITIZER_NETBSD +INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name, void *arg) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg); + COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0); + COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name, arg); + return REAL(pthread_setname_np)(thread, name, arg); +} +#define INIT_PTHREAD_SETNAME_NP COMMON_INTERCEPT_FUNCTION(pthread_setname_np); #else #define INIT_PTHREAD_SETNAME_NP #endif Index: lib/sanitizer_common/sanitizer_internal_defs.h =================================================================== --- lib/sanitizer_common/sanitizer_internal_defs.h +++ lib/sanitizer_common/sanitizer_internal_defs.h @@ -36,7 +36,7 @@ #endif // TLS is handled differently on different platforms -#if SANITIZER_LINUX +#if SANITIZER_LINUX || SANITIZER_NETBSD # define SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE \ __attribute__((tls_model("initial-exec"))) thread_local #else Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -87,7 +87,9 @@ #include // For NAME_MAX #include extern char **environ; // provided by crt1 -#endif // SANITIZER_NETBSD +#include +extern struct ps_strings *__ps_strings; +#endif // SANITIZER_NETBSD #if !SANITIZER_ANDROID #include @@ -174,11 +176,11 @@ #endif // !SANITIZER_S390 uptr internal_munmap(void *addr, uptr length) { - return internal_syscall(SYSCALL(munmap), (uptr)addr, length); + return internal_syscall_ptr(SYSCALL(munmap), (uptr)addr, length); } int internal_mprotect(void *addr, uptr length, int prot) { - return internal_syscall(SYSCALL(mprotect), (uptr)addr, length, prot); + return internal_syscall_ptr(SYSCALL(mprotect), (uptr)addr, length, prot); } uptr internal_close(fd_t fd) { @@ -189,7 +191,7 @@ #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags); #else - return internal_syscall(SYSCALL(open), (uptr)filename, flags); + return internal_syscall_ptr(SYSCALL(open), (uptr)filename, flags); #endif } @@ -198,36 +200,28 @@ return internal_syscall(SYSCALL(openat), AT_FDCWD, (uptr)filename, flags, mode); #else - return internal_syscall(SYSCALL(open), (uptr)filename, flags, mode); + return internal_syscall_ptr(SYSCALL(open), (uptr)filename, flags, mode); #endif } uptr internal_read(fd_t fd, void *buf, uptr count) { sptr res; -#if SANITIZER_NETBSD - HANDLE_EINTR(res, internal_syscall_ptr(SYSCALL(read), fd, buf, count)); -#else - HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, + HANDLE_EINTR(res, (sptr)internal_syscall_ptr(SYSCALL(read), fd, (uptr)buf, count)); -#endif return res; } uptr internal_write(fd_t fd, const void *buf, uptr count) { sptr res; -#if SANITIZER_NETBSD - HANDLE_EINTR(res, internal_syscall_ptr(SYSCALL(write), fd, buf, count)); -#else - HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, + HANDLE_EINTR(res, (sptr)internal_syscall_ptr(SYSCALL(write), fd, (uptr)buf, count)); -#endif return res; } uptr internal_ftruncate(fd_t fd, uptr size) { sptr res; #if SANITIZER_NETBSD - HANDLE_EINTR(res, internal_syscall(SYSCALL(ftruncate), fd, 0, (s64)size)); + HANDLE_EINTR(res, internal_syscall64(SYSCALL(ftruncate), fd, 0, (s64)size)); #else HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, (OFF_T)size)); @@ -304,7 +298,7 @@ uptr internal_stat(const char *path, void *buf) { #if SANITIZER_FREEBSD || SANITIZER_NETBSD - return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, + return internal_syscall_ptr(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, @@ -329,7 +323,7 @@ uptr internal_lstat(const char *path, void *buf) { #if SANITIZER_NETBSD - return internal_syscall(SYSCALL(lstat), path, buf); + return internal_syscall_ptr(SYSCALL(lstat), path, buf); #elif SANITIZER_FREEBSD return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); @@ -355,15 +349,15 @@ } uptr internal_fstat(fd_t fd, void *buf) { -#if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS || SANITIZER_NETBSD -# if SANITIZER_MIPS64 +#if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS +# if SANITIZER_MIPS64 && !SANITIZER_NETBSD // For mips64, fstat syscall fills buffer in the format of kernel_stat struct kernel_stat kbuf; int res = internal_syscall(SYSCALL(fstat), fd, &kbuf); kernel_stat_to_stat(&kbuf, (struct stat *)buf); return res; # else - return internal_syscall(SYSCALL(fstat), fd, (uptr)buf); + return internal_syscall_ptr(SYSCALL(fstat), fd, (uptr)buf); # endif #else struct stat64 buf64; @@ -389,13 +383,11 @@ } uptr internal_readlink(const char *path, char *buf, uptr bufsize) { -#if SANITIZER_NETBSD - return internal_syscall_ptr(SYSCALL(readlink), path, buf, bufsize); -#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(readlinkat), AT_FDCWD, (uptr)path, (uptr)buf, bufsize); #else - return internal_syscall(SYSCALL(readlink), (uptr)path, (uptr)buf, bufsize); + return internal_syscall_ptr(SYSCALL(readlink), path, buf, bufsize); #endif } @@ -403,7 +395,7 @@ #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(unlinkat), AT_FDCWD, (uptr)path, 0); #else - return internal_syscall(SYSCALL(unlink), (uptr)path); + return internal_syscall_ptr(SYSCALL(unlink), (uptr)path); #endif } @@ -412,7 +404,7 @@ return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD, (uptr)newpath); #else - return internal_syscall(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); + return internal_syscall_ptr(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); #endif } @@ -433,14 +425,14 @@ struct timespec ts; ts.tv_sec = 1; ts.tv_nsec = 0; - int res = internal_syscall(SYSCALL(nanosleep), &ts, &ts); + int res = internal_syscall_ptr(SYSCALL(nanosleep), &ts, &ts); if (res) return ts.tv_sec; return 0; } uptr internal_execve(const char *filename, char *const argv[], char *const envp[]) { - return internal_syscall(SYSCALL(execve), (uptr)filename, (uptr)argv, + return internal_syscall_ptr(SYSCALL(execve), (uptr)filename, (uptr)argv, (uptr)envp); } @@ -474,11 +466,7 @@ kernel_timeval tv; #endif internal_memset(&tv, 0, sizeof(tv)); -#if SANITIZER_NETBSD - internal_syscall_ptr(SYSCALL(gettimeofday), &tv, NULL); -#else - internal_syscall(SYSCALL(gettimeofday), (uptr)&tv, 0); -#endif + internal_syscall_ptr(SYSCALL(gettimeofday), &tv, 0); return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; } @@ -524,13 +512,13 @@ #endif } -#if !SANITIZER_FREEBSD +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD extern "C" { SANITIZER_WEAK_ATTRIBUTE extern void *__libc_stack_end; } #endif -#if !SANITIZER_GO && !SANITIZER_FREEBSD +#if !SANITIZER_GO && !SANITIZER_FREEBSD && !SANITIZER_NETBSD static void ReadNullSepFileToArray(const char *path, char ***arr, int arr_size) { char *buff; @@ -556,7 +544,22 @@ #endif static void GetArgsAndEnv(char ***argv, char ***envp) { -#if !SANITIZER_FREEBSD +#if SANITIZER_FREEBSD + // On FreeBSD, retrieving the argument and environment arrays is done via the + // kern.ps_strings sysctl, which returns a pointer to a structure containing + // this information. See also . + ps_strings *pss; + size_t sz = sizeof(pss); + if (sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) { + Printf("sysctl kern.ps_strings failed\n"); + Die(); + } + *argv = pss->ps_argvstr; + *envp = pss->ps_envstr; +#elif SANITIZER_NETBSD + *argv = __ps_strings->ps_argvstr; + *argv = __ps_strings->ps_envstr; +#else #if !SANITIZER_GO if (&__libc_stack_end) { #endif @@ -571,18 +574,6 @@ ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); } #endif -#else - // On FreeBSD, retrieving the argument and environment arrays is done via the - // kern.ps_strings sysctl, which returns a pointer to a structure containing - // this information. See also . - ps_strings *pss; - size_t sz = sizeof(pss); - if (sysctlbyname("kern.ps_strings", &pss, &sz, NULL, 0) == -1) { - Printf("sysctl kern.ps_strings failed\n"); - Die(); - } - *argv = pss->ps_argvstr; - *envp = pss->ps_envstr; #endif } @@ -594,8 +585,22 @@ void ReExec() { char **argv, **envp; + const char *pathname = "/proc/self/exe"; + +#if SANITIZER_NETBSD + static const int name[] = { + CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME, + }; + char path[400]; + size_t len; + + len = sizeof(path); + if (sysctl(name, ARRAY_SIZE(name), path, &len, NULL, 0) != -1) + pathname = path; +#endif + GetArgsAndEnv(&argv, &envp); - uptr rv = internal_execve("/proc/self/exe", argv, envp); + uptr rv = internal_execve(pathname, argv, envp); int rverrno; CHECK_EQ(internal_iserror(rv, &rverrno), true); Printf("execve failed, errno %d\n", rverrno); @@ -698,13 +703,8 @@ } uptr internal_waitpid(int pid, int *status, int options) { -#if SANITIZER_NETBSD - return internal_syscall(SYSCALL(wait4), pid, status, options, - NULL /* rusage */); -#else - return internal_syscall(SYSCALL(wait4), pid, (uptr)status, options, + return internal_syscall_ptr(SYSCALL(wait4), pid, (uptr)status, options, 0 /* rusage */); -#endif } uptr internal_getpid() { @@ -716,14 +716,12 @@ } uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { -#if SANITIZER_NETBSD - return internal_syscall(SYSCALL(getdents), fd, dirp, (uptr)count); -#elif SANITIZER_FREEBSD +#if SANITIZER_FREEBSD return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL); #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count); #else - return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count); + return internal_syscall_ptr(SYSCALL(getdents), fd, (uptr)dirp, count); #endif } @@ -742,7 +740,7 @@ #endif uptr internal_sigaltstack(const void *ss, void *oss) { - return internal_syscall(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss); + return internal_syscall_ptr(SYSCALL(sigaltstack), (uptr)ss, (uptr)oss); } int internal_fork() { @@ -824,7 +822,7 @@ uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, __sanitizer_sigset_t *oldset) { #if SANITIZER_FREEBSD || SANITIZER_NETBSD - return internal_syscall(SYSCALL(sigprocmask), how, set, oldset); + return internal_syscall_ptr(SYSCALL(sigprocmask), how, set, oldset); #else __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; Index: lib/sanitizer_common/sanitizer_platform_limits_netbsd.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -313,7 +313,7 @@ uptr we_nbytes; }; -typedef void __sanitizer_FILE; +typedef char __sanitizer_FILE; #define SANITIZER_HAS_STRUCT_FILE 0 extern int shmctl_ipc_stat; Index: lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -128,6 +128,8 @@ return 0; } +unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); + int glob_nomatch = GLOB_NOMATCH; int glob_altdirfunc = GLOB_ALTDIRFUNC; Index: lib/sanitizer_common/sanitizer_syscall_generic.inc =================================================================== --- lib/sanitizer_common/sanitizer_syscall_generic.inc +++ lib/sanitizer_common/sanitizer_syscall_generic.inc @@ -43,8 +43,12 @@ # endif #elif defined(__x86_64__) && (SANITIZER_FREEBSD || SANITIZER_MAC) # define internal_syscall __syscall +# define internal_syscall64 __syscall +# define internal_syscall_ptr __syscall # else # define internal_syscall syscall +# define internal_syscall64 syscall +# define internal_syscall_ptr syscall #endif bool internal_iserror(uptr retval, int *rverrno) { Index: lib/tsan/go/buildgo.sh =================================================================== --- lib/tsan/go/buildgo.sh +++ lib/tsan/go/buildgo.sh @@ -68,6 +68,21 @@ ../../sanitizer_common/sanitizer_linux_libcdep.cc ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc " +elif [ "`uname -a | grep NetBSD`" != "" ]; then + SUFFIX="netbsd_amd64" + OSCFLAGS="-fno-strict-aliasing -fPIC -Werror" + OSLDFLAGS="-lpthread -fPIC -fpie" + SRCS=" + $SRCS + ../rtl/tsan_platform_linux.cc + ../../sanitizer_common/sanitizer_posix.cc + ../../sanitizer_common/sanitizer_posix_libcdep.cc + ../../sanitizer_common/sanitizer_procmaps_common.cc + ../../sanitizer_common/sanitizer_procmaps_freebsd.cc + ../../sanitizer_common/sanitizer_linux.cc + ../../sanitizer_common/sanitizer_linux_libcdep.cc + ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc + " elif [ "`uname -a | grep Darwin`" != "" ]; then SUFFIX="darwin_amd64" OSCFLAGS="-fPIC -Wno-unused-const-variable -Wno-unknown-warning-option -isysroot $(xcodebuild -version -sdk macosx Path) -mmacosx-version-min=10.7" Index: lib/tsan/rtl/tsan_interceptors.cc =================================================================== --- lib/tsan/rtl/tsan_interceptors.cc +++ lib/tsan/rtl/tsan_interceptors.cc @@ -43,8 +43,16 @@ #if SANITIZER_NETBSD #define dirfd(dirp) (*(int *)(dirp)) #define fileno_unlocked fileno -#define stdout __sF[1] -#define stderr __sF[2] + +#if _LP64 +#define __sF_size 152 +#else +#define __sF_size 88 +#endif + +#define stdout ((char*)&__sF + (__sF_size * 1)) +#define stderr ((char*)&__sF + (__sF_size * 2)) + #endif #if SANITIZER_ANDROID @@ -99,7 +107,7 @@ extern "C" int mallopt(int param, int value); #endif #if SANITIZER_NETBSD -extern __sanitizer_FILE **__sF; +extern __sanitizer_FILE __sF[]; #else extern __sanitizer_FILE *stdout, *stderr; #endif @@ -2248,8 +2256,17 @@ #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ ThreadSetName(((TsanInterceptorContext *) ctx)->thr, name) +#if !SANITIZER_NETBSD #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, name) +#else +#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name, arg) \ + do { \ + char newname[32]; \ + internal_snprintf(newname, sizeof(newname), name, arg); \ + __tsan::ctx->thread_registry->SetThreadNameByUserId(thread, newname); \ + } while (false) +#endif #define COMMON_INTERCEPTOR_BLOCK_REAL(name) BLOCK_REAL(name) Index: lib/tsan/rtl/tsan_platform.h =================================================================== --- lib/tsan/rtl/tsan_platform.h +++ lib/tsan/rtl/tsan_platform.h @@ -42,6 +42,19 @@ 7b00 0000 0000 - 7c00 0000 0000: heap 7c00 0000 0000 - 7e80 0000 0000: - 7e80 0000 0000 - 8000 0000 0000: modules and main thread stack + +C/C++ on netbsd/amd64 can reuse the same mapping: + * The address space starts from 0x1000 (option with 0x0) and ends with + 0x7f7ffffff000. + * LoAppMem-kHeapMemEnd can be reused as it is. + * No VDSO support. + * No MidAppMem region. + * No additional HeapMem region. + * HiAppMem contains the stack, loader, shared libraries and heap. + * Stack on NetBSD/amd64 has prereserved 128MB. + * Heap grows downwards (top-down). + * ASLR must be disabled per-process or globally. + */ struct Mapping { static const uptr kMetaShadowBeg = 0x300000000000ull; Index: lib/tsan/rtl/tsan_platform_linux.cc =================================================================== --- lib/tsan/rtl/tsan_platform_linux.cc +++ lib/tsan/rtl/tsan_platform_linux.cc @@ -14,11 +14,12 @@ #include "sanitizer_common/sanitizer_platform.h" -#if SANITIZER_LINUX || SANITIZER_FREEBSD +#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" @@ -401,4 +402,4 @@ } // namespace __tsan -#endif // SANITIZER_LINUX || SANITIZER_FREEBSD +#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD Index: lib/tsan/rtl/tsan_platform_posix.cc =================================================================== --- lib/tsan/rtl/tsan_platform_posix.cc +++ lib/tsan/rtl/tsan_platform_posix.cc @@ -124,8 +124,10 @@ if (segment.start >= HeapMemEnd() && segment.start < HeapEnd()) continue; if (segment.protection == 0) // Zero page or mprotected. continue; +#if !SANITIZER_NETBSD if (segment.start >= VdsoBeg()) // vdso break; +#endif Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", segment.start, segment.end); Die(); Index: lib/tsan/tests/rtl/tsan_test_util_posix.cc =================================================================== --- lib/tsan/tests/rtl/tsan_test_util_posix.cc +++ lib/tsan/tests/rtl/tsan_test_util_posix.cc @@ -9,7 +9,7 @@ // // This file is a part of ThreadSanitizer (TSan), a race detector. // -// Test utils, Linux, FreeBSD and Darwin implementation. +// Test utils, Linux, FreeBSD, NetBSD and Darwin implementation. //===----------------------------------------------------------------------===// #include "sanitizer_common/sanitizer_atomic.h" @@ -270,7 +270,7 @@ } } CHECK_NE(tsan_mop, 0); -#if defined(__FreeBSD__) || defined(__APPLE__) +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__) const int ErrCode = ESOCKTNOSUPPORT; #else const int ErrCode = ECHRNG; Index: test/msan/lit.cfg =================================================================== --- test/msan/lit.cfg +++ test/msan/lit.cfg @@ -29,8 +29,7 @@ # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp'] -# MemorySanitizer tests are currently supported on Linux only. -if config.host_os not in ['Linux']: +if config.host_os not in ['Linux', 'NetBSD']: config.unsupported = True # For mips64, mips64el we have forced store_context_size to 1 because these Index: test/tsan/lit.cfg =================================================================== --- test/tsan/lit.cfg +++ test/tsan/lit.cfg @@ -79,8 +79,7 @@ # Default test suffixes. config.suffixes = ['.c', '.cc', '.cpp', '.m', '.mm'] -# ThreadSanitizer tests are currently supported on FreeBSD, Linux and Darwin. -if config.host_os not in ['FreeBSD', 'Linux', 'Darwin']: +if config.host_os not in ['FreeBSD', 'Linux', 'Darwin', 'NetBSD']: config.unsupported = True if config.android: Index: test/tsan/map32bit.cc =================================================================== --- test/tsan/map32bit.cc +++ test/tsan/map32bit.cc @@ -12,8 +12,8 @@ // XFAIL: aarch64 // XFAIL: powerpc64 -// MAP_32BIT doesn't exist on OS X. -// UNSUPPORTED: darwin +// MAP_32BIT doesn't exist on OS X and NetBSD. +// UNSUPPORTED: darwin,netbsd void *Thread(void *ptr) { *(int*)ptr = 42; @@ -45,4 +45,3 @@ // CHECK: WARNING: ThreadSanitizer: data race // CHECK: DONE - Index: test/tsan/strerror_r.cc =================================================================== --- test/tsan/strerror_r.cc +++ test/tsan/strerror_r.cc @@ -11,7 +11,8 @@ char buffer[1000]; void *Thread(void *p) { - return strerror_r(TEST_ERROR, buffer, sizeof(buffer)); + strerror_r(TEST_ERROR, buffer, sizeof(buffer)); + return buffer; } int main() {