Index: lib/sanitizer_common/sanitizer_internal_defs.h =================================================================== --- lib/sanitizer_common/sanitizer_internal_defs.h +++ lib/sanitizer_common/sanitizer_internal_defs.h @@ -113,8 +113,8 @@ typedef unsigned long uptr; // NOLINT typedef signed long sptr; // NOLINT #endif // defined(_WIN64) -#if defined(__x86_64__) -// Since x32 uses ILP32 data model in 64-bit hardware mode, we must use +#if defined(__x86_64__) || SANITIZER_AARCH64_ILP32 +// Since x32 and ILP32 uses data model in 64-bit hardware mode, we must use // 64-bit pointer to unwind stack frame. typedef unsigned long long uhwptr; // NOLINT #else @@ -140,7 +140,7 @@ typedef int pid_t; #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_MAC || \ - (SANITIZER_LINUX && defined(__x86_64__)) + (SANITIZER_LINUX && (defined(__x86_64__) || SANITIZER_AARCH64_ILP32)) typedef u64 OFF_T; #else typedef uptr OFF_T; @@ -150,8 +150,8 @@ #if (SANITIZER_WORDSIZE == 64) || SANITIZER_MAC typedef uptr operator_new_size_type; #else -# if defined(__s390__) && !defined(__s390x__) -// Special case: 31-bit s390 has unsigned long as size_t. +# if (defined(__s390__) && !defined(__s390x__)) || SANITIZER_AARCH64_ILP32 +// Special case: 31-bit s390 and aarch64 ilp32 have unsigned long as size_t. typedef unsigned long operator_new_size_type; # else typedef u32 operator_new_size_type; Index: lib/sanitizer_common/sanitizer_linux.cc =================================================================== --- lib/sanitizer_common/sanitizer_linux.cc +++ lib/sanitizer_common/sanitizer_linux.cc @@ -114,8 +114,16 @@ #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__powerpc64__) || \ SANITIZER_WORDSIZE == 64) # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1 +# define SYSCALL_LL64(val) (val) #else # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define SYSCALL_LL64(val) \ + (long) ((OFF64_T)(val) & 0xffffffff), (long) ((OFF64_T)(val) >> 32) +# else +# define SYSCALL_LL64(val) \ + (long) ((OFF64_T)val >> 32), (long) ((OFF64_T)(val) & 0xffffffff) +# endif #endif #if defined(__x86_64__) || SANITIZER_MIPS64 @@ -212,8 +220,13 @@ #if SANITIZER_NETBSD HANDLE_EINTR(res, internal_syscall64(SYSCALL(ftruncate), fd, 0, (s64)size)); #else +# if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 2 + HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate64), fd, + SYSCALL_LL64((OFF_T)size))); +# else HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd, (OFF_T)size)); +# endif #endif return res; } @@ -289,9 +302,12 @@ #if SANITIZER_FREEBSD || SANITIZER_NETBSD return internal_syscall_ptr(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); -#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 1 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, 0); +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 2 + return internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path, + (uptr)buf, 0); #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS # if defined(__mips64) // For mips64, stat syscall fills buffer in the format of kernel_stat @@ -316,9 +332,12 @@ #elif SANITIZER_FREEBSD return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); -#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 1 return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path, (uptr)buf, AT_SYMLINK_NOFOLLOW); +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 2 + return internal_syscall(SYSCALL(fstatat64), AT_FDCWD, (uptr)path, + (uptr)buf, AT_SYMLINK_NOFOLLOW); #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS # if SANITIZER_MIPS64 // For mips64, lstat syscall fills buffer in the format of kernel_stat @@ -389,9 +408,12 @@ } uptr internal_rename(const char *oldpath, const char *newpath) { -#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 1 return internal_syscall(SYSCALL(renameat), AT_FDCWD, (uptr)oldpath, AT_FDCWD, (uptr)newpath); +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 2 + return internal_syscall(SYSCALL(renameat2), AT_FDCWD, (uptr)oldpath, AT_FDCWD, + (uptr)newpath, 0); #else return internal_syscall_ptr(SYSCALL(rename), (uptr)oldpath, (uptr)newpath); #endif @@ -428,8 +450,10 @@ // ----------------- sanitizer_common.h bool FileExists(const char *filename) { struct stat st; -#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 1 if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0)) +#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 2 + if (internal_syscall(SYSCALL(fstatat64), AT_FDCWD, filename, &st, 0)) #else if (internal_stat(filename, &st)) #endif @@ -718,7 +742,15 @@ #if SANITIZER_NETBSD return internal_syscall64(SYSCALL(lseek), fd, 0, offset, whence); #else +# if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS == 2 + int64_t res; + int rc = internal_syscall(SYSCALL(llseek), fd, + (long) (((u64)(offset)) >> 32), + (long) offset, &res, whence); + return rc ? rc : res; +# else return internal_syscall(SYSCALL(lseek), fd, offset, whence); +# endif #endif } @@ -1634,9 +1666,24 @@ uint64_t esr; }; +// glibc starting at 2.26 does not typedef sigcontext to mcontext_t, +// but rather defines its own with internal reserved member with +// different naming. The mcontext_t definition below is based on +// Linux UAPI for sicontex_t. +struct __sanitizer_mcontext_t { + unsigned long long int fault_address; + unsigned long long int regs[31]; + unsigned long long int pc; + unsigned long long int sp; + unsigned long long int pstate; + unsigned char reserved[4096] __attribute__ ((__aligned__ (16))); // NOLINT +}; + static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { static const u32 kEsrMagic = 0x45535201; - u8 *aux = ucontext->uc_mcontext.__reserved; + __sanitizer_mcontext_t *mctx = reinterpret_cast<__sanitizer_mcontext_t *> + (&ucontext->uc_mcontext); + u8 *aux = mctx->reserved; while (true) { _aarch64_ctx *ctx = (_aarch64_ctx *)aux; if (ctx->size == 0) break; Index: lib/sanitizer_common/sanitizer_platform.h =================================================================== --- lib/sanitizer_common/sanitizer_platform.h +++ lib/sanitizer_common/sanitizer_platform.h @@ -181,6 +181,12 @@ # define SANITIZER_ARM 0 #endif +#if defined(__aarch64__) && defined(__ILP32__) +# define SANITIZER_AARCH64_ILP32 1 +#else +# define SANITIZER_AARCH64_ILP32 0 +#endif + // By default we allow to use SizeClassAllocator64 on 64-bit platform. // But in some cases (e.g. AArch64's 39-bit address space) SizeClassAllocator64 // does not work well and we need to fallback to SizeClassAllocator32. @@ -209,10 +215,15 @@ // 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. +// use legacy syscalls. Also AArch64 ILP32 uses canonical syscall set +// 32 bits ports. #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS # if defined(__aarch64__) && SANITIZER_LINUX -# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1 +# if defined(__ILP32__) +# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 2 +# else +# define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1 +# endif # else # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0 # endif Index: lib/sanitizer_common/sanitizer_platform_limits_posix.h =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_posix.h +++ lib/sanitizer_common/sanitizer_platform_limits_posix.h @@ -76,7 +76,10 @@ #elif defined(__arm__) const unsigned struct_kernel_stat_sz = 64; const unsigned struct_kernel_stat64_sz = 104; -#elif defined(__aarch64__) +#elif defined(__aarch64__) && defined(__ILP32__) + const unsigned struct_kernel_stat_sz = 80; + const unsigned struct_kernel_stat64_sz = 104; +#elif defined(__aarch64__) && defined(__LP64__) const unsigned struct_kernel_stat_sz = 128; const unsigned struct_kernel_stat64_sz = 104; #elif defined(__powerpc__) && !defined(__powerpc64__) @@ -508,8 +511,13 @@ }; #else struct __sanitizer_dirent { +# if SANITIZER_AARCH64_ILP32 + unsigned long long d_ino; + unsigned long long d_off; +# else uptr d_ino; uptr d_off; +# endif unsigned short d_reclen; // more fields that we don't care about }; @@ -539,7 +547,8 @@ #if SANITIZER_LINUX || SANITIZER_FREEBSD #if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__)\ - || defined(__mips__) + || defined(__mips__)\ + || (defined(__aarch64__) && defined(__ILP32__)) typedef unsigned __sanitizer___kernel_uid_t; typedef unsigned __sanitizer___kernel_gid_t; #else Index: lib/sanitizer_common/sanitizer_platform_limits_posix.cc =================================================================== --- lib/sanitizer_common/sanitizer_platform_limits_posix.cc +++ lib/sanitizer_common/sanitizer_platform_limits_posix.cc @@ -1139,7 +1139,8 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, gid); CHECK_SIZE_AND_OFFSET(ipc_perm, cuid); CHECK_SIZE_AND_OFFSET(ipc_perm, cgid); -#if !defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21) +#if !defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21) \ + && !defined(__ILP32__) /* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */ CHECK_SIZE_AND_OFFSET(ipc_perm, mode); #endif