From c98ce2853355c1a861e0afcd732036e3d16feaa2 Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 13 Feb 2014 07:50:20 +0000 Subject: [PATCH] [sanitizer] AArch64 sanitizer support; patch by Christophe Lyon and Yvan Roux llvm-svn: 201303 --- compiler-rt/lib/asan/asan_linux.cc | 5 +++ compiler-rt/lib/asan/asan_mapping.h | 5 ++- .../lib/sanitizer_common/sanitizer_linux.cc | 40 ++++++++++++++++++- .../lib/sanitizer_common/sanitizer_platform.h | 23 ++++++++++- .../sanitizer_platform_limits_linux.cc | 2 +- .../sanitizer_platform_limits_posix.h | 6 ++- .../lib/sanitizer_common/sanitizer_posix.cc | 2 + .../sanitizer_common/sanitizer_stacktrace.h | 5 ++- 8 files changed, 79 insertions(+), 9 deletions(-) diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc index 042e06ed97ef..4e7ca7e77bde 100644 --- a/compiler-rt/lib/asan/asan_linux.cc +++ b/compiler-rt/lib/asan/asan_linux.cc @@ -57,6 +57,11 @@ void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *pc = ucontext->uc_mcontext.arm_pc; *bp = ucontext->uc_mcontext.arm_fp; *sp = ucontext->uc_mcontext.arm_sp; +# elif defined(__aarch64__) + ucontext_t *ucontext = (ucontext_t*)context; + *pc = ucontext->uc_mcontext.pc; + *bp = ucontext->uc_mcontext.regs[29]; + *sp = ucontext->uc_mcontext.sp; # elif defined(__hppa__) ucontext_t *ucontext = (ucontext_t*)context; *pc = ucontext->uc_mcontext.sc_iaoq[0]; diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index eac717518b29..93fa69accd9a 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -61,6 +61,7 @@ static const u64 kDefaultShadowScale = 3; static const u64 kDefaultShadowOffset32 = 1ULL << 29; static const u64 kDefaultShadowOffset64 = 1ULL << 44; static const u64 kDefaultShort64bitShadowOffset = 0x7FFF8000; // < 2G. +static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; static const u64 kMIPS32_ShadowOffset32 = 0x0aaa8000; #define SHADOW_SCALE kDefaultShadowScale @@ -74,7 +75,9 @@ static const u64 kMIPS32_ShadowOffset32 = 0x0aaa8000; # define SHADOW_OFFSET kDefaultShadowOffset32 # endif # else -# if SANITIZER_MAC +# if defined(__aarch64__) +# define SHADOW_OFFSET kAArch64_ShadowOffset64 +# elif SANITIZER_MAC # define SHADOW_OFFSET kDefaultShadowOffset64 # else # define SHADOW_OFFSET kDefaultShort64bitShadowOffset diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 73a35ca23378..ea50acfcbb10 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -101,11 +101,19 @@ uptr internal_close(fd_t fd) { } uptr internal_open(const char *filename, int flags) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_openat, AT_FDCWD, (uptr)filename, flags); +#else return internal_syscall(__NR_open, (uptr)filename, flags); +#endif } uptr internal_open(const char *filename, int flags, u32 mode) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_openat, AT_FDCWD, (uptr)filename, flags, mode); +#else return internal_syscall(__NR_open, (uptr)filename, flags, mode); +#endif } uptr OpenFile(const char *filename, bool write) { @@ -146,7 +154,9 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) { #endif uptr internal_stat(const char *path, void *buf) { -#if SANITIZER_LINUX_USES_64BIT_SYSCALLS +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_newfstatat, AT_FDCWD, (uptr)path, (uptr)buf, 0); +#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS return internal_syscall(__NR_stat, (uptr)path, (uptr)buf); #else struct stat64 buf64; @@ -157,7 +167,10 @@ uptr internal_stat(const char *path, void *buf) { } uptr internal_lstat(const char *path, void *buf) { -#if SANITIZER_LINUX_USES_64BIT_SYSCALLS +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_newfstatat, AT_FDCWD, (uptr)path, + (uptr)buf, AT_SYMLINK_NOFOLLOW); +#elif SANITIZER_LINUX_USES_64BIT_SYSCALLS return internal_syscall(__NR_lstat, (uptr)path, (uptr)buf); #else struct stat64 buf64; @@ -186,15 +199,28 @@ uptr internal_filesize(fd_t fd) { } uptr internal_dup2(int oldfd, int newfd) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_dup3, oldfd, newfd, 0); +#else return internal_syscall(__NR_dup2, oldfd, newfd); +#endif } uptr internal_readlink(const char *path, char *buf, uptr bufsize) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_readlinkat, AT_FDCWD, + (uptr)path, (uptr)buf, bufsize); +#else return internal_syscall(__NR_readlink, (uptr)path, (uptr)buf, bufsize); +#endif } uptr internal_unlink(const char *path) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_unlinkat, AT_FDCWD, (uptr)path, 0); +#else return internal_syscall(__NR_unlink, (uptr)path); +#endif } uptr internal_sched_yield() { @@ -213,11 +239,17 @@ uptr internal_execve(const char *filename, char *const argv[], // ----------------- sanitizer_common.h bool FileExists(const char *filename) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + struct stat st; + if (internal_syscall(__NR_newfstatat, AT_FDCWD, filename, &st, 0)) + return false; +#else struct stat st; if (internal_stat(filename, &st)) return false; // Sanity check: filename is a regular file. return S_ISREG(st.st_mode); +#endif } uptr GetTid() { @@ -389,7 +421,11 @@ uptr internal_getppid() { } uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS + return internal_syscall(__NR_getdents64, fd, (uptr)dirp, count); +#else return internal_syscall(__NR_getdents, fd, (uptr)dirp, count); +#endif } uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index 27ffaec99c30..c286097f696f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -68,13 +68,32 @@ // For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or // change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here. #ifndef SANITIZER_CAN_USE_ALLOCATOR64 -# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64) +# if defined(__aarch64__) +# define SANITIZER_CAN_USE_ALLOCATOR64 0 +# else +# define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64) +# endif #endif // The range of addresses which can be returned my mmap. // FIXME: this value should be different on different platforms, // e.g. on AArch64 it is most likely (1ULL << 39). Larger values will still work // but will consume more memory for TwoLevelByteMap. -#define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47) +#if defined(__aarch64__) +# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 39) +#else +# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47) +#endif + +// The AArch64 linux port uses the canonical syscall set as mandated by +// the upstream linux community for all new ports. Other ports may still +// use legacy syscalls. +#ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +# ifdef __aarch64__ +# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1 +# else +# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0 +# endif +#endif #endif // SANITIZER_PLATFORM_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc index 54c0809257b6..66c6ab90393c 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_linux.cc @@ -64,7 +64,7 @@ namespace __sanitizer { unsigned struct_statfs64_sz = sizeof(struct statfs64); } // namespace __sanitizer -#if !defined(__powerpc64__) && !defined(__x86_64__) +#if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__) COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat)); #endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h index 744e180d5d0e..b82b4cfb1665 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -63,6 +63,10 @@ namespace __sanitizer { const unsigned struct___old_kernel_stat_sz = 32; const unsigned struct_kernel_stat_sz = 64; const unsigned struct_kernel_stat64_sz = 104; +#elif defined(__aarch64__) + const unsigned struct___old_kernel_stat_sz = 32; + const unsigned struct_kernel_stat_sz = 128; + const unsigned struct_kernel_stat64_sz = 104; #elif defined(__powerpc__) && !defined(__powerpc64__) const unsigned struct___old_kernel_stat_sz = 32; const unsigned struct_kernel_stat_sz = 72; @@ -343,7 +347,7 @@ namespace __sanitizer { typedef long __sanitizer___kernel_off_t; #endif -#if defined(__powerpc__) +#if defined(__powerpc__) || defined(__aarch64__) typedef unsigned int __sanitizer___kernel_old_uid_t; typedef unsigned int __sanitizer___kernel_old_gid_t; #else diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc index df5cbd465864..833b7cf3db76 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_posix.cc @@ -38,6 +38,8 @@ uptr GetMaxVirtualAddress() { // Note that with 'ulimit -s unlimited' the stack is moved away from the top // of the address space, so simply checking the stack address is not enough. return (1ULL << 44) - 1; // 0x00000fffffffffffUL +# elif defined(__aarch64__) + return (1ULL << 39) - 1; # else return (1ULL << 47) - 1; // 0x00007fffffffffffUL; # endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h index 9d067b1c9c8d..c3ba193f45df 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h @@ -19,8 +19,9 @@ namespace __sanitizer { static const uptr kStackTraceMax = 256; -#if SANITIZER_LINUX && (defined(__powerpc__) || defined(__powerpc64__) || \ - defined(__sparc__) || defined(__mips__)) +#if SANITIZER_LINUX && (defined(__aarch64__) || defined(__powerpc__) || \ + defined(__powerpc64__) || defined(__sparc__) || \ + defined(__mips__)) # define SANITIZER_CAN_FAST_UNWIND 0 #elif SANITIZER_WINDOWS # define SANITIZER_CAN_FAST_UNWIND 0