diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2013-05-08 14:43:49 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2013-05-08 14:43:49 +0000 |
commit | 6f4be19b576fc7eb5f3f573ebedbe2cd4a598ee7 (patch) | |
tree | ebf5d111a9704ca38a393f8ef55d771a7d8e4d82 | |
parent | 4307282de6cd6e1f2f24871361248eec136ce2c7 (diff) | |
download | bcm5719-llvm-6f4be19b576fc7eb5f3f573ebedbe2cd4a598ee7.tar.gz bcm5719-llvm-6f4be19b576fc7eb5f3f573ebedbe2cd4a598ee7.zip |
[nolibc] Change internal syscall API to remove reliance on libc's errno.
This change moves to a model where the error value of a system call is
potentially contained in the return value itself rather than being
implicit in errno. The helper function internal_iserror can be used
to extract the error value from a return value. On platforms other
than Linux/x86_64 this still uses errno, but other platforms are free
to port their error handling to this new model.
Differential Revision: http://llvm-reviews.chandlerc.com/D756
llvm-svn: 181436
17 files changed, 309 insertions, 151 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc index 39e52e88083..3bb8e8118d4 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.cc @@ -69,8 +69,8 @@ static void MaybeOpenReportFile() { InternalScopedBuffer<char> report_path_full(4096); internal_snprintf(report_path_full.data(), report_path_full.size(), "%s.%d", report_path_prefix, GetPid()); - fd_t fd = OpenFile(report_path_full.data(), true); - if (fd == kInvalidFd) { + uptr openrv = OpenFile(report_path_full.data(), true); + if (internal_iserror(openrv)) { report_fd = kStderrFd; log_to_file = false; Report("ERROR: Can't open file: %s\n", report_path_full.data()); @@ -80,7 +80,7 @@ static void MaybeOpenReportFile() { // We're in the child. Close the parent's log. internal_close(report_fd); } - report_fd = fd; + report_fd = openrv; report_fd_pid = GetPid(); } @@ -108,8 +108,9 @@ uptr ReadFileToBuffer(const char *file_name, char **buff, *buff_size = 0; // The files we usually open are not seekable, so try different buffer sizes. for (uptr size = kMinFileLen; size <= max_len; size *= 2) { - fd_t fd = OpenFile(file_name, /*write*/ false); - if (fd == kInvalidFd) return 0; + uptr openrv = OpenFile(file_name, /*write*/ false); + if (internal_iserror(openrv)) return 0; + fd_t fd = openrv; UnmapOrDie(*buff, *buff_size); *buff = (char*)MmapOrDie(size, __FUNCTION__); *buff_size = size; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 7c18f1794a7..92ba0d53b99 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h @@ -115,7 +115,7 @@ void SetPrintfAndReportCallback(void (*callback)(const char *)); // Can be used to prevent mixing error reports from different sanitizers. extern StaticSpinMutex CommonSanitizerReportMutex; -fd_t OpenFile(const char *filename, bool write); +uptr OpenFile(const char *filename, bool write); // Opens the file 'file_name" and reads up to 'max_len' bytes. // The resulting buffer is mmaped and stored in '*buff'. // The size of the mmaped region is stored in '*buff_size', diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h index 6ee21f02fe1..9a7d374bf5a 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h @@ -273,10 +273,12 @@ extern "C" void* _ReturnAddress(void); # define GET_CURRENT_FRAME() (uptr)0xDEADBEEF #endif -#define HANDLE_EINTR(res, f) { \ - do { \ - res = (f); \ - } while (res == -1 && errno == EINTR); \ +#define HANDLE_EINTR(res, f) \ + { \ + int rverrno; \ + do { \ + res = (f); \ + } while (internal_iserror(res, &rverrno) && rverrno == EINTR); \ } #endif // SANITIZER_DEFS_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_libc.h b/compiler-rt/lib/sanitizer_common/sanitizer_libc.h index 9f4088e02af..5f77ad1e5cf 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_libc.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_libc.h @@ -53,42 +53,45 @@ bool mem_is_zero(const char *mem, uptr size); // Memory -void *internal_mmap(void *addr, uptr length, int prot, int flags, - int fd, u64 offset); -int internal_munmap(void *addr, uptr length); +uptr internal_mmap(void *addr, uptr length, int prot, int flags, + int fd, u64 offset); +uptr internal_munmap(void *addr, uptr length); // I/O const fd_t kInvalidFd = -1; const fd_t kStdinFd = 0; const fd_t kStdoutFd = 1; const fd_t kStderrFd = 2; -int internal_close(fd_t fd); +uptr internal_close(fd_t fd); int internal_isatty(fd_t fd); // Use __sanitizer::OpenFile() instead. -fd_t internal_open(const char *filename, int flags); -fd_t internal_open(const char *filename, int flags, u32 mode); +uptr internal_open(const char *filename, int flags); +uptr internal_open(const char *filename, int flags, u32 mode); uptr internal_read(fd_t fd, void *buf, uptr count); uptr internal_write(fd_t fd, const void *buf, uptr count); // OS uptr internal_filesize(fd_t fd); // -1 on error. -int internal_stat(const char *path, void *buf); -int internal_lstat(const char *path, void *buf); -int internal_fstat(fd_t fd, void *buf); -int internal_dup2(int oldfd, int newfd); +uptr internal_stat(const char *path, void *buf); +uptr internal_lstat(const char *path, void *buf); +uptr internal_fstat(fd_t fd, void *buf); +uptr internal_dup2(int oldfd, int newfd); uptr internal_readlink(const char *path, char *buf, uptr bufsize); -int internal_unlink(const char *path); +uptr internal_unlink(const char *path); void NORETURN internal__exit(int exitcode); -OFF_T internal_lseek(fd_t fd, OFF_T offset, int whence); +uptr internal_lseek(fd_t fd, OFF_T offset, int whence); -long internal_ptrace(int request, int pid, void *addr, void *data); -int internal_waitpid(int pid, int *status, int options); -int internal_getppid(); +uptr internal_ptrace(int request, int pid, void *addr, void *data); +uptr internal_waitpid(int pid, int *status, int options); +uptr internal_getppid(); // Threading -int internal_sched_yield(); +uptr internal_sched_yield(); + +// Error handling +bool internal_iserror(uptr retval, int *rverrno = 0); } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 29c67220e65..46d3a2463aa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -72,46 +72,52 @@ extern "C" int arch_prctl(int code, __sanitizer::uptr *addr); namespace __sanitizer { +#ifdef __x86_64__ +#include "sanitizer_syscall_linux_x86_64.inc" +#else +#include "sanitizer_syscall_generic.inc" +#endif + // --------------- sanitizer_libc.h -void *internal_mmap(void *addr, uptr length, int prot, int flags, +uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, u64 offset) { #if SANITIZER_LINUX_USES_64BIT_SYSCALLS - return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); + return internal_syscall(__NR_mmap, addr, length, prot, flags, fd, offset); #else - return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); + return internal_syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); #endif } -int internal_munmap(void *addr, uptr length) { - return syscall(__NR_munmap, addr, length); +uptr internal_munmap(void *addr, uptr length) { + return internal_syscall(__NR_munmap, addr, length); } -int internal_close(fd_t fd) { - return syscall(__NR_close, fd); +uptr internal_close(fd_t fd) { + return internal_syscall(__NR_close, fd); } -fd_t internal_open(const char *filename, int flags) { - return syscall(__NR_open, filename, flags); +uptr internal_open(const char *filename, int flags) { + return internal_syscall(__NR_open, filename, flags); } -fd_t internal_open(const char *filename, int flags, u32 mode) { - return syscall(__NR_open, filename, flags, mode); +uptr internal_open(const char *filename, int flags, u32 mode) { + return internal_syscall(__NR_open, filename, flags, mode); } -fd_t OpenFile(const char *filename, bool write) { +uptr OpenFile(const char *filename, bool write) { return internal_open(filename, write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660); } uptr internal_read(fd_t fd, void *buf, uptr count) { sptr res; - HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count)); + HANDLE_EINTR(res, (sptr)internal_syscall(__NR_read, fd, buf, count)); return res; } uptr internal_write(fd_t fd, const void *buf, uptr count) { sptr res; - HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count)); + HANDLE_EINTR(res, (sptr)internal_syscall(__NR_write, fd, buf, count)); return res; } @@ -135,34 +141,34 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) { } #endif -int internal_stat(const char *path, void *buf) { +uptr internal_stat(const char *path, void *buf) { #if SANITIZER_LINUX_USES_64BIT_SYSCALLS - return syscall(__NR_stat, path, buf); + return internal_syscall(__NR_stat, path, buf); #else struct stat64 buf64; - int res = syscall(__NR_stat64, path, &buf64); + int res = internal_syscall(__NR_stat64, path, &buf64); stat64_to_stat(&buf64, (struct stat *)buf); return res; #endif } -int internal_lstat(const char *path, void *buf) { +uptr internal_lstat(const char *path, void *buf) { #if SANITIZER_LINUX_USES_64BIT_SYSCALLS - return syscall(__NR_lstat, path, buf); + return internal_syscall(__NR_lstat, path, buf); #else struct stat64 buf64; - int res = syscall(__NR_lstat64, path, &buf64); + int res = internal_syscall(__NR_lstat64, path, &buf64); stat64_to_stat(&buf64, (struct stat *)buf); return res; #endif } -int internal_fstat(fd_t fd, void *buf) { +uptr internal_fstat(fd_t fd, void *buf) { #if SANITIZER_LINUX_USES_64BIT_SYSCALLS - return syscall(__NR_fstat, fd, buf); + return internal_syscall(__NR_fstat, fd, buf); #else struct stat64 buf64; - int res = syscall(__NR_fstat64, fd, &buf64); + int res = internal_syscall(__NR_fstat64, fd, &buf64); stat64_to_stat(&buf64, (struct stat *)buf); return res; #endif @@ -175,27 +181,32 @@ uptr internal_filesize(fd_t fd) { return (uptr)st.st_size; } -int internal_dup2(int oldfd, int newfd) { - return syscall(__NR_dup2, oldfd, newfd); +uptr internal_dup2(int oldfd, int newfd) { + return internal_syscall(__NR_dup2, oldfd, newfd); } uptr internal_readlink(const char *path, char *buf, uptr bufsize) { - return (uptr)syscall(__NR_readlink, path, buf, bufsize); + return internal_syscall(__NR_readlink, path, buf, bufsize); } -int internal_unlink(const char *path) { - return syscall(__NR_unlink, path); +uptr internal_unlink(const char *path) { + return internal_syscall(__NR_unlink, path); } -int internal_sched_yield() { - return syscall(__NR_sched_yield); +uptr internal_sched_yield() { + return internal_syscall(__NR_sched_yield); } void internal__exit(int exitcode) { - syscall(__NR_exit_group, exitcode); + internal_syscall(__NR_exit_group, exitcode); Die(); // Unreachable. } +uptr internal_execve(const char *filename, char *const argv[], + char *const envp[]) { + return internal_syscall(__NR_execve, filename, argv, envp); +} + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { struct stat st; @@ -206,12 +217,12 @@ bool FileExists(const char *filename) { } uptr GetTid() { - return syscall(__NR_gettid); + return internal_syscall(__NR_gettid); } u64 NanoTime() { kernel_timeval tv; - syscall(__NR_gettimeofday, &tv, 0); + internal_syscall(__NR_gettimeofday, &tv, 0); return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; } @@ -349,8 +360,10 @@ static void GetArgsAndEnv(char ***argv, char ***envp) { void ReExec() { char **argv, **envp; GetArgsAndEnv(&argv, &envp); - execve("/proc/self/exe", argv, envp); - Printf("execve failed, errno %d\n", errno); + uptr rv = internal_execve("/proc/self/exe", argv, envp); + int rverrno; + CHECK_EQ(internal_iserror(rv, &rverrno), true); + Printf("execve failed, errno %d\n", rverrno); Die(); } @@ -616,7 +629,7 @@ void BlockingMutex::Lock() { if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) return; while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) - syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); + internal_syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0); } void BlockingMutex::Unlock() { @@ -624,7 +637,7 @@ void BlockingMutex::Unlock() { u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed); CHECK_NE(v, MtxUnlocked); if (v == MtxSleeping) - syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0); + internal_syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0); } void BlockingMutex::CheckLocked() { @@ -644,33 +657,37 @@ struct linux_dirent { }; // Syscall wrappers. -long internal_ptrace(int request, int pid, void *addr, void *data) { - return syscall(__NR_ptrace, request, pid, addr, data); +uptr internal_ptrace(int request, int pid, void *addr, void *data) { + return internal_syscall(__NR_ptrace, request, pid, addr, data); +} + +uptr internal_waitpid(int pid, int *status, int options) { + return internal_syscall(__NR_wait4, pid, status, options, 0 /* rusage */); } -int internal_waitpid(int pid, int *status, int options) { - return syscall(__NR_wait4, pid, status, options, NULL /* rusage */); +uptr internal_getpid() { + return internal_syscall(__NR_getpid); } -int internal_getppid() { - return syscall(__NR_getppid); +uptr internal_getppid() { + return internal_syscall(__NR_getppid); } -int internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { - return syscall(__NR_getdents, fd, dirp, count); +uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { + return internal_syscall(__NR_getdents, fd, dirp, count); } -OFF_T internal_lseek(fd_t fd, OFF_T offset, int whence) { - return syscall(__NR_lseek, fd, offset, whence); +uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { + return internal_syscall(__NR_lseek, fd, offset, whence); } -int internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { - return syscall(__NR_prctl, option, arg2, arg3, arg4, arg5); +uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { + return internal_syscall(__NR_prctl, option, arg2, arg3, arg4, arg5); } -int internal_sigaltstack(const struct sigaltstack *ss, +uptr internal_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss) { - return syscall(__NR_sigaltstack, ss, oss); + return internal_syscall(__NR_sigaltstack, ss, oss); } // ThreadLister implementation. @@ -684,12 +701,13 @@ ThreadLister::ThreadLister(int pid) char task_directory_path[80]; internal_snprintf(task_directory_path, sizeof(task_directory_path), "/proc/%d/task/", pid); - descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY); - if (descriptor_ < 0) { + uptr openrv = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY); + if (internal_iserror(openrv)) { error_ = true; Report("Can't open /proc/%d/task for reading.\n", pid); } else { error_ = false; + descriptor_ = openrv; } } @@ -729,7 +747,7 @@ bool ThreadLister::GetDirectoryEntries() { bytes_read_ = internal_getdents(descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size()); - if (bytes_read_ < 0) { + if (internal_iserror(bytes_read_)) { Report("Can't read directory entries from /proc/%d/task.\n", pid_); error_ = true; return false; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h index 2545e631f28..ec2d94889aa 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.h @@ -24,9 +24,10 @@ namespace __sanitizer { struct linux_dirent; // Syscall wrappers. -int internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); -int internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); -int internal_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss); +uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count); +uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); +uptr internal_sigaltstack(const struct sigaltstack* ss, + struct sigaltstack* oss); // This class reads thread IDs from /proc/<pid>/task using only syscalls. class ThreadLister { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc index 08d48bca34e..8134f894c60 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc @@ -42,6 +42,8 @@ namespace __sanitizer { +#include "sanitizer_syscall_generic.inc" + // ---------------------- sanitizer_libc.h void *internal_mmap(void *addr, size_t length, int prot, int flags, int fd, u64 offset) { @@ -52,19 +54,19 @@ int internal_munmap(void *addr, uptr length) { return munmap(addr, length); } -int internal_close(fd_t fd) { +uptr internal_close(fd_t fd) { return close(fd); } -fd_t internal_open(const char *filename, int flags) { +uptr internal_open(const char *filename, int flags) { return open(filename, flags); } -fd_t internal_open(const char *filename, int flags, u32 mode) { +uptr internal_open(const char *filename, int flags, u32 mode) { return open(filename, flags, mode); } -fd_t OpenFile(const char *filename, bool write) { +uptr OpenFile(const char *filename, bool write) { return internal_open(filename, write ? O_WRONLY | O_CREAT : O_RDONLY, 0660); } @@ -77,15 +79,15 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) { return write(fd, buf, count); } -int internal_stat(const char *path, void *buf) { +uptr internal_stat(const char *path, void *buf) { return stat(path, (struct stat *)buf); } -int internal_lstat(const char *path, void *buf) { +uptr internal_lstat(const char *path, void *buf) { return lstat(path, (struct stat *)buf); } -int internal_fstat(fd_t fd, void *buf) { +uptr internal_fstat(fd_t fd, void *buf) { return fstat(fd, (struct stat *)buf); } @@ -96,7 +98,7 @@ uptr internal_filesize(fd_t fd) { return (uptr)st.st_size; } -int internal_dup2(int oldfd, int newfd) { +uptr internal_dup2(int oldfd, int newfd) { return dup2(oldfd, newfd); } @@ -104,7 +106,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) { return readlink(path, buf, bufsize); } -int internal_sched_yield() { +uptr internal_sched_yield() { return sched_yield(); } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index fffd0314ddd..1bc99081a6b 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -57,10 +57,11 @@ uptr GetThreadSelf() { void *MmapOrDie(uptr size, const char *mem_type) { size = RoundUpTo(size, GetPageSizeCached()); - void *res = internal_mmap(0, size, + uptr res = internal_mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - if (res == (void*)-1) { + int reserrno; + if (internal_iserror(res, &reserrno)) { static int recursion_count; if (recursion_count) { // The Report() and CHECK calls below may call mmap recursively and fail. @@ -70,17 +71,17 @@ void *MmapOrDie(uptr size, const char *mem_type) { } recursion_count++; Report("ERROR: %s failed to allocate 0x%zx (%zd) bytes of %s: %d\n", - SanitizerToolName, size, size, mem_type, errno); + SanitizerToolName, size, size, mem_type, reserrno); DumpProcessMap(); CHECK("unable to mmap" && 0); } - return res; + return (void *)res; } void UnmapOrDie(void *addr, uptr size) { if (!addr || !size) return; - int res = internal_munmap(addr, size); - if (res != 0) { + uptr res = internal_munmap(addr, size); + if (internal_iserror(res)) { Report("ERROR: %s failed to deallocate 0x%zx (%zd) bytes at address %p\n", SanitizerToolName, size, size, addr); CHECK("unable to unmap" && 0); @@ -89,39 +90,41 @@ void UnmapOrDie(void *addr, uptr size) { void *MmapFixedNoReserve(uptr fixed_addr, uptr size) { uptr PageSize = GetPageSizeCached(); - void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)), + uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)), RoundUpTo(size, PageSize), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, -1, 0); - if (p == (void*)-1) + int reserrno; + if (internal_iserror(p, &reserrno)) Report("ERROR: " "%s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n", - SanitizerToolName, size, size, fixed_addr, errno); - return p; + SanitizerToolName, size, size, fixed_addr, reserrno); + return (void *)p; } void *MmapFixedOrDie(uptr fixed_addr, uptr size) { uptr PageSize = GetPageSizeCached(); - void *p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)), + uptr p = internal_mmap((void*)(fixed_addr & ~(PageSize - 1)), RoundUpTo(size, PageSize), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); - if (p == (void*)-1) { + int reserrno; + if (internal_iserror(p, &reserrno)) { Report("ERROR:" " %s failed to allocate 0x%zx (%zd) bytes at address %p (%d)\n", - SanitizerToolName, size, size, fixed_addr, errno); + SanitizerToolName, size, size, fixed_addr, reserrno); CHECK("unable to mmap" && 0); } - return p; + return (void *)p; } void *Mprotect(uptr fixed_addr, uptr size) { - return internal_mmap((void*)fixed_addr, size, - PROT_NONE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, - -1, 0); + return (void *)internal_mmap((void*)fixed_addr, size, + PROT_NONE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED | + MAP_NORESERVE, -1, 0); } void FlushUnneededShadowMemory(uptr addr, uptr size) { @@ -129,14 +132,15 @@ void FlushUnneededShadowMemory(uptr addr, uptr size) { } void *MapFileToMemory(const char *file_name, uptr *buff_size) { - fd_t fd = OpenFile(file_name, false); - CHECK_NE(fd, kInvalidFd); + uptr openrv = OpenFile(file_name, false); + CHECK(!internal_iserror(openrv)); + fd_t fd = openrv; uptr fsize = internal_filesize(fd); CHECK_NE(fsize, (uptr)-1); CHECK_GT(fsize, 0); *buff_size = RoundUpTo(fsize, GetPageSizeCached()); - void *map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); - return (map == MAP_FAILED) ? 0 : map; + uptr map = internal_mmap(0, *buff_size, PROT_READ, MAP_PRIVATE, fd, 0); + return internal_iserror(map) ? 0 : (void *)map; } diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc index 8bb155588cd..fe3d4e39501 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stoptheworld_linux.cc @@ -101,23 +101,26 @@ bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) { // usually small. if (suspended_threads_list_.Contains(thread_id)) return false; - if (internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL) != 0) { + int pterrno; + if (internal_iserror(internal_ptrace(PTRACE_ATTACH, thread_id, NULL, NULL), + &pterrno)) { // Either the thread is dead, or something prevented us from attaching. // Log this event and move on. - Report("Could not attach to thread %d (errno %d).\n", thread_id, errno); + Report("Could not attach to thread %d (errno %d).\n", thread_id, pterrno); return false; } else { if (SanitizerVerbosity > 0) Report("Attached to thread %d.\n", thread_id); // The thread is not guaranteed to stop before ptrace returns, so we must // wait on it. - int waitpid_status; + uptr waitpid_status; HANDLE_EINTR(waitpid_status, internal_waitpid(thread_id, NULL, __WALL)); - if (waitpid_status < 0) { + int wperrno; + if (internal_iserror(waitpid_status, &wperrno)) { // Got a ECHILD error. I don't think this situation is possible, but it // doesn't hurt to report it. Report("Waiting on thread %d failed, detaching (errno %d).\n", thread_id, - errno); + wperrno); internal_ptrace(PTRACE_DETACH, thread_id, NULL, NULL); return false; } @@ -129,14 +132,16 @@ bool ThreadSuspender::SuspendThread(SuspendedThreadID thread_id) { void ThreadSuspender::ResumeAllThreads() { for (uptr i = 0; i < suspended_threads_list_.thread_count(); i++) { pid_t tid = suspended_threads_list_.GetThreadID(i); - if (internal_ptrace(PTRACE_DETACH, tid, NULL, NULL) == 0) { + int pterrno; + if (!internal_iserror(internal_ptrace(PTRACE_DETACH, tid, NULL, NULL), + &pterrno)) { if (SanitizerVerbosity > 0) Report("Detached from thread %d.\n", tid); } else { // Either the thread is dead, or we are already detached. // The latter case is possible, for instance, if this function was called // from a signal handler. - Report("Could not detach from thread %d (errno %d).\n", tid, errno); + Report("Could not detach from thread %d (errno %d).\n", tid, pterrno); } } } @@ -330,9 +335,10 @@ void StopTheWorld(StopTheWorldCallback callback, void *argument) { // must avoid using errno while the tracer thread is running. // At this point, any signal will either be blocked or kill us, so waitpid // should never return (and set errno) while the tracer thread is alive. - int waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL); - if (waitpid_status < 0) - Report("Waiting on the tracer thread failed (errno %d).\n", errno); + uptr waitpid_status = internal_waitpid(tracer_pid, NULL, __WALL); + int wperrno; + if (internal_iserror(waitpid_status, &wperrno)) + Report("Waiting on the tracer thread failed (errno %d).\n", wperrno); } // Restore the dumpable flag. if (!process_was_dumpable) @@ -358,9 +364,11 @@ int SuspendedThreadsList::GetRegistersAndSP(uptr index, uptr *sp) const { pid_t tid = GetThreadID(index); regs_struct regs; - if (internal_ptrace(PTRACE_GETREGS, tid, NULL, ®s) != 0) { + int pterrno; + if (internal_iserror(internal_ptrace(PTRACE_GETREGS, tid, NULL, ®s), + &pterrno)) { Report("Could not get registers from thread %d (errno %d).\n", - tid, errno); + tid, pterrno); return -1; } #if defined(__arm__) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_linux.cc index 14a682bd99e..fc3299c0f4e 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_linux.cc @@ -148,7 +148,7 @@ static int dl_iterate_phdr_cb(dl_phdr_info *info, size_t size, void *arg) { // First module is the binary itself. uptr module_name_len = internal_readlink( "/proc/self/exe", module_name.data(), module_name.size()); - if (module_name_len == (uptr)-1) { + if (internal_iserror(module_name_len)) { // We can't read /proc/self/exe for some reason, assume the name of the // binary is unknown. module_name_len = internal_snprintf(module_name.data(), diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc new file mode 100644 index 00000000000..aac20a5f2d6 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_generic.inc @@ -0,0 +1,24 @@ +//===-- sanitizer_syscall_generic.inc ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generic implementations of internal_syscall and internal_iserror. +// +//===----------------------------------------------------------------------===// + +#define internal_syscall syscall + +bool internal_iserror(uptr retval, int *rverrno) { + if (retval == (uptr)-1) { + if (rverrno) + *rverrno = errno; + return true; + } else { + return false; + } +} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc new file mode 100644 index 00000000000..e084b84ab11 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_syscall_linux_x86_64.inc @@ -0,0 +1,87 @@ +//===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implementations of internal_syscall and internal_iserror for Linux/x86_64. +// +//===----------------------------------------------------------------------===// + +static uptr internal_syscall(u64 nr) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11"); + return retval; +} + +template <typename T1> +static uptr internal_syscall(u64 nr, T1 arg1) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) : + "rcx", "r11"); + return retval; +} + +template <typename T1, typename T2> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2) : "rcx", "r11"); + return retval; +} + +template <typename T1, typename T2, typename T3> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) { + u64 retval; + asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11"); + return retval; +} + +template <typename T1, typename T2, typename T3, typename T4> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { + u64 retval; + asm volatile("mov %5, %%r10;" + "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) : + "rcx", "r11", "r10"); + return retval; +} + +template <typename T1, typename T2, typename T3, typename T4, typename T5> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, + T5 arg5) { + u64 retval; + asm volatile("mov %5, %%r10;" + "mov %6, %%r8;" + "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) : + "rcx", "r11", "r10", "r8"); + return retval; +} + +template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> +static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, + T5 arg5, T6 arg6) { + u64 retval; + asm volatile("mov %5, %%r10;" + "mov %6, %%r8;" + "mov %7, %%r9;" + "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), + "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5), + "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9"); + return retval; +} + +bool internal_iserror(uptr retval, int *rverrno) { + if (retval >= (uptr)-4095) { + if (rverrno) + *rverrno = -retval; + return true; + } + return false; +} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc index 95445be6546..ab0d78dc45d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc @@ -29,6 +29,8 @@ namespace __sanitizer { +#include "sanitizer_syscall_generic.inc" + // --------------------- sanitizer_common.h uptr GetPageSize() { return 1U << 14; // FIXME: is this configurable? @@ -217,7 +219,7 @@ int internal_munmap(void *addr, uptr length) { UNIMPLEMENTED(); } -int internal_close(fd_t fd) { +uptr internal_close(fd_t fd) { UNIMPLEMENTED(); } @@ -233,7 +235,7 @@ fd_t internal_open(const char *filename, int flags, u32 mode) { UNIMPLEMENTED(); } -fd_t OpenFile(const char *filename, bool write) { +uptr OpenFile(const char *filename, bool write) { UNIMPLEMENTED(); } @@ -253,15 +255,15 @@ uptr internal_write(fd_t fd, const void *buf, uptr count) { return ret; } -int internal_stat(const char *path, void *buf) { +uptr internal_stat(const char *path, void *buf) { UNIMPLEMENTED(); } -int internal_lstat(const char *path, void *buf) { +uptr internal_lstat(const char *path, void *buf) { UNIMPLEMENTED(); } -int internal_fstat(fd_t fd, void *buf) { +uptr internal_fstat(fd_t fd, void *buf) { UNIMPLEMENTED(); } @@ -269,7 +271,7 @@ uptr internal_filesize(fd_t fd) { UNIMPLEMENTED(); } -int internal_dup2(int oldfd, int newfd) { +uptr internal_dup2(int oldfd, int newfd) { UNIMPLEMENTED(); } @@ -277,7 +279,7 @@ uptr internal_readlink(const char *path, char *buf, uptr bufsize) { UNIMPLEMENTED(); } -int internal_sched_yield() { +uptr internal_sched_yield() { Sleep(0); return 0; } diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc b/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc index 51cd66cf0cd..459fa39d578 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_libc_test.cc @@ -74,29 +74,31 @@ TEST(SanitizerCommon, FileOps) { internal_snprintf(temp_filename, sizeof(temp_filename), "/tmp/sanitizer_common.tmp.%d", uid); #endif - fd_t fd = OpenFile(temp_filename, true); - EXPECT_NE(fd, kInvalidFd); + uptr openrv = OpenFile(temp_filename, true); + EXPECT_EQ(false, internal_iserror(openrv)); + fd_t fd = openrv; EXPECT_EQ(len1, internal_write(fd, str1, len1)); EXPECT_EQ(len2, internal_write(fd, str2, len2)); internal_close(fd); - fd = OpenFile(temp_filename, false); - EXPECT_NE(fd, kInvalidFd); + openrv = OpenFile(temp_filename, false); + EXPECT_EQ(false, internal_iserror(openrv)); + fd = openrv; uptr fsize = internal_filesize(fd); EXPECT_EQ(len1 + len2, fsize); #if SANITIZER_TEST_HAS_STAT_H struct stat st1, st2, st3; - EXPECT_EQ(0, internal_stat(temp_filename, &st1)); - EXPECT_EQ(0, internal_lstat(temp_filename, &st2)); - EXPECT_EQ(0, internal_fstat(fd, &st3)); + EXPECT_EQ(0u, internal_stat(temp_filename, &st1)); + EXPECT_EQ(0u, internal_lstat(temp_filename, &st2)); + EXPECT_EQ(0u, internal_fstat(fd, &st3)); EXPECT_EQ(fsize, (uptr)st3.st_size); // Verify that internal_fstat does not write beyond the end of the supplied // buffer. struct stat_and_more sam; memset(&sam, 0xAB, sizeof(sam)); - EXPECT_EQ(0, internal_fstat(fd, &sam.st)); + EXPECT_EQ(0u, internal_fstat(fd, &sam.st)); EXPECT_EQ(0xAB, sam.z); EXPECT_NE(0xAB, sam.st.st_size); EXPECT_NE(0, sam.st.st_size); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index df07ac6383d..5ccdc49d37d 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -178,9 +178,10 @@ static void MapRodata() { char filename[256]; internal_snprintf(filename, sizeof(filename), "%s/tsan.rodata.%u", tmpdir, GetPid()); - fd_t fd = internal_open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd == kInvalidFd) + uptr openrv = internal_open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); + if (internal_iserror(openrv)) return; + fd_t fd = openrv; // Fill the file with kShadowRodata. const uptr kMarkerSize = 512 * 1024 / sizeof(u64); InternalScopedBuffer<u64> marker(kMarkerSize); @@ -188,9 +189,9 @@ static void MapRodata() { *p = kShadowRodata; internal_write(fd, marker.data(), marker.size()); // Map the file into memory. - void *page = internal_mmap(0, kPageSize, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, fd, 0); - if (page == MAP_FAILED) { + uptr page = internal_mmap(0, kPageSize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, fd, 0); + if (internal_iserror(page)) { internal_close(fd); internal_unlink(filename); return; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 1205028e3c3..c51a5669060 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -121,10 +121,12 @@ static void BackgroundThread(void *arg) { InternalScopedBuffer<char> filename(4096); internal_snprintf(filename.data(), filename.size(), "%s.%d", flags()->profile_memory, GetPid()); - mprof_fd = OpenFile(filename.data(), true); - if (mprof_fd == kInvalidFd) { + uptr openrv = OpenFile(filename.data(), true); + if (internal_iserror(openrv)) { Printf("ThreadSanitizer: failed to open memory profile file '%s'\n", &filename[0]); + } else { + mprof_fd = openrv; } } diff --git a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc index 47fe7b2d4f3..14b6a3acacc 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_suppressions.cc @@ -38,12 +38,13 @@ static char *ReadFile(const char *filename) { internal_snprintf(tmp.data(), tmp.size(), "%s", filename); else internal_snprintf(tmp.data(), tmp.size(), "%s/%s", GetPwd(), filename); - fd_t fd = OpenFile(tmp.data(), false); - if (fd == kInvalidFd) { + uptr openrv = OpenFile(tmp.data(), false); + if (internal_iserror(openrv)) { Printf("ThreadSanitizer: failed to open suppressions file '%s'\n", tmp.data()); Die(); } + fd_t fd = openrv; const uptr fsize = internal_filesize(fd); if (fsize == (uptr)-1) { Printf("ThreadSanitizer: failed to stat suppressions file '%s'\n", |