summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Rytarowski <n54@gmx.com>2017-10-25 17:09:05 +0000
committerKamil Rytarowski <n54@gmx.com>2017-10-25 17:09:05 +0000
commit16cd8b12c079582001d7adc5e25de51927a79463 (patch)
treeb15d5533f96a1e4b80f4f9235b5373f4d16eadb7
parentd8ac58ba4113c97e6a33e063e03bd907cb82ea47 (diff)
Add NetBSD improvements in sanitizers
Summary: Changes: * Add initial msan stub support. * Handle NetBSD specific pthread_setname_np(3). * NetBSD supports __attribute__((tls_model("initial-exec"))), define it in SANITIZER_TLS_INITIAL_EXEC_ATTRIBUTE. * Add ReExec() specific bits for NetBSD. * Simplify code and add syscall64 and syscall_ptr for !NetBSD. * Correct bunch of syscall wrappers for NetBSD. * Disable test/tsan/map32bit on NetBSD as not applicable. * Port test/tsan/strerror_r to a POSIX-compliant OSes. * Disable __libc_stack_end on NetBSD. * Disable ReadNullSepFileToArray() on NetBSD. * Define struct_ElfW_Phdr_sz, detected missing symbol by msan. * Change type of __sanitizer_FILE from void to char. This helps to reuse this type as an array. Long term it will be properly implemented along with SANITIZER_HAS_STRUCT_FILE setting to 1. * Add initial NetBSD support in lib/tsan/go/buildgo.sh. * Correct referencing stdout and stderr in tsan_interceptors.cc on NetBSD. * Document NetBSD x86_64 specific virtual memory layout in tsan_platform.h. * Port tests/rtl/tsan_test_util_posix.cc to NetBSD. * Enable NetBSD tests in test/msan/lit.cfg. * Enable NetBSD tests in test/tsan/lit.cfg. Sponsored by <The NetBSD Foundation> Reviewers: joerg, vitalybuka, eugenis, kcc, dvyukov Reviewed By: dvyukov Subscribers: #sanitizers, llvm-commits, kubamracek Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D39124 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@316591 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/msan/msan_interceptors.cc38
-rw-r--r--lib/msan/msan_linux.cc6
-rw-r--r--lib/sanitizer_common/sanitizer_common_interceptors.inc13
-rw-r--r--lib/sanitizer_common/sanitizer_internal_defs.h2
-rw-r--r--lib/sanitizer_common/sanitizer_linux.cc122
-rw-r--r--lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_platform_limits_netbsd.h2
-rw-r--r--lib/sanitizer_common/sanitizer_syscall_generic.inc4
-rwxr-xr-xlib/tsan/go/buildgo.sh15
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc14
-rw-r--r--lib/tsan/rtl/tsan_platform.h13
-rw-r--r--lib/tsan/rtl/tsan_platform_linux.cc5
-rw-r--r--lib/tsan/tests/rtl/tsan_test_util_posix.cc4
-rw-r--r--test/msan/lit.cfg3
-rw-r--r--test/tsan/lit.cfg3
-rw-r--r--test/tsan/map32bit.cc5
-rw-r--r--test/tsan/strerror_r.cc3
17 files changed, 152 insertions, 102 deletions
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc
index 4bf7fcbee..d14ebb30d 100644
--- a/lib/msan/msan_interceptors.cc
+++ b/lib/msan/msan_interceptors.cc
@@ -118,7 +118,7 @@ static void *AllocateFromLocalPool(uptr size_in_bytes) {
#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 @@ INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
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 @@ INTERCEPTOR(void *, valloc, SIZE_T size) {
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 @@ INTERCEPTOR(void, free, void *ptr) {
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 @@ INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
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 @@ INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) {
#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 @@ INTERCEPTOR(int, mallopt, int cmd, int value) {
#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 @@ INTERCEPTOR(char *, strdup, char *src) {
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(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
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 @@ INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
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 @@ INTERCEPTOR(int, putenv, char *string) {
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 @@ INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
#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 @@ INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
#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 @@ INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
# 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 @@ INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
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 @@ INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
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 @@ INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
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 @@ INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
#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 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
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();
diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc
index 0a687f620..a1191a100 100644
--- a/lib/msan/msan_linux.cc
+++ b/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 @@ void MsanTSDDtor(void *tsd) {
} // namespace __msan
-#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
diff --git a/lib/sanitizer_common/sanitizer_common_interceptors.inc b/lib/sanitizer_common/sanitizer_common_interceptors.inc
index 21a405ae4..321126c10 100644
--- a/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ b/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -4405,7 +4405,7 @@ INTERCEPTOR(char *, tempnam, char *dir, char *pfx) {
#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,17 @@ INTERCEPTOR(int, pthread_setname_np, uptr thread, const char *name) {
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;
+ char newname[32]; // PTHREAD_MAX_NAMELEN_NP=32
+ COMMON_INTERCEPTOR_ENTER(ctx, pthread_setname_np, thread, name, arg);
+ COMMON_INTERCEPTOR_READ_STRING(ctx, name, 0);
+ internal_snprintf(newname, sizeof(newname), name, arg);
+ COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, newname);
+ 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
diff --git a/lib/sanitizer_common/sanitizer_internal_defs.h b/lib/sanitizer_common/sanitizer_internal_defs.h
index 003a3c7a9..dcc8db414 100644
--- a/lib/sanitizer_common/sanitizer_internal_defs.h
+++ b/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
diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc
index 48c53d46d..6ea185817 100644
--- a/lib/sanitizer_common/sanitizer_linux.cc
+++ b/lib/sanitizer_common/sanitizer_linux.cc
@@ -87,7 +87,9 @@ extern char **environ; // provided by crt1
#include <limits.h> // For NAME_MAX
#include <sys/sysctl.h>
extern char **environ; // provided by crt1
-#endif // SANITIZER_NETBSD
+#include <sys/exec.h>
+extern struct ps_strings *__ps_strings;
+#endif // SANITIZER_NETBSD
#if !SANITIZER_ANDROID
#include <sys/signal.h>
@@ -174,11 +176,11 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
#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 @@ uptr internal_open(const char *filename, int flags) {
#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 @@ uptr internal_open(const char *filename, int flags, u32 mode) {
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 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
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_stat(const char *path, void *buf) {
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_lstat(const char *path, void *buf) {
}
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_dup2(int oldfd, int newfd) {
}
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 @@ uptr internal_unlink(const char *path) {
#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 @@ uptr internal_rename(const char *oldpath, const char *newpath) {
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 @@ unsigned int internal_sleep(unsigned int seconds) {
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 @@ u64 NanoTime() {
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 @@ const char *GetEnv(const char *name) {
#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 @@ static void ReadNullSepFileToArray(const char *path, char ***arr,
#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 <sys/exec.h>.
+ 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 @@ static void GetArgsAndEnv(char ***argv, char ***envp) {
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 <sys/exec.h>.
- 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 @@ char **GetArgv() {
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_ptrace(int request, int pid, void *addr, void *data) {
}
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_getppid() {
}
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 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
#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 @@ int internal_sigaction_syscall(int signum, const void *act, void *oldact) {
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;
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc
index 3be1d371f..342bd0825 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc
+++ b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc
@@ -128,6 +128,8 @@ uptr __sanitizer_in_addr_sz(int af) {
return 0;
}
+unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr);
+
int glob_nomatch = GLOB_NOMATCH;
int glob_altdirfunc = GLOB_ALTDIRFUNC;
diff --git a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
index fe12cd2a5..d2f3a652b 100644
--- a/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
+++ b/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h
@@ -313,7 +313,7 @@ struct __sanitizer_wordexp_t {
uptr we_nbytes;
};
-typedef void __sanitizer_FILE;
+typedef char __sanitizer_FILE;
#define SANITIZER_HAS_STRUCT_FILE 0
extern int shmctl_ipc_stat;
diff --git a/lib/sanitizer_common/sanitizer_syscall_generic.inc b/lib/sanitizer_common/sanitizer_syscall_generic.inc
index b1a5941a5..138d5ca90 100644
--- a/lib/sanitizer_common/sanitizer_syscall_generic.inc
+++ b/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) {
diff --git a/lib/tsan/go/buildgo.sh b/lib/tsan/go/buildgo.sh
index c27b72afe..62ff0fc38 100755
--- a/lib/tsan/go/buildgo.sh
+++ b/lib/tsan/go/buildgo.sh
@@ -68,6 +68,21 @@ elif [ "`uname -a | grep FreeBSD`" != "" ]; then
../../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"
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 908378ff4..79e243aef 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -43,8 +43,16 @@ using namespace __tsan; // NOLINT
#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 dirfd(void *dirp);
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
diff --git a/lib/tsan/rtl/tsan_platform.h b/lib/tsan/rtl/tsan_platform.h
index bea1daba3..4b9771359 100644
--- a/lib/tsan/rtl/tsan_platform.h
+++ b/lib/tsan/rtl/tsan_platform.h
@@ -42,6 +42,19 @@ C/C++ on linux/x86_64 and freebsd/x86_64
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;
diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc
index ead1e5704..216eef93c 100644
--- a/lib/tsan/rtl/tsan_platform_linux.cc
+++ b/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 @@ void cur_thread_finalize() {
} // namespace __tsan
-#endif // SANITIZER_LINUX || SANITIZER_FREEBSD
+#endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
diff --git a/lib/tsan/tests/rtl/tsan_test_util_posix.cc b/lib/tsan/tests/rtl/tsan_test_util_posix.cc
index 834a271aa..d00e26dd5 100644
--- a/lib/tsan/tests/rtl/tsan_test_util_posix.cc
+++ b/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 @@ void ScopedThread::Impl::HandleEvent(Event *ev) {
}
}
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;
diff --git a/test/msan/lit.cfg b/test/msan/lit.cfg
index c6a384120..cac260999 100644
--- a/test/msan/lit.cfg
+++ b/test/msan/lit.cfg
@@ -29,8 +29,7 @@ config.substitutions.append( ("%clangxx_msan ", build_invocation(clang_msan_cxxf
# 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
diff --git a/test/tsan/lit.cfg b/test/tsan/lit.cfg
index 95c7d7cc3..f0dc7b67e 100644
--- a/test/tsan/lit.cfg
+++ b/test/tsan/lit.cfg
@@ -79,8 +79,7 @@ config.substitutions.append( ("%deflake ", os.path.join(os.path.dirname(__file__
# 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:
diff --git a/test/tsan/map32bit.cc b/test/tsan/map32bit.cc
index 3b4f89900..8aef27bc1 100644
--- a/test/tsan/map32bit.cc
+++ b/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 @@ int main() {
// CHECK: WARNING: ThreadSanitizer: data race
// CHECK: DONE
-
diff --git a/test/tsan/strerror_r.cc b/test/tsan/strerror_r.cc
index 06c92d3bb..ad4820130 100644
--- a/test/tsan/strerror_r.cc
+++ b/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() {