Switch syscall(2)/__syscall(2) calls to libc calls on NetBSD

Summary:
When possible, switch syscall(2)/__syscall(2) calls
to direct calls of internal libc symbols.

Add a new function to detect address of a libc
symbol of a function that could be intercepted.
With the address detector in GetRealLibcAddress(),
an optional interceptor of libc call will be bypassed.

The original approach with syscall(2)/__syscall(2)
wasn't portable across supported ABIs and CPU
architectures. The indirect syscall interface is
also a candidate for removal in future revisions
of NetBSD, as the C language ABI is not a good
domain for serialization of arbitrary functions
arguments.

Switch the following functions to libc calls:
 - internal_mmap()
 - internal_munmap()
 - internal_mprotect()
 - internal_close()
 - internal_open()
 - internal_read()
 - internal_write()
 - internal_ftruncate()
 - internal_stat()
 - internal_lstat()
 - internal_fstat()
 - internal_dup2()
 - internal_readlink()
 - internal_unlink()
 - internal_rename()
 - internal_sched_yield()
 - internal__exit()
 - internal_sleep()
 - internal_execve()
 - NanoTime()
 - internal_clock_gettime()
 - internal_waitpid()
 - internal_getpid()
 - internal_getppid()
 - internal_getdents()
 - internal_lseek()
 - internal_sigaltstack()
 - internal_fork()
 - internal_sigprocmask()
 - internal_sysctl()
 - internal_sigemptyset()
 - internal_sigfillset()
 - GetTid()
 - TgKill()

This revision leaves room for refactoring in subsequent commits.

Reviewers: vitalybuka, kcc, joerg

Reviewed By: vitalybuka

Subscribers: mgorny, fedor.sergeev, jfb, loverszhaokai, devnexen, kubamracek, llvm-commits, ro, #sanitizers

Tags: #sanitizers

Differential Revision: https://reviews.llvm.org/D51419

llvm-svn: 343523
This commit is contained in:
Kamil Rytarowski 2018-10-01 19:50:12 +00:00
parent dcf1d97c5c
commit 162aac511a
4 changed files with 351 additions and 51 deletions

View File

@ -16,6 +16,7 @@ set(SANITIZER_SOURCES_NOTERMINATION
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

View File

@ -31,10 +31,6 @@
#include <asm/param.h>
#endif
#if SANITIZER_NETBSD
#include <lwp.h>
#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 @@ namespace __sanitizer {
#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_write(fd_t fd, const void *buf, uptr count) {
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 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
#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_stat(const char *path, void *buf) {
}
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_lstat(const char *path, void *buf) {
}
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 @@ uptr internal_sched_yield() {
}
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 @@ uptr internal_execve(const char *filename, char *const argv[],
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 @@ bool FileExists(const char *filename) {
return S_ISREG(st.st_mode);
}
#if !SANITIZER_NETBSD
tid_t GetTid() {
#if SANITIZER_FREEBSD
long Tid;
@ -481,8 +469,6 @@ tid_t GetTid() {
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 @@ int TgKill(pid_t pid, tid_t tid, int sig) {
#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 @@ u64 NanoTime() {
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 @@ void BlockingMutex::CheckLocked() {
// 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 @@ struct linux_dirent {
};
#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_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
}
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 @@ int internal_fork() {
#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 @@ 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 || 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 @@ bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
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 @@ ThreadLister::~ThreadLister() {
if (!internal_iserror(descriptor_))
internal_close(descriptor_);
}
#endif
#if SANITIZER_WORDSIZE == 32
// Take care of unusable kernel area in top gigabyte.

View File

@ -0,0 +1,326 @@
//===-- sanitizer_netbsd.cc -----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is shared between Sanitizer run-time libraries and implements
// NetBSD-specific functions from sanitizer_libc.h.
//===----------------------------------------------------------------------===//
#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 <sys/param.h>
#include <sys/types.h>
#include <sys/exec.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <link.h>
#include <lwp.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <ucontext.h>
#include <unistd.h>
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;
}
#define _REAL(func, ...) real##_##func(__VA_ARGS__)
#define DEFINE__REAL(ret_type, func, ...) \
static ret_type (*real_##func)(__VA_ARGS__) = NULL; \
if (!real_##func) { \
real_##func = (ret_type(*)(__VA_ARGS__))GetRealLibcAddress(#func); \
} \
CHECK(real_##func);
#define DEFINE_INTERNAL(ret_type, func, ...) \
ret_type internal_##func(__VA_ARGS__)
// --------------- sanitizer_libc.h
DEFINE_INTERNAL(uptr, 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);
}
DEFINE_INTERNAL(uptr, munmap, void *addr, uptr length) {
DEFINE__REAL(int, munmap, void *a, uptr b);
return _REAL(munmap, addr, length);
}
DEFINE_INTERNAL(int, mprotect, void *addr, uptr length, int prot) {
DEFINE__REAL(int, mprotect, void *a, uptr b, int c);
return _REAL(mprotect, addr, length, prot);
}
DEFINE_INTERNAL(uptr, close, fd_t fd) {
CHECK(&_sys_close);
return _sys_close(fd);
}
DEFINE_INTERNAL(uptr, open, const char *filename, int flags) {
CHECK(&_sys_open);
return _sys_open(filename, flags);
}
DEFINE_INTERNAL(uptr, open, const char *filename, int flags, u32 mode) {
CHECK(&_sys_open);
return _sys_open(filename, flags, mode);
}
DEFINE_INTERNAL(uptr, 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;
}
DEFINE_INTERNAL(uptr, 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;
}
DEFINE_INTERNAL(uptr, ftruncate, fd_t fd, uptr size) {
sptr res;
CHECK(&__ftruncate);
HANDLE_EINTR(res, __ftruncate(fd, 0, (s64)size));
return res;
}
DEFINE_INTERNAL(uptr, stat, const char *path, void *buf) {
DEFINE__REAL(int, __stat50, const char *a, void *b);
return _REAL(__stat50, path, buf);
}
DEFINE_INTERNAL(uptr, lstat, const char *path, void *buf) {
DEFINE__REAL(int, __lstat50, const char *a, void *b);
return _REAL(__lstat50, path, buf);
}
DEFINE_INTERNAL(uptr, fstat, fd_t fd, void *buf) {
DEFINE__REAL(int, __fstat50, int a, void *b);
return _REAL(__fstat50, fd, buf);
}
DEFINE_INTERNAL(uptr, filesize, fd_t fd) {
struct stat st;
if (internal_fstat(fd, &st))
return -1;
return (uptr)st.st_size;
}
DEFINE_INTERNAL(uptr, dup2, int oldfd, int newfd) {
DEFINE__REAL(int, dup2, int a, int b);
return _REAL(dup2, oldfd, newfd);
}
DEFINE_INTERNAL(uptr, readlink, const char *path, char *buf, uptr bufsize) {
CHECK(&_sys_readlink);
return (uptr)_sys_readlink(path, buf, bufsize);
}
DEFINE_INTERNAL(uptr, unlink, const char *path) {
DEFINE__REAL(int, unlink, const char *a);
return _REAL(unlink, path);
}
DEFINE_INTERNAL(uptr, rename, const char *oldpath, const char *newpath) {
DEFINE__REAL(int, rename, const char *a, const char *b);
return _REAL(rename, oldpath, newpath);
}
DEFINE_INTERNAL(uptr, sched_yield) {
CHECK(&_sys_sched_yield);
return _sys_sched_yield();
}
DEFINE_INTERNAL(void, _exit, int exitcode) {
DEFINE__REAL(void, _exit, int a);
_REAL(_exit, exitcode);
Die(); // Unreachable.
}
DEFINE_INTERNAL(unsigned int, 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;
}
DEFINE_INTERNAL(uptr, execve, const char *filename, char *const argv[],
char *const envp[]) {
CHECK(&_sys_execve);
return _sys_execve(filename, argv, envp);
}
tid_t GetTid() {
DEFINE__REAL(int, _lwp_self);
return _REAL(_lwp_self);
}
int TgKill(pid_t pid, tid_t tid, int sig) {
DEFINE__REAL(int, _lwp_kill, int a, int b);
(void)pid;
return _REAL(_lwp_kill, tid, sig);
}
u64 NanoTime() {
timeval tv;
DEFINE__REAL(int, __gettimeofday50, void *a, void *b);
internal_memset(&tv, 0, sizeof(tv));
_REAL(__gettimeofday50, &tv, 0);
return (u64)tv.tv_sec * 1000 * 1000 * 1000 + tv.tv_usec * 1000;
}
DEFINE_INTERNAL(uptr, clock_gettime, __sanitizer_clockid_t clk_id, void *tp) {
DEFINE__REAL(int, __clock_gettime50, __sanitizer_clockid_t a, void *b);
return _REAL(__clock_gettime50, clk_id, tp);
}
DEFINE_INTERNAL(uptr, ptrace, int request, int pid, void *addr, void *data) {
Printf("internal_ptrace not implemented for NetBSD");
Die();
return 0;
}
DEFINE_INTERNAL(uptr, waitpid, int pid, int *status, int options) {
CHECK(&_sys___wait450);
return _sys___wait450(pid, status, options, 0 /* rusage */);
}
DEFINE_INTERNAL(uptr, getpid) {
DEFINE__REAL(int, getpid);
return _REAL(getpid);
}
DEFINE_INTERNAL(uptr, getppid) {
DEFINE__REAL(int, getppid);
return _REAL(getppid);
}
DEFINE_INTERNAL(uptr, getdents, fd_t fd, void *dirp, unsigned int count) {
DEFINE__REAL(int, __getdents30, int a, void *b, size_t c);
return _REAL(__getdents30, fd, dirp, count);
}
DEFINE_INTERNAL(uptr, lseek, fd_t fd, OFF_T offset, int whence) {
CHECK(&__lseek);
return __lseek(fd, 0, offset, whence);
}
DEFINE_INTERNAL(uptr, prctl, int option, uptr arg2, uptr arg3, uptr arg4,
uptr arg5) {
Printf("internal_prctl not implemented for NetBSD");
Die();
return 0;
}
DEFINE_INTERNAL(uptr, sigaltstack, const void *ss, void *oss) {
DEFINE__REAL(int, __sigaltstack14, const void *a, void *b);
return _REAL(__sigaltstack14, ss, oss);
}
DEFINE_INTERNAL(int, fork) {
CHECK(&__fork);
return __fork();
}
DEFINE_INTERNAL(int, 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);
}
DEFINE_INTERNAL(uptr, sigprocmask, int how, __sanitizer_sigset_t *set,
__sanitizer_sigset_t *oldset) {
CHECK(&_sys___sigprocmask14);
return _sys___sigprocmask14(how, set, oldset);
}
DEFINE_INTERNAL(void, sigfillset, __sanitizer_sigset_t *set) {
DEFINE__REAL(int, __sigfillset14, const void *a);
(void)_REAL(__sigfillset14, set);
}
DEFINE_INTERNAL(void, sigemptyset, __sanitizer_sigset_t *set) {
DEFINE__REAL(int, __sigemptyset14, const void *a);
(void)_REAL(__sigemptyset14, set);
}
DEFINE_INTERNAL(uptr, 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

View File

@ -94,6 +94,7 @@ elif [ "`uname -a | grep NetBSD`" != "" ]; then
../../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