From df516f16c04a4806fde50fefc45f9d4c518d6872 Mon Sep 17 00:00:00 2001 From: swcompiler Date: Mon, 25 Nov 2024 17:14:17 +0800 Subject: [PATCH 15/16] Sw64 Port: libsanitizer --- libsanitizer/asan/asan_allocator.h | 5 + libsanitizer/asan/asan_mapping.h | 3 + libsanitizer/configure.tgt | 4 + libsanitizer/lsan/lsan_allocator.cpp | 2 +- libsanitizer/lsan/lsan_allocator.h | 3 +- libsanitizer/lsan/lsan_common.cpp | 2 + libsanitizer/lsan/lsan_common.h | 2 +- .../sanitizer_common_interceptors.inc | 77 ++++-- .../sanitizer_common_syscalls.inc | 4 +- .../sanitizer_common/sanitizer_linux.cpp | 131 +++++++++- .../sanitizer_common/sanitizer_linux.h | 2 +- .../sanitizer_linux_libcdep.cpp | 6 +- .../sanitizer_common/sanitizer_platform.h | 8 + .../sanitizer_platform_interceptors.h | 6 +- .../sanitizer_platform_limits_linux.cpp | 2 +- .../sanitizer_platform_limits_posix.cpp | 16 +- .../sanitizer_platform_limits_posix.h | 24 +- .../sanitizer_common/sanitizer_stacktrace.h | 2 + .../sanitizer_stoptheworld_linux_libcdep.cpp | 8 +- .../sanitizer_symbolizer_libcdep.cpp | 2 + libsanitizer/tsan/Makefile.am | 2 +- libsanitizer/tsan/Makefile.in | 2 +- libsanitizer/tsan/tsan_interceptors_posix.cpp | 14 +- libsanitizer/tsan/tsan_platform.h | 41 +++ libsanitizer/tsan/tsan_platform_linux.cpp | 4 + libsanitizer/tsan/tsan_rtl.h | 2 +- libsanitizer/tsan/tsan_rtl_sw64.S | 236 ++++++++++++++++++ 27 files changed, 550 insertions(+), 60 deletions(-) create mode 100644 libsanitizer/tsan/tsan_rtl_sw64.S diff --git a/libsanitizer/asan/asan_allocator.h b/libsanitizer/asan/asan_allocator.h index 27d826fb6..8b7b22db6 100644 --- a/libsanitizer/asan/asan_allocator.h +++ b/libsanitizer/asan/asan_allocator.h @@ -149,6 +149,11 @@ typedef DefaultSizeClassMap SizeClassMap; const uptr kAllocatorSpace = ~(uptr)0; const uptr kAllocatorSize = 0x8000000000ULL; // 500G typedef DefaultSizeClassMap SizeClassMap; +# elif SANITIZER_SW64 +// If kSpaceBeg is ~0 then SpaceBeg is chosen dynamically my mmap. +const uptr kAllocatorSpace = ~(uptr)0; +const uptr kAllocatorSize = 0x40000000000ULL; // 4T. +typedef DefaultSizeClassMap SizeClassMap; # else const uptr kAllocatorSpace = 0x600000000000ULL; const uptr kAllocatorSize = 0x40000000000ULL; // 4T. diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h index 4b0037fce..3b752d81d 100644 --- a/libsanitizer/asan/asan_mapping.h +++ b/libsanitizer/asan/asan_mapping.h @@ -165,6 +165,7 @@ static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; static const u64 kRiscv64_ShadowOffset64 = 0xd55550000; static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; +static const u64 kSW64_ShadowOffset64 = 1ULL << 49; static const u64 kPPC64_ShadowOffset64 = 1ULL << 41; static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52; static const u64 kSPARC64_ShadowOffset64 = 1ULL << 43; // 0x80000000000 @@ -205,6 +206,8 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 # define SHADOW_OFFSET kAArch64_ShadowOffset64 # elif defined(__powerpc64__) # define SHADOW_OFFSET kPPC64_ShadowOffset64 +# elif defined(__sw_64__) +# define SHADOW_OFFSET kSW64_ShadowOffset64 # elif defined(__s390x__) # define SHADOW_OFFSET kSystemZ_ShadowOffset64 # elif SANITIZER_FREEBSD diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt index fb89df493..f62e59ef8 100644 --- a/libsanitizer/configure.tgt +++ b/libsanitizer/configure.tgt @@ -54,6 +54,10 @@ case "${target}" in ;; arm*-*-linux*) ;; + sw_64*-*-linux*) + TSAN_SUPPORTED=yes + LSAN_SUPPORTED=yes + ;; mips*-*-linux*) ;; aarch64*-*-linux*) diff --git a/libsanitizer/lsan/lsan_allocator.cpp b/libsanitizer/lsan/lsan_allocator.cpp index 91e34ebb3..9895719fd 100644 --- a/libsanitizer/lsan/lsan_allocator.cpp +++ b/libsanitizer/lsan/lsan_allocator.cpp @@ -28,7 +28,7 @@ extern "C" void *memset(void *ptr, int value, uptr num); namespace __lsan { #if defined(__i386__) || defined(__arm__) static const uptr kMaxAllowedMallocSize = 1UL << 30; -#elif defined(__mips64) || defined(__aarch64__) +#elif defined(__mips64) || defined(__aarch64__) || defined(__sw_64__) static const uptr kMaxAllowedMallocSize = 4UL << 30; #else static const uptr kMaxAllowedMallocSize = 8UL << 30; diff --git a/libsanitizer/lsan/lsan_allocator.h b/libsanitizer/lsan/lsan_allocator.h index 45c6ac406..a6ca2b250 100644 --- a/libsanitizer/lsan/lsan_allocator.h +++ b/libsanitizer/lsan/lsan_allocator.h @@ -50,7 +50,8 @@ struct ChunkMetadata { }; #if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \ - defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__) + defined(__arm__) || SANITIZER_RISCV64 || defined(__hexagon__) || \ + defined(__sw_64__) template struct AP32 { static const uptr kSpaceBeg = 0; diff --git a/libsanitizer/lsan/lsan_common.cpp b/libsanitizer/lsan/lsan_common.cpp index 308dbb3e4..16b664b14 100644 --- a/libsanitizer/lsan/lsan_common.cpp +++ b/libsanitizer/lsan/lsan_common.cpp @@ -163,6 +163,8 @@ static inline bool CanBeAHeapPointer(uptr p) { return ((p >> 47) == 0); #elif defined(__mips64) return ((p >> 40) == 0); +#elif defined(__sw_64__) + return ((p >> 52) == 0); #elif defined(__aarch64__) unsigned runtimeVMA = (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); diff --git a/libsanitizer/lsan/lsan_common.h b/libsanitizer/lsan/lsan_common.h index f9b55e4e8..6afff378c 100644 --- a/libsanitizer/lsan/lsan_common.h +++ b/libsanitizer/lsan/lsan_common.h @@ -36,7 +36,7 @@ #define CAN_SANITIZE_LEAKS 0 #elif (SANITIZER_LINUX || SANITIZER_MAC) && (SANITIZER_WORDSIZE == 64) && \ (defined(__x86_64__) || defined(__mips64) || defined(__aarch64__) || \ - defined(__powerpc64__) || defined(__s390x__)) + defined(__powerpc64__) || defined(__s390x__) || defined(__sw_64__)) #define CAN_SANITIZE_LEAKS 1 #elif defined(__i386__) && (SANITIZER_LINUX || SANITIZER_MAC) #define CAN_SANITIZE_LEAKS 1 diff --git a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc index abb38ccfa..2b6a7d612 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc @@ -1532,6 +1532,16 @@ VSCANF_INTERCEPTOR_IMPL(__isoc99_vsscanf, false, str, format, ap) INTERCEPTOR(int, __isoc99_vfscanf, void *stream, const char *format, va_list ap) VSCANF_INTERCEPTOR_IMPL(__isoc99_vfscanf, false, stream, format, ap) + +INTERCEPTOR(int, __isoc23_vscanf, const char *format, va_list ap) +VSCANF_INTERCEPTOR_IMPL(__isoc23_vscanf, false, format, ap) + +INTERCEPTOR(int, __isoc23_vsscanf, const char *str, const char *format, + va_list ap) +VSCANF_INTERCEPTOR_IMPL(__isoc23_vsscanf, false, str, format, ap) + +INTERCEPTOR(int, __isoc23_vfscanf, void *stream, const char *format, va_list ap) +VSCANF_INTERCEPTOR_IMPL(__isoc23_vfscanf, false, stream, format, ap) #endif // SANITIZER_INTERCEPT_ISOC99_SCANF INTERCEPTOR(int, scanf, const char *format, ...) @@ -1552,6 +1562,15 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_fscanf, __isoc99_vfscanf, stream, format) INTERCEPTOR(int, __isoc99_sscanf, const char *str, const char *format, ...) FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) + +INTERCEPTOR(int, __isoc23_scanf, const char *format, ...) +FORMAT_INTERCEPTOR_IMPL(__isoc23_scanf, __isoc23_vscanf, format) + +INTERCEPTOR(int, __isoc23_fscanf, void *stream, const char *format, ...) +FORMAT_INTERCEPTOR_IMPL(__isoc23_fscanf, __isoc23_vfscanf, stream, format) + +INTERCEPTOR(int, __isoc23_sscanf, const char *str, const char *format, ...) +FORMAT_INTERCEPTOR_IMPL(__isoc23_sscanf, __isoc23_vsscanf, str, format) #endif #endif @@ -1575,7 +1594,13 @@ FORMAT_INTERCEPTOR_IMPL(__isoc99_sscanf, __isoc99_vsscanf, str, format) COMMON_INTERCEPT_FUNCTION(__isoc99_fscanf); \ COMMON_INTERCEPT_FUNCTION(__isoc99_vscanf); \ COMMON_INTERCEPT_FUNCTION(__isoc99_vsscanf); \ - COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); + COMMON_INTERCEPT_FUNCTION(__isoc99_vfscanf); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_scanf); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_sscanf); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_fscanf); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_vscanf); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_vsscanf); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_vfscanf); #else #define INIT_ISOC99_SCANF #endif @@ -3502,30 +3527,26 @@ UNUSED static inline void StrtolFixAndCheck(void *ctx, const char *nptr, (real_endptr - nptr) + 1 : 0); } - #if SANITIZER_INTERCEPT_STRTOIMAX -INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base); - // FIXME: under ASan the call below may write to freed memory and corrupt - // its metadata. See - // https://github.com/google/sanitizers/issues/321. +template +static ALWAYS_INLINE auto StrtoimaxImpl(void *ctx, Fn real, const char *nptr, + char **endptr, int base) + -> decltype(real(nullptr, nullptr, 0)) { char *real_endptr; - INTMAX_T res = REAL(strtoimax)(nptr, &real_endptr, base); + auto res = real(nptr, &real_endptr, base); StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); return res; } +INTERCEPTOR(INTMAX_T, strtoimax, const char *nptr, char **endptr, int base) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, strtoimax, nptr, endptr, base); + return StrtoimaxImpl(ctx, REAL(strtoimax), nptr, endptr, base); +} INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, strtoumax, nptr, endptr, base); - // FIXME: under ASan the call below may write to freed memory and corrupt - // its metadata. See - // https://github.com/google/sanitizers/issues/321. - char *real_endptr; - UINTMAX_T res = REAL(strtoumax)(nptr, &real_endptr, base); - StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); - return res; + return StrtoimaxImpl(ctx, REAL(strtoumax), nptr, endptr, base); } #define INIT_STRTOIMAX \ @@ -3535,6 +3556,25 @@ INTERCEPTOR(UINTMAX_T, strtoumax, const char *nptr, char **endptr, int base) { #define INIT_STRTOIMAX #endif +#if SANITIZER_INTERCEPT_STRTOIMAX && SANITIZER_GLIBC +INTERCEPTOR(INTMAX_T, __isoc23_strtoimax, const char *nptr, char **endptr, int base) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoimax, nptr, endptr, base); + return StrtoimaxImpl(ctx, REAL(__isoc23_strtoimax), nptr, endptr, base); +} +INTERCEPTOR(UINTMAX_T, __isoc23_strtoumax, const char *nptr, char **endptr, int base) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, __isoc23_strtoumax, nptr, endptr, base); + return StrtoimaxImpl(ctx, REAL(__isoc23_strtoumax), nptr, endptr, base); +} + +# define INIT_STRTOIMAX_C23 \ + COMMON_INTERCEPT_FUNCTION(__isoc23_strtoimax); \ + COMMON_INTERCEPT_FUNCTION(__isoc23_strtoumax); +#else +# define INIT_STRTOIMAX_C23 +#endif + #if SANITIZER_INTERCEPT_MBSTOWCS INTERCEPTOR(SIZE_T, mbstowcs, wchar_t *dest, const char *src, SIZE_T len) { void *ctx; @@ -4708,7 +4748,11 @@ INTERCEPTOR(int, shmctl, int shmid, int cmd, void *buf) { } return res; } +#ifdef SANITIZER_SW64 +#define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION_VER(shmctl, "GLIBC_2.2"); +#else #define INIT_SHMCTL COMMON_INTERCEPT_FUNCTION(shmctl); +#endif #else #define INIT_SHMCTL #endif @@ -10325,6 +10369,7 @@ static void InitializeCommonInterceptors() { INIT_GETCWD; INIT_GET_CURRENT_DIR_NAME; INIT_STRTOIMAX; + INIT_STRTOIMAX_C23; INIT_MBSTOWCS; INIT_MBSNRTOWCS; INIT_WCSTOMBS; diff --git a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc index a38b13408..fd4e1e3b6 100644 --- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc +++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc @@ -2512,7 +2512,7 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { # if !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ - SANITIZER_RISCV64) + defined(__sw_64__) || SANITIZER_RISCV64) if (data) { if (request == ptrace_setregs) { PRE_READ((void *)data, struct_user_regs_struct_sz); @@ -2534,7 +2534,7 @@ POST_SYSCALL(ptrace)(long res, long request, long pid, long addr, long data) { # if !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ - SANITIZER_RISCV64) + defined(__sw_64__) || SANITIZER_RISCV64) if (res >= 0 && data) { // Note that this is different from the interceptor in // sanitizer_common_interceptors.inc. diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cpp b/libsanitizer/sanitizer_common/sanitizer_linux.cpp index aa59d9718..711079d86 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_linux.cpp @@ -50,6 +50,16 @@ #undef stat #endif +#if defined(__sw_64__) +#define stat kernel_stat +#define stat64 kernel_stat64 +#include +#undef stat +#undef stat64 +#include +#include +#endif + #include #include #include @@ -282,7 +292,7 @@ static void stat64_to_stat(struct stat64 *in, struct stat *out) { } #endif -#if defined(__mips64) +#if defined(__mips64) || defined(__sw_64__) // Undefine compatibility macros from // so that they would not clash with the kernel_stat // st_[a|m|c]time fields @@ -312,6 +322,12 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { out->st_size = in->st_size; out->st_blksize = in->st_blksize; out->st_blocks = in->st_blocks; +#if defined(__sw_64__) + // There's no nsecs in sw_64's struct stat + out->st_atim.tv_sec = in->st_atime; + out->st_mtim.tv_sec = in->st_mtime; + out->st_ctim.tv_sec = in->st_ctime; +#else #if defined(__USE_MISC) || \ defined(__USE_XOPEN2K8) || \ defined(SANITIZER_ANDROID) @@ -329,6 +345,7 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { out->st_ctime = in->st_ctime; out->st_atimensec = in->st_ctime_nsec; #endif +#endif } #endif @@ -339,8 +356,8 @@ uptr internal_stat(const char *path, void *buf) { return internal_syscall(SYSCALL(newfstatat), 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 +# if defined(__mips64) || defined(__sw_64__) + // For mips64 and sw_64, stat syscall fills buffer in the format of kernel_stat struct kernel_stat kbuf; int res = internal_syscall(SYSCALL(stat), path, &kbuf); kernel_stat_to_stat(&kbuf, (struct stat *)buf); @@ -364,8 +381,8 @@ uptr internal_lstat(const char *path, void *buf) { return internal_syscall(SYSCALL(newfstatat), 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 +# if SANITIZER_MIPS64 || SANITIZER_SW64 + // For mips64 and sw_64, lstat syscall fills buffer in the format of kernel_stat struct kernel_stat kbuf; int res = internal_syscall(SYSCALL(lstat), path, &kbuf); kernel_stat_to_stat(&kbuf, (struct stat *)buf); @@ -383,8 +400,8 @@ uptr internal_lstat(const char *path, void *buf) { uptr internal_fstat(fd_t fd, void *buf) { #if SANITIZER_FREEBSD || SANITIZER_LINUX_USES_64BIT_SYSCALLS -#if SANITIZER_MIPS64 - // For mips64, fstat syscall fills buffer in the format of kernel_stat +#if (SANITIZER_MIPS64 || SANITIZER_SW64) + // For mips64 and sw_64, fstat syscall fills buffer in the format of kernel_stat struct kernel_stat kbuf; int res = internal_syscall(SYSCALL(fstat), fd, &kbuf); kernel_stat_to_stat(&kbuf, (struct stat *)buf); @@ -718,6 +735,19 @@ uptr internal_waitpid(int pid, int *status, int options) { 0 /* rusage */); } +#ifdef __sw_64__ +uptr internal_getpid() { + return internal_syscall(SYSCALL(getxpid)); +} + +uptr internal_getppid() { + uptr ppid; + internal_syscall(SYSCALL(getxpid)); + asm("mov $20, %0\n" + :"=r"(ppid)); + return ppid; +} +#else uptr internal_getpid() { return internal_syscall(SYSCALL(getpid)); } @@ -725,6 +755,7 @@ uptr internal_getpid() { uptr internal_getppid() { return internal_syscall(SYSCALL(getppid)); } +#endif int internal_dlinfo(void *handle, int request, void *p) { #if SANITIZER_FREEBSD @@ -759,7 +790,7 @@ uptr internal_sigaltstack(const void *ss, void *oss) { } int internal_fork() { -#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS || SANITIZER_SW64 return internal_syscall(SYSCALL(clone), SIGCHLD, 0); #else return internal_syscall(SYSCALL(fork)); @@ -826,7 +857,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { // rt_sigaction, so we need to do the same (we'll need to reimplement the // restorers; for x86_64 the restorer address can be obtained from // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact). -#if !SANITIZER_ANDROID || !SANITIZER_MIPS32 +#if ( !SANITIZER_ANDROID || !SANITIZER_MIPS32 ) && !SANITIZER_SW64 k_act.sa_restorer = u_act->sa_restorer; #endif } @@ -842,7 +873,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask, sizeof(__sanitizer_kernel_sigset_t)); u_oldact->sa_flags = k_oldact.sa_flags; -#if !SANITIZER_ANDROID || !SANITIZER_MIPS32 +#if ( !SANITIZER_ANDROID || !SANITIZER_MIPS32 ) && !SANITIZER_SW64 u_oldact->sa_restorer = k_oldact.sa_restorer; #endif } @@ -1045,6 +1076,11 @@ uptr GetMaxVirtualAddress() { return (1ULL << 38) - 1; # elif defined(__mips64) return (1ULL << 40) - 1; // 0x000000ffffffffffUL; +# elif defined(__sw_64__) +// SW64 has a 42-bit user address space(4TiB) +// according to TASK_SIZE in kernel. +// In sw6b PGTABLE is SW_4LEVEL. + return (1ULL << 52) - 1; // 0x000fffffffffffffUL; # elif defined(__s390x__) return (1ULL << 53) - 1; // 0x001fffffffffffffUL; #elif defined(__sparc__) @@ -1377,6 +1413,71 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, : "memory"); return res; } +#elif defined(__sw_64__) +uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + int *parent_tidptr, void *newtls, int *child_tidptr) { + long long res; + if (!fn || !child_stack) + return -EINVAL; + child_stack = (char *)child_stack - 4 * sizeof(unsigned long long); + ((unsigned long long *)child_stack)[0] = (uptr)fn; + ((unsigned long long *)child_stack)[1] = (uptr)arg; + ((unsigned long long *)child_stack)[2] = (uptr)flags; + + register void *r20 __asm__("$20") = newtls; + register int *r22 __asm__("$22") = child_tidptr; + + __asm__ __volatile__( + /* $v0 = syscall($v0 = __NR_clone, + * $a0 = flags, + * $a1 = child_stack, + * $a2 = parent_tidptr, + * $a3 = child_tidptr, + * $a4 = new_tls) + */ + "mov %[flag],$16\n" + "mov %[usp],$17\n" + "mov %[ptid],$18\n" + "ldl $19,0($sp)\n" + "mov %5,$20\n" + /* Store the fifth argument on stack + * if we are using 32-bit abi. + */ + "ldi $0,%[NR_clone];\n" + "sys_call 0x83;\n" + + /* if ($v0 != 0) + * return; + */ + "bne $0,1f;\n" + "mov $31,$15;\n" + /* Call "fn(arg)". */ + "ldl $27,0($sp);\n" + "ldl $16,8($sp);\n" + "ldi $sp,32($sp);\n" + + "call $26,($27),0;\n" + "ldgp $29, 0($26);\n" + + /* Call _exit($v0). */ + "mov $0,$16;\n" + "ldi $0,%[NR_exit];\n" + "sys_call 0x83;\n" + + /* Return to parent. */ + "1:\n" + : "=r" (res) + : [flag]"r"(flags), + [usp]"r"(child_stack), + [ptid]"r"(parent_tidptr), + "r"(r20), + "r"(r22), + [NR_clone]"i"(__NR_clone), + [NR_exit]"i"(__NR_exit) + : "memory", "$30"); + + return res; +} #elif defined(__aarch64__) uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr) { @@ -2026,6 +2127,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *pc = ucontext->uc_mcontext.pc; *bp = ucontext->uc_mcontext.regs[29]; *sp = ucontext->uc_mcontext.sp; +#elif defined(__sw_64__) + ucontext_t *ucontext = (ucontext_t*)context; + *pc = ucontext->uc_mcontext.sc_pc; + *bp = ucontext->uc_mcontext.sc_regs[15]; + *sp = ucontext->uc_mcontext.sc_regs[30]; #elif defined(__hppa__) ucontext_t *ucontext = (ucontext_t*)context; *pc = ucontext->uc_mcontext.sc_iaoq[0]; @@ -2103,6 +2209,11 @@ static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { *pc = ucontext->uc_mcontext.pc; *bp = ucontext->uc_mcontext.gregs[30]; *sp = ucontext->uc_mcontext.gregs[29]; +#elif defined(__sw_64__) + ucontext_t *ucontext = (ucontext_t*)context; + *pc = ucontext->uc_mcontext.sc_pc; + *bp = ucontext->uc_mcontext.sc_regs[15]; + *sp = ucontext->uc_mcontext.sc_regs[30]; #elif defined(__s390__) ucontext_t *ucontext = (ucontext_t*)context; # if defined(__s390x__) diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.h b/libsanitizer/sanitizer_common/sanitizer_linux.h index 6a235db0e..a5d18e73d 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux.h +++ b/libsanitizer/sanitizer_common/sanitizer_linux.h @@ -73,7 +73,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact); void internal_sigdelset(__sanitizer_sigset_t *set, int signum); #if defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ - defined(__arm__) || SANITIZER_RISCV64 + defined(__arm__) || defined(__sw_64__) || SANITIZER_RISCV64 uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr); #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp index 4f22c78a1..ef8ab755f 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cpp @@ -203,7 +203,7 @@ void InitTlsSize() { g_use_dlpi_tls_data = GetLibcVersion(&major, &minor, &patch) && major == 2 && minor >= 25; -#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) +#if defined(__aarch64__) || defined(__x86_64__) || defined(__powerpc64__) || defined(__sw_64__) void *get_tls_static_info = dlsym(RTLD_NEXT, "_dl_get_tls_static_info"); size_t tls_align; ((void (*)(size_t *, size_t *))get_tls_static_info)(&g_tls_size, &tls_align); @@ -282,6 +282,8 @@ static uptr ThreadDescriptorSizeFallback() { val = 1776; #elif defined(__powerpc64__) val = 1776; // from glibc.ppc64le 2.20-8.fc21 +#elif defined(__sw_64__) + val = 1776; #endif return val; } @@ -471,7 +473,7 @@ static void GetTls(uptr *addr, uptr *size) { *size = g_tls_size; *addr -= *size; *addr += ThreadDescriptorSize(); -#elif SANITIZER_GLIBC && defined(__aarch64__) +#elif SANITIZER_GLIBC && (defined(__aarch64__) || defined(__sw_64__)) *addr = reinterpret_cast(__builtin_thread_pointer()) - ThreadDescriptorSize(); *size = g_tls_size + ThreadDescriptorSize(); diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h index 3153de34e..5cec9a7c0 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform.h @@ -159,6 +159,12 @@ # define SANITIZER_MIPS64 0 #endif +#if defined(__sw_64__) +# define SANITIZER_SW64 1 +#else +# define SANITIZER_SW64 0 +#endif + #if defined(__s390__) # define SANITIZER_S390 1 # if defined(__s390x__) @@ -264,6 +270,8 @@ # endif #elif defined(__sparc__) #define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 52) +#elif defined(__sw_64__) +# define SANITIZER_MMAP_RANGE_SIZE 1ULL << 52 #else # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47) #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h index 14610f2df..03cdf0a07 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h @@ -234,7 +234,11 @@ #define SANITIZER_INTERCEPT_GETITIMER SI_POSIX #define SANITIZER_INTERCEPT_TIME SI_POSIX #define SANITIZER_INTERCEPT_GLOB (SI_GLIBC || SI_SOLARIS) +#if SANITIZER_SW64 +#define SANITIZER_INTERCEPT_GLOB64 0 +#else #define SANITIZER_INTERCEPT_GLOB64 SI_GLIBC +#endif #define SANITIZER_INTERCEPT_POSIX_SPAWN SI_POSIX #define SANITIZER_INTERCEPT_WAIT SI_POSIX #define SANITIZER_INTERCEPT_INET SI_POSIX @@ -271,7 +275,7 @@ #if SI_LINUX_NOT_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ - defined(__s390__) || SANITIZER_RISCV64) + defined(__s390__) || defined(__sw_64__) || SANITIZER_RISCV64) #define SANITIZER_INTERCEPT_PTRACE 1 #else #define SANITIZER_INTERCEPT_PTRACE 0 diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp index 2b1a2f793..e7b20605f 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cpp @@ -68,7 +68,7 @@ namespace __sanitizer { # if !defined(__powerpc64__) && !defined(__x86_64__) && \ !defined(__aarch64__) && !defined(__mips__) && !defined(__s390__) && \ - !defined(__sparc__) && !defined(__riscv) && !defined(__hexagon__) + !defined(__sparc__) && !defined(__riscv) && !defined(__hexagon__) && !defined(__sw_64__) COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat)); #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp index c335f33dd..c96d9b043 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp @@ -94,7 +94,7 @@ # include # include # if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \ - defined(__hexagon__) || SANITIZER_RISCV64 + defined(__hexagon__) || defined(__sw_64__) || SANITIZER_RISCV64 # include # ifdef __arm__ typedef struct user_fpregs elf_fpregset_t; @@ -141,7 +141,7 @@ typedef struct user_fpregs elf_fpregset_t; #include #include #include -#if defined(__mips64) +#if defined(__mips64) || defined(__sw_64__) // for elf_gregset_t # include #endif #include @@ -242,7 +242,7 @@ namespace __sanitizer { // has been removed from glibc 2.28. #if defined(__aarch64__) || defined(__s390x__) || defined(__mips64) || \ defined(__powerpc64__) || defined(__arch64__) || defined(__sparcv9) || \ - defined(__x86_64__) || SANITIZER_RISCV64 + defined(__x86_64__) || SANITIZER_RISCV64 || defined(__sw_64__) #define SIZEOF_STRUCT_USTAT 32 # elif defined(__arm__) || defined(__i386__) || defined(__mips__) || \ defined(__powerpc__) || defined(__s390__) || defined(__sparc__) || \ @@ -322,14 +322,14 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ - defined(__s390__) || SANITIZER_RISCV64) + defined(__s390__) || SANITIZER_RISCV64 || defined(__sw_64__)) #if defined(__mips64) || defined(__powerpc64__) || defined(__arm__) unsigned struct_user_regs_struct_sz = sizeof(struct pt_regs); unsigned struct_user_fpregs_struct_sz = sizeof(elf_fpregset_t); #elif SANITIZER_RISCV64 unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct); unsigned struct_user_fpregs_struct_sz = sizeof(struct __riscv_q_ext_state); -#elif defined(__aarch64__) +#elif defined(__aarch64__) || defined(__sw_64__) unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs); unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state); #elif defined(__s390__) @@ -341,12 +341,12 @@ unsigned struct_ElfW_Phdr_sz = sizeof(Elf_Phdr); #endif // __mips64 || __powerpc64__ || __aarch64__ #if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \ defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \ - SANITIZER_RISCV64 + defined(__sw_64__) || SANITIZER_RISCV64 unsigned struct_user_fpxregs_struct_sz = 0; #else unsigned struct_user_fpxregs_struct_sz = sizeof(struct user_fpxregs_struct); #endif // __x86_64 || __mips64 || __powerpc64__ || __aarch64__ || __arm__ -// || __s390__ +// || __s390__ || __sw_64__ #ifdef __arm__ unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; #else @@ -1080,7 +1080,7 @@ CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_mask); // didn't exist. CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_flags); #endif -#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32) +#if SANITIZER_LINUX && (!SANITIZER_ANDROID || !SANITIZER_MIPS32) && !SANITIZER_SW64 CHECK_STRUCT_SIZE_AND_OFFSET(sigaction, sa_restorer); #endif diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h index da53b5abe..524a6b942 100644 --- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h +++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h @@ -74,6 +74,9 @@ const unsigned struct_kernel_stat64_sz = 104; #elif defined(__aarch64__) const unsigned struct_kernel_stat_sz = 128; const unsigned struct_kernel_stat64_sz = 104; +#elif defined(__sw_64__) +const unsigned struct_kernel_stat_sz = 80; +const unsigned struct_kernel_stat64_sz = 136; #elif defined(__powerpc__) && !defined(__powerpc64__) const unsigned struct_kernel_stat_sz = 72; const unsigned struct_kernel_stat64_sz = 104; @@ -105,7 +108,10 @@ const unsigned struct_kernel_stat64_sz = 0; // RISCV64 does not use stat64 # elif defined(__hexagon__) const unsigned struct_kernel_stat_sz = 128; const unsigned struct_kernel_stat64_sz = 0; -# endif +#elif defined(__sw_64__) +const unsigned struct_kernel_stat_sz = 80; +const unsigned struct_kernel_stat64_sz = 136; +#endif struct __sanitizer_perf_event_attr { unsigned type; unsigned size; @@ -263,15 +269,15 @@ struct __sanitizer_shmid_ds { u64 shm_ctime; #else uptr shm_atime; -#if !defined(_LP64) && !defined(__mips__) +#if !defined(_LP64) && !defined(__mips__) && !defined(__sw_64__) uptr __unused1; #endif uptr shm_dtime; -#if !defined(_LP64) && !defined(__mips__) +#if !defined(_LP64) && !defined(__mips__) && !defined(__sw_64__) uptr __unused2; #endif uptr shm_ctime; -#if !defined(_LP64) && !defined(__mips__) +#if !defined(_LP64) && !defined(__mips__) && !defined(__sw_64__) uptr __unused3; #endif #endif @@ -515,7 +521,7 @@ typedef int __sanitizer_clockid_t; #if SANITIZER_LINUX # if defined(_LP64) || defined(__x86_64__) || defined(__powerpc__) || \ - defined(__mips__) || defined(__hexagon__) + defined(__mips__) || defined(__hexagon__) && !defined(__sw_64__) typedef unsigned __sanitizer___kernel_uid_t; typedef unsigned __sanitizer___kernel_gid_t; #else @@ -528,7 +534,7 @@ typedef long long __sanitizer___kernel_off_t; typedef long __sanitizer___kernel_off_t; #endif -#if defined(__powerpc__) || defined(__mips__) +#if defined(__powerpc__) || defined(__mips__) && !defined(__sw_64__) typedef unsigned int __sanitizer___kernel_old_uid_t; typedef unsigned int __sanitizer___kernel_old_gid_t; #else @@ -640,7 +646,7 @@ struct __sanitizer_sigaction { #endif #endif #endif -#if SANITIZER_LINUX +#if SANITIZER_LINUX && !defined(__sw_64__) void (*sa_restorer)(); #endif #if defined(__mips__) && (SANITIZER_WORDSIZE == 32) @@ -820,7 +826,7 @@ typedef void __sanitizer_FILE; #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ - defined(__s390__) || SANITIZER_RISCV64) + defined(__s390__) || defined(__sw_64__) || SANITIZER_RISCV64) extern unsigned struct_user_regs_struct_sz; extern unsigned struct_user_fpregs_struct_sz; extern unsigned struct_user_fpxregs_struct_sz; @@ -906,7 +912,7 @@ struct __sanitizer_cookie_io_functions_t { #define IOC_NRBITS 8 #define IOC_TYPEBITS 8 #if defined(__powerpc__) || defined(__powerpc64__) || defined(__mips__) || \ - defined(__sparc__) + defined(__sparc__) || defined(__sw_64__) #define IOC_SIZEBITS 13 #define IOC_DIRBITS 3 #define IOC_NONE 1U diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h index 11c6154b0..35a4bfd16 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h +++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h @@ -24,6 +24,8 @@ static const u32 kStackTraceMax = 256; #if SANITIZER_LINUX && defined(__mips__) # define SANITIZER_CAN_FAST_UNWIND 0 +#elif defined(__sw_64__) +# define SANITIZER_CAN_FAST_UNWIND 0 #elif SANITIZER_WINDOWS # define SANITIZER_CAN_FAST_UNWIND 0 #else diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp index 403bda117..574a82dc5 100644 --- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cpp @@ -16,7 +16,7 @@ #if SANITIZER_LINUX && \ (defined(__x86_64__) || defined(__mips__) || defined(__aarch64__) || \ defined(__powerpc64__) || defined(__s390__) || defined(__i386__) || \ - defined(__arm__) || SANITIZER_RISCV64) + defined(__arm__) || defined(__sw_64__) || SANITIZER_RISCV64) #include "sanitizer_stoptheworld.h" @@ -508,6 +508,12 @@ typedef struct user regs_struct; # define REG_SP regs[EF_REG29] # endif +#elif defined(__sw_64__) +typedef struct user regs_struct; +static constexpr uptr kExtraRegs[] = {0}; +#define REG_SP regs[EF_SP] +#define ARCH_IOVEC_FOR_GETREGSET + #elif defined(__aarch64__) typedef struct user_pt_regs regs_struct; #define REG_SP sp diff --git a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp index 3fc994fd3..8f1cba26f 100644 --- a/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp +++ b/libsanitizer/sanitizer_common/sanitizer_symbolizer_libcdep.cpp @@ -273,6 +273,8 @@ class LLVMSymbolizerProcess final : public SymbolizerProcess { const char* const kSymbolizerArch = "--default-arch=s390x"; #elif defined(__s390__) const char* const kSymbolizerArch = "--default-arch=s390"; +#elif defined(__sw_64__) + const char* const kSymbolizerArch = "--default-arch=sw_64"; #else const char* const kSymbolizerArch = "--default-arch=unknown"; #endif diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am index ae588a67d..f0608f3d1 100644 --- a/libsanitizer/tsan/Makefile.am +++ b/libsanitizer/tsan/Makefile.am @@ -50,7 +50,7 @@ tsan_files = \ tsan_vector_clock.cpp libtsan_la_SOURCES = $(tsan_files) -EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S +EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S tsan_rtl_sw64.S libtsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(TSAN_TARGET_DEPENDENT_OBJECTS) libtsan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(TSAN_TARGET_DEPENDENT_OBJECTS) if LIBBACKTRACE_SUPPORTED diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in index 538d2e8eb..4c1be63a3 100644 --- a/libsanitizer/tsan/Makefile.in +++ b/libsanitizer/tsan/Makefile.in @@ -456,7 +456,7 @@ tsan_files = \ tsan_vector_clock.cpp libtsan_la_SOURCES = $(tsan_files) -EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S +EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S tsan_rtl_s390x.S tsan_rtl_sw64.S libtsan_la_LIBADD = \ $(top_builddir)/sanitizer_common/libsanitizer_common.la \ $(top_builddir)/interception/libinterception.la \ diff --git a/libsanitizer/tsan/tsan_interceptors_posix.cpp b/libsanitizer/tsan/tsan_interceptors_posix.cpp index 9a85ee00d..54532a0fd 100644 --- a/libsanitizer/tsan/tsan_interceptors_posix.cpp +++ b/libsanitizer/tsan/tsan_interceptors_posix.cpp @@ -72,7 +72,7 @@ struct ucontext_t { #endif #if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \ - defined(__s390x__) + defined(__s390x__) || defined(__sw_64__) #define PTHREAD_ABI_BASE "GLIBC_2.3.2" #elif defined(__aarch64__) || SANITIZER_PPC64V2 #define PTHREAD_ABI_BASE "GLIBC_2.17" @@ -141,7 +141,7 @@ typedef __sanitizer::u16 mode_t; # define F_TLOCK 2 /* Test and lock a region for exclusive use. */ # define F_TEST 3 /* Test a region for other processes locks. */ -#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD +#if SANITIZER_FREEBSD || SANITIZER_MAC || SANITIZER_NETBSD || SANITIZER_SW64 const int SA_SIGINFO = 0x40; const int SIG_SETMASK = 3; #elif defined(__mips__) @@ -2487,7 +2487,7 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act, sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags; internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask, sizeof(sigactions[sig].sa_mask)); -#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD +#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD && !SANITIZER_SW64 sigactions[sig].sa_restorer = act->sa_restorer; #endif internal_memcpy(&newact, act, sizeof(newact)); @@ -2786,6 +2786,14 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_timedjoin_np); #endif + #if SANITIZER_SW64 + // sw64 have two version of timer function, osf_xxx with @glibc2.0, + // which is 32bits syscall for old kernal. xxx with @glibc2.1 is 64bits + // syscall for new kernal, we use the new one. + TSAN_INTERCEPT_VER(setitimer, "GLIBC_2.1"); + TSAN_INTERCEPT_VER(setitimer, "GLIBC_2.1"); + #endif + TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE); TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE); TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE); diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h index 7ff0acace..7ae0c9f3b 100644 --- a/libsanitizer/tsan/tsan_platform.h +++ b/libsanitizer/tsan/tsan_platform.h @@ -392,6 +392,44 @@ struct MappingS390x { static const uptr kMidAppMemEnd = 0; }; +// TODO(sw64_map): as sw64 kernal doesn't map such large space, we just map +// it for test, for now it works will. +// TODO(sw64_map_la): as sw64 map all space in low address, we set all user +// space +// in Lo address, perhaps there is some way to change it. +/* +C/C++ on linux/sw64 (52-bit VMA) +0000 0000 0000 - 0001 2000 0000: modules and main thread stack +0001 2000 0000 - 0008 0000 0000: main binary +0400 0000 0000 - 0600 0000 0000: pie main binary (including heap) +0600 0000 0000 - 4000 0000 0000: - +4000 0000 0000 - 6000 0000 0000: shadow +6000 0000 0000 - 7000 0000 0000: metainfo +7000 0000 0000 - 7c00 0000 0000: trace +*/ + +struct MappingSW64_52 { + static const uptr kLoAppMemBeg = 0x0000000000000ull; + static const uptr kLoAppMemEnd = 0x0600000000000ull; + static const uptr kShadowBeg = 0x4000000000000ull; + static const uptr kShadowEnd = 0x6000000000000ull; + static const uptr kHiAppMemBeg = 0xfff0000000000ull; + static const uptr kHiAppMemEnd = 0xfff0000000000ull; + static const uptr kShadowMsk = 0x0000000000000ull; + //distans between lo address to shadow begin + static const uptr kShadowXor = 0x1000000000000ull; + static const uptr kShadowAdd = 0x0000000000000ull; + static const uptr kHeapMemBeg = 0xff00000000000ull; + static const uptr kHeapMemEnd = 0xff00000000000ull; + static const uptr kMetaShadowBeg = 0x6000000000000ull; + static const uptr kMetaShadowEnd = 0x7000000000000ull; + static const uptr kTraceMemBeg = 0x7000000000000ull; + static const uptr kTraceMemEnd = 0x7c00000000000ull; + static const uptr kVdsoBeg = 0x3c00000000000000ull; + static const uptr kMidAppMemBeg = 0; + static const uptr kMidAppMemEnd = 0; +}; + /* Go on linux, darwin and freebsd on x86_64 0000 0000 1000 - 0000 1000 0000: executable 0000 1000 0000 - 00c0 0000 0000: - @@ -674,6 +712,8 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) { return Func::template Apply(arg); # elif defined(__s390x__) return Func::template Apply(arg); +# elif defined(__sw_64__) + return Func::template Apply(arg); # else # error "unsupported platform" # endif @@ -693,6 +733,7 @@ void ForEachMapping() { Func::template Apply(); Func::template Apply(); Func::template Apply(); + Func::template Apply(); Func::template Apply(); Func::template Apply(); Func::template Apply(); diff --git a/libsanitizer/tsan/tsan_platform_linux.cpp b/libsanitizer/tsan/tsan_platform_linux.cpp index 73ec14892..83dfa2391 100644 --- a/libsanitizer/tsan/tsan_platform_linux.cpp +++ b/libsanitizer/tsan/tsan_platform_linux.cpp @@ -400,6 +400,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { // tcbhead_t.stack_guard uptr xor_key = ((uptr *)__builtin_thread_pointer())[5]; return mangled_sp ^ xor_key; +#elif defined(__sw_64__) + return mangled_sp; #else #error "Unknown platform" #endif @@ -422,6 +424,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { # define LONG_JMP_SP_ENV_SLOT 1 # elif defined(__s390x__) # define LONG_JMP_SP_ENV_SLOT 9 +# elif defined(__sw_64__) +# define LONG_JMP_SP_ENV_SLOT 8 # else # define LONG_JMP_SP_ENV_SLOT 6 # endif diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h index eab837042..d3ceae483 100644 --- a/libsanitizer/tsan/tsan_rtl.h +++ b/libsanitizer/tsan/tsan_rtl.h @@ -55,7 +55,7 @@ namespace __tsan { #if !SANITIZER_GO struct MapUnmapCallback; -#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) +#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) || defined(__sw_64__) struct AP32 { static const uptr kSpaceBeg = 0; diff --git a/libsanitizer/tsan/tsan_rtl_sw64.S b/libsanitizer/tsan/tsan_rtl_sw64.S new file mode 100644 index 000000000..f74bfef8d --- /dev/null +++ b/libsanitizer/tsan/tsan_rtl_sw64.S @@ -0,0 +1,236 @@ +// The content of this file is sw64-only: +#if defined(__sw_64__) + +#include "sanitizer_common/sanitizer_asm.h" + +.section .text +.set noreorder + +ASM_HIDDEN(__tsan_setjmp) +.comm _ZN14__interception11real_setjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(setjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(setjmp)) +ASM_SYMBOL_INTERCEPTOR(setjmp): + ldgp $r29, 0($r27) + CFI_STARTPROC + + // Save frame/link register + ldi $sp, -32($sp) + stl $r26, 0($sp) + stl $fp, 8($sp) + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (26, -32) + CFI_OFFSET (15, -24) + + // Adjust the SP for previous frame + ldi $fp,0($sp) + CFI_DEF_CFA_REGISTER (15) + + // Save env parameter + stl $r16, 16($sp) + CFI_OFFSET (0, -16) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + ldi $r16, 32($sp) + + // call tsan interceptor + //ldih $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprelhigh + //ldi $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprellow + ldl $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !literal + call $r26, ($r27), 0 + ldgp $r29, 0($r26) + + // Restore env parameter + ldl $r16, 16($sp) + CFI_RESTORE (0) + + // Restore frame/link register + ldl $fp, 8($sp) + ldl $r26, 0($sp) + CFI_RESTORE (15) + CFI_RESTORE (26) + CFI_DEF_CFA (31, 0) + ldi $sp, 32($sp) + + // tail jump to libc setjmp + ldl $r27, _ZN14__interception11real_setjmpE($r29) !literal + ldl $r27, 0($r27) + + jmp $r31, ($r27) + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(setjmp)) + +ASM_HIDDEN(__tsan_setjmp) +.comm _ZN14__interception12real__setjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(_setjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(_setjmp)) +ASM_SYMBOL_INTERCEPTOR(_setjmp): + ldgp $r29, 0($r27) + CFI_STARTPROC + + // Save frame/link register + ldi $sp, -32($sp) + stl $r26, 0($sp) + stl $fp, 8($sp) + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (26, -32) + CFI_OFFSET (15, -24) + + // Adjust the SP for previous frame + ldi $fp,0($sp) + CFI_DEF_CFA_REGISTER (15) + + // Save env parameter + stl $r16, 16($sp) + CFI_OFFSET (0, -16) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + ldi $r16, 32($sp) + + // call tsan interceptor + //ldih $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprelhigh + //ldi $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprellow + ldl $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !literal + call $r26, ($r27), 0 + ldgp $r29, 0($r26) + + // Restore env parameter + ldl $r16, 16($sp) + CFI_RESTORE (0) + + // Restore frame/link register + ldl $fp, 8($sp) + ldl $r26, 0($sp) + CFI_RESTORE (15) + CFI_RESTORE (26) + CFI_DEF_CFA (31, 0) + ldi $sp, 32($sp) + + // tail jump to libc setjmp + ldl $r27, _ZN14__interception12real__setjmpE($r29) !literal + ldl $r27, 0($r27) + + jmp $r31, ($r27) + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(_setjmp)) + +ASM_HIDDEN(__tsan_setjmp) +.comm _ZN14__interception14real_sigsetjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(sigsetjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(sigsetjmp)) +ASM_SYMBOL_INTERCEPTOR(sigsetjmp): + ldgp $r29, 0($r27) + CFI_STARTPROC + + // Save frame/link register + ldi $sp, -32($sp) + stl $r26, 0($sp) + stl $fp, 8($sp) + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (26, -32) + CFI_OFFSET (15, -24) + + // Adjust the SP for previous frame + ldi $fp,0($sp) + CFI_DEF_CFA_REGISTER (15) + + // Save env parameter + stl $r16, 16($sp) + stl $r17, 24($sp) + CFI_OFFSET (16, -16) + CFI_OFFSET (17, -8) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + ldi $r16, 32($sp) + + // call tsan interceptor + //ldih $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprelhigh + //ldi $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprellow + ldl $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !literal + call $r26, ($r27), 0 + ldgp $r29, 0($r26) + + // Restore env parameter + ldl $r16, 16($sp) + ldl $r17, 24($sp) + CFI_RESTORE (0) + CFI_RESTORE (1) + + // Restore frame/link register + ldl $fp, 8($sp) + ldl $r26, 0($sp) + CFI_RESTORE (15) + CFI_RESTORE (26) + CFI_DEF_CFA (31, 0) + ldi $sp, 32($sp) + + // tail jump to libc setjmp + ldl $r27, _ZN14__interception14real_sigsetjmpE($r29) !literal + ldl $r27, 0($r27) + + jmp $r31, ($r27) + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(sigsetjmp)) + +ASM_HIDDEN(__tsan_setjmp) +.comm _ZN14__interception16real___sigsetjmpE,8,8 +.globl ASM_SYMBOL_INTERCEPTOR(__sigsetjmp) +ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)) +ASM_SYMBOL_INTERCEPTOR(__sigsetjmp): + ldgp $r29, 0($r27) + CFI_STARTPROC + + // Save frame/link register + ldi $sp, -32($sp) + stl $r26, 0($sp) + stl $fp, 8($sp) + CFI_DEF_CFA_OFFSET (32) + CFI_OFFSET (26, -32) + CFI_OFFSET (15, -24) + + // Adjust the SP for previous frame + ldi $fp,0($sp) + CFI_DEF_CFA_REGISTER (15) + + // Save env parameter + stl $r16, 16($sp) + stl $r17, 24($sp) + CFI_OFFSET (16, -16) + CFI_OFFSET (17, -8) + + // Obtain SP, first argument to `void __tsan_setjmp(uptr sp)` + ldi $r16, 32($sp) + + // call tsan interceptor + //ldih $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprelhigh + //ldi $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !gprellow + ldl $r27, ASM_SYMBOL(__tsan_setjmp)($r29) !literal + call $r26, ($r27), 0 + ldgp $r29, 0($r26) + + // Restore env parameter + ldl $r16, 16($sp) + ldl $r17, 24($sp) + CFI_RESTORE (0) + CFI_RESTORE (1) + + // Restore frame/link register + ldl $fp, 8($sp) + ldl $r26, 0($sp) + CFI_RESTORE (15) + CFI_RESTORE (26) + CFI_DEF_CFA (31, 0) + ldi $sp, 32($sp) + + // tail jump to libc setjmp + ldl $r27, _ZN14__interception16real___sigsetjmpE($r29) !literal + ldl $r27, 0($r27) + jmp $r31, ($r27) + + CFI_ENDPROC +ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(__sigsetjmp)) + +#endif -- 2.25.1