[sanitizer] AArch64 sanitizer support; patch by Christophe Lyon and Yvan Roux

llvm-svn: 201303
This commit is contained in:
Kostya Serebryany 2014-02-13 07:50:20 +00:00
parent 5e52d48e3a
commit c98ce28533
8 changed files with 79 additions and 9 deletions

View File

@ -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];

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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