gcc/0015-Sw64-Port-libsanitizer.patch

1291 lines
50 KiB
Diff
Raw Permalink Normal View History

2024-11-28 08:55:07 +08:00
From df516f16c04a4806fde50fefc45f9d4c518d6872 Mon Sep 17 00:00:00 2001
From: swcompiler <lc@wxiat.com>
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 <typename AddressSpaceViewTy>
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 <typename Fn>
+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 <asm/stat.h>
+#undef stat
+#undef stat64
+#include <cstring>
+#include <cstdio>
+#endif
+
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
@@ -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 <sys/stat.h>
// 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<uptr>(__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 <utime.h>
# include <sys/ptrace.h>
# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \
- defined(__hexagon__) || SANITIZER_RISCV64
+ defined(__hexagon__) || defined(__sw_64__) || SANITIZER_RISCV64
# include <asm/ptrace.h>
# ifdef __arm__
typedef struct user_fpregs elf_fpregset_t;
@@ -141,7 +141,7 @@ typedef struct user_fpregs elf_fpregset_t;
#include <sys/shm.h>
#include <sys/statvfs.h>
#include <sys/timex.h>
-#if defined(__mips64)
+#if defined(__mips64) || defined(__sw_64__) // for elf_gregset_t
# include <sys/procfs.h>
#endif
#include <sys/user.h>
@@ -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<MappingMips64_40>(arg);
# elif defined(__s390x__)
return Func::template Apply<MappingS390x>(arg);
+# elif defined(__sw_64__)
+ return Func::template Apply<MappingSW64_52>(arg);
# else
# error "unsupported platform"
# endif
@@ -693,6 +733,7 @@ void ForEachMapping() {
Func::template Apply<MappingPPC64_46>();
Func::template Apply<MappingPPC64_47>();
Func::template Apply<MappingS390x>();
+ Func::template Apply<MappingSW64_52>();
Func::template Apply<MappingGo48>();
Func::template Apply<MappingGoWindows>();
Func::template Apply<MappingGoPPC64_46>();
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