diff --git a/0001-libsanitizer-Add-LoongArch-support.patch b/0001-libsanitizer-Add-LoongArch-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..65b4d38e364f9262c81ba919a1e11295769f3763 --- /dev/null +++ b/0001-libsanitizer-Add-LoongArch-support.patch @@ -0,0 +1,1100 @@ +From bf3e906f3541c81dceccbcd365eda857049a4db1 Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Fri, 6 Jan 2023 10:39:21 +0800 +Subject: [PATCH 1/2] LoongArch: Add sanitizer support + +Signed-off-by: Xing Li +Signed-off-by: Peng Fan +--- + gcc/config/loongarch/loongarch.c | 16 +- + libsanitizer/asan/asan_mapping.h | 6 + + libsanitizer/configure.tgt | 10 ++ + libsanitizer/lsan/lsan_allocator.cc | 2 +- + libsanitizer/lsan/lsan_allocator.h | 2 +- + libsanitizer/lsan/lsan_common.cc | 2 + + libsanitizer/sanitizer_common/Makefile.am | 2 +- + libsanitizer/sanitizer_common/Makefile.in | 3 +- + .../sanitizer_common_syscalls.inc | 6 +- + .../sanitizer_common/sanitizer_linux.cc | 94 ++++++++++- + .../sanitizer_common/sanitizer_linux.h | 4 +- + .../sanitizer_linux_libcdep.cc | 15 +- + .../sanitizer_linux_loongarch64.S | 22 +++ + .../sanitizer_common/sanitizer_platform.h | 21 ++- + .../sanitizer_platform_interceptors.h | 4 +- + .../sanitizer_platform_limits_linux.cc | 2 +- + .../sanitizer_platform_limits_posix.cc | 22 ++- + .../sanitizer_platform_limits_posix.h | 7 +- + .../sanitizer_common/sanitizer_stacktrace.cc | 2 +- + .../sanitizer_common/sanitizer_stacktrace.h | 5 +- + .../sanitizer_stoptheworld_linux_libcdep.cc | 14 +- + .../sanitizer_tls_get_addr.cc | 2 + + libsanitizer/tsan/Makefile.am | 2 +- + libsanitizer/tsan/Makefile.in | 3 +- + libsanitizer/tsan/tsan_interceptors.cc | 5 +- + libsanitizer/tsan/tsan_platform.h | 38 +++++ + libsanitizer/tsan/tsan_platform_posix.cc | 3 + + libsanitizer/tsan/tsan_rtl.cc | 16 +- + libsanitizer/tsan/tsan_rtl.h | 3 +- + libsanitizer/tsan/tsan_rtl_loongarch64.S | 156 ++++++++++++++++++ + 30 files changed, 448 insertions(+), 41 deletions(-) + create mode 100644 libsanitizer/sanitizer_common/sanitizer_linux_loongarch64.S + create mode 100644 libsanitizer/tsan/tsan_rtl_loongarch64.S + +diff --git a/gcc/config/loongarch/loongarch.c b/gcc/config/loongarch/loongarch.c +index e556f81e4..a7beee05e 100644 +--- a/gcc/config/loongarch/loongarch.c ++++ b/gcc/config/loongarch/loongarch.c +@@ -7761,7 +7761,16 @@ loongarch_prefetch_cookie (rtx write, rtx locality) + return GEN_INT (INTVAL (write) + 6); + } + +- ++/* Implement the TARGET_ASAN_SHADOW_OFFSET hook. */ ++ ++static unsigned HOST_WIDE_INT ++loongarch_asan_shadow_offset (void) ++{ ++ /* We only have libsanitizer support for LOONGARCH64 at present. ++ This value is taken from the file libsanitizer/asan/asan_mappint.h. */ ++ return TARGET_64BIT ? (HOST_WIDE_INT_1 << 37) : (0x0aaa0000); ++} ++ + /* Return whether CFG is used in loongarch_reorg. */ + + static bool +@@ -10461,5 +10470,8 @@ loongarch_build_signbit_mask (machine_mode mode, bool vect, bool invert) + #define TARGET_STARTING_FRAME_OFFSET loongarch_starting_frame_offset + + struct gcc_target targetm = TARGET_INITIALIZER; +- ++ ++#undef TARGET_ASAN_SHADOW_OFFSET ++#define TARGET_ASAN_SHADOW_OFFSET loongarch_asan_shadow_offset ++ + #include "gt-loongarch.h" +diff --git a/libsanitizer/asan/asan_mapping.h b/libsanitizer/asan/asan_mapping.h +index 5496df66d..77c8061ad 100644 +--- a/libsanitizer/asan/asan_mapping.h ++++ b/libsanitizer/asan/asan_mapping.h +@@ -141,6 +141,8 @@ static const u64 kIosSimShadowOffset64 = kDefaultShadowOffset64; + static const u64 kAArch64_ShadowOffset64 = 1ULL << 36; + static const u64 kMIPS32_ShadowOffset32 = 0x0aaa0000; + static const u64 kMIPS64_ShadowOffset64 = 1ULL << 37; ++static const u64 kLoongArch32_ShadowOffset32 = 0x0aaa0000; ++static const u64 kLoongArch64_ShadowOffset64 = 1ULL << 37; + static const u64 kPPC64_ShadowOffset64 = 1ULL << 41; + static const u64 kSystemZ_ShadowOffset64 = 1ULL << 52; + static const u64 kFreeBSD_ShadowOffset32 = 1ULL << 30; // 0x40000000 +@@ -157,6 +159,8 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 + # define SHADOW_OFFSET (0) + # elif defined(__mips__) + # define SHADOW_OFFSET kMIPS32_ShadowOffset32 ++# elif defined(__loongarch__) ++# define SHADOW_OFFSET kLoongArch32_ShadowOffset32 + # elif SANITIZER_FREEBSD + # define SHADOW_OFFSET kFreeBSD_ShadowOffset32 + # elif SANITIZER_WINDOWS +@@ -191,6 +195,8 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000 + # define SHADOW_OFFSET kDefaultShadowOffset64 + # elif defined(__mips64) + # define SHADOW_OFFSET kMIPS64_ShadowOffset64 ++# elif defined(__loongarch64) ++# define SHADOW_OFFSET kLoongArch64_ShadowOffset64 + # elif SANITIZER_WINDOWS64 + # define SHADOW_OFFSET __asan_shadow_memory_dynamic_address + # else +diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt +index 573e3b482..8da064c1e 100644 +--- a/libsanitizer/configure.tgt ++++ b/libsanitizer/configure.tgt +@@ -55,6 +55,16 @@ case "${target}" in + x86_64-*-darwin[1]* | i?86-*-darwin[1]*) + TSAN_SUPPORTED=no + ;; ++ loongarch*-*-linux*) ++ if echo "int x = __loongarch64;" | $CC -c -x c -o /dev/null - > /dev/null 2>&1; then ++ SANITIZER_COMMON_TARGET_DEPENDENT_OBJECTS=sanitizer_linux_loongarch64.lo ++ fi ++ if test x$ac_cv_sizeof_void_p = x8; then ++ TSAN_SUPPORTED=yes ++ LSAN_SUPPORTED=yes ++ TSAN_TARGET_DEPENDENT_OBJECTS=tsan_rtl_loongarch64.lo ++ fi ++ ;; + *) + UNSUPPORTED=1 + ;; +diff --git a/libsanitizer/lsan/lsan_allocator.cc b/libsanitizer/lsan/lsan_allocator.cc +index 9e1668077..b3ef2400e 100644 +--- a/libsanitizer/lsan/lsan_allocator.cc ++++ b/libsanitizer/lsan/lsan_allocator.cc +@@ -26,7 +26,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(__loongarch64) + 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 b0c0ec241..5793dd372 100644 +--- a/libsanitizer/lsan/lsan_allocator.h ++++ b/libsanitizer/lsan/lsan_allocator.h +@@ -49,7 +49,7 @@ struct ChunkMetadata { + }; + + #if defined(__mips64) || defined(__aarch64__) || defined(__i386__) || \ +- defined(__arm__) ++ defined(__arm__) || defined(__loongarch64) + static const uptr kRegionSizeLog = 20; + static const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog; + typedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap; +diff --git a/libsanitizer/lsan/lsan_common.cc b/libsanitizer/lsan/lsan_common.cc +index 4afce9df0..e1dce25c7 100644 +--- a/libsanitizer/lsan/lsan_common.cc ++++ b/libsanitizer/lsan/lsan_common.cc +@@ -136,6 +136,8 @@ static inline bool CanBeAHeapPointer(uptr p) { + return ((p >> 47) == 0); + #elif defined(__mips64) + return ((p >> 40) == 0); ++#elif defined(__loongarch64) ++ return ((p >> 40) == 0); + #elif defined(__aarch64__) + unsigned runtimeVMA = + (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1); +diff --git a/libsanitizer/sanitizer_common/Makefile.am b/libsanitizer/sanitizer_common/Makefile.am +index 246985b99..3b39f5bb0 100644 +--- a/libsanitizer/sanitizer_common/Makefile.am ++++ b/libsanitizer/sanitizer_common/Makefile.am +@@ -71,7 +71,7 @@ sanitizer_common_files = \ + + + libsanitizer_common_la_SOURCES = $(sanitizer_common_files) +-EXTRA_libsanitizer_common_la_SOURCES = sanitizer_linux_mips64.S sanitizer_linux_x86_64.S ++EXTRA_libsanitizer_common_la_SOURCES = sanitizer_linux_mips64.S sanitizer_linux_x86_64.S sanitizer_linux_loongarch64.S + libsanitizer_common_la_LIBADD = $(SANITIZER_COMMON_TARGET_DEPENDENT_OBJECTS) + libsanitizer_common_la_DEPENDENCIES = $(SANITIZER_COMMON_TARGET_DEPENDENT_OBJECTS) + +diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in +index b0f5ac25a..023f633f7 100644 +--- a/libsanitizer/sanitizer_common/Makefile.in ++++ b/libsanitizer/sanitizer_common/Makefile.in +@@ -355,7 +355,7 @@ sanitizer_common_files = \ + sanitizer_win.cc + + libsanitizer_common_la_SOURCES = $(sanitizer_common_files) +-EXTRA_libsanitizer_common_la_SOURCES = sanitizer_linux_mips64.S sanitizer_linux_x86_64.S ++EXTRA_libsanitizer_common_la_SOURCES = sanitizer_linux_mips64.S sanitizer_linux_x86_64.S sanitizer_linux_loongarch64.S + libsanitizer_common_la_LIBADD = $(SANITIZER_COMMON_TARGET_DEPENDENT_OBJECTS) + libsanitizer_common_la_DEPENDENCIES = $(SANITIZER_COMMON_TARGET_DEPENDENT_OBJECTS) + +@@ -467,6 +467,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux_libcdep.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux_mips64.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux_loongarch64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux_s390.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_linux_x86_64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sanitizer_mac.Plo@am__quote@ +diff --git a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc +index 6fd5ef742..f55759106 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc ++++ b/libsanitizer/sanitizer_common/sanitizer_common_syscalls.inc +@@ -2295,7 +2295,8 @@ POST_SYSCALL(ni_syscall)(long res) {} + 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__)) ++ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ ++ defined(__loongarch64)) + if (data) { + if (request == ptrace_setregs) { + PRE_READ((void *)data, struct_user_regs_struct_sz); +@@ -2316,7 +2317,8 @@ PRE_SYSCALL(ptrace)(long request, long pid, long addr, long data) { + 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__)) ++ defined(__powerpc64__) || defined(__aarch64__) || defined(__s390__) || \ ++ defined(__loongarch64)) + 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.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc +index 2826cc89e..003c38b4f 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_linux.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc +@@ -12,6 +12,10 @@ + + #include "sanitizer_platform.h" + ++#if defined(__loongarch__) ++#define __ARCH_WANT_RENAMEAT 1 ++#endif ++ + #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD + + #include "sanitizer_common.h" +@@ -127,7 +131,7 @@ const int FUTEX_WAKE = 1; + # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0 + #endif + +-#if defined(__x86_64__) || SANITIZER_MIPS64 ++#if defined(__x86_64__) || SANITIZER_MIPS64 || SANITIZER_LOONGARCH64 + extern "C" { + extern void internal_sigreturn(); + } +@@ -802,7 +806,7 @@ int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { + // Invokes sigaction via a raw syscall with a restorer, but does not support + // all platforms yet. + // We disable for Go simply because we have not yet added to buildgo.sh. +-#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO ++#if (defined(__x86_64__) || SANITIZER_MIPS64 || SANITIZER_LOONGARCH64) && !SANITIZER_GO + int internal_sigaction_syscall(int signum, const void *act, void *oldact) { + if (act == nullptr) + return internal_sigaction_norestorer(signum, act, oldact); +@@ -980,6 +984,8 @@ uptr GetMaxVirtualAddress() { + return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1; + # elif defined(__mips64) + return (1ULL << 40) - 1; // 0x000000ffffffffffUL; ++# elif defined(__loongarch64) ++ return (1ULL << 40) - 1; // 0x000000ffffffffffUL; + # elif defined(__s390x__) + return (1ULL << 53) - 1; // 0x001fffffffffffffUL; + # else +@@ -1247,6 +1253,61 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, + : "memory", "$29" ); + return res; + } ++#elif defined(__loongarch__) && SANITIZER_LINUX ++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; ++ CHECK_EQ(0, (uptr)child_stack % 16); ++ child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); ++ ((unsigned long long *)child_stack)[0] = (uptr)fn; ++ ((unsigned long long *)child_stack)[1] = (uptr)arg; ++ ++ register int __flags __asm__("r4") = flags; ++ register void *__child_stack __asm__("r5") = child_stack; ++ register int *__parent_tidptr __asm__("r6") = parent_tidptr; ++ register void *__newtls __asm__("r7") = newtls; ++ register int *__child_tidptr __asm__("r8") = child_tidptr; ++ ++ __asm__ __volatile__( ++ /* $a0 = syscall($a7 = SYSCALL(clone), ++ * $a0 = flags, ++ * $a1 = child_stack, ++ * $a2 = parent_tidptr, ++ * $a3 = new_tls, ++ * $a4 = child_tyidptr) ++ */ ++ ++ /* Do the system call */ ++ "addi.d $a7, $r0, %1\n" ++ "syscall 0\n" ++ ++ "move %0, $a0" ++ : "=r"(res) ++ : "i"(__NR_clone), ++ "r"(__flags), "r"(__child_stack), "r"(__parent_tidptr), "r"(__newtls), "r"(__child_tidptr) ++ :"memory" ); ++ if (res != 0) { ++ return res; ++ } ++ __asm__ __volatile__ ( ++ /* In the child, now. Call "fn(arg)". */ ++ "ld.d $a6, $sp, 0\n" ++ "ld.d $a0, $sp, 8\n" ++ ++ "jirl $r1, $a6, 0\n" ++ ++ /* Call _exit($v0) */ ++ "addi.d $a7, $r0, %1\n" ++ "syscall 0\n" ++ ++ "move %0, $a0" ++ : "=r"(res) ++ : "i"(__NR_exit) ++ :"r1", "memory"); ++ 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) { +@@ -1676,6 +1737,30 @@ SignalContext::WriteFlag SignalContext::GetWriteFlag() const { + u64 esr; + if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN; + return esr & ESR_ELx_WNR ? WRITE : READ; ++#elif defined(__loongarch__) ++ uint32_t *exception_source; ++ uint32_t faulty_instruction; ++ uint32_t op_code; ++ ++ exception_source = (uint32_t *)ucontext->uc_mcontext.__pc; ++ faulty_instruction = (uint32_t)(*exception_source); ++ ++ op_code = (faulty_instruction >> 22) & 0x3ff; ++ switch (op_code) { ++ case 0xa0: //ld.b ++ case 0xa1: //ld.h ++ case 0xa2: //ld.w ++ case 0xa3: //ld.d ++ return SignalContext::READ; ++ case 0xa4: ++ case 0xa5: ++ case 0xa6: ++ return SignalContext::WRITE; ++ case 0xa8: ++ case 0xa9: ++ return SignalContext::READ; ++ } ++ return SignalContext::UNKNOWN; + #else + (void)ucontext; + return UNKNOWN; // FIXME: Implement. +@@ -1763,6 +1848,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(__loongarch__) ++ ucontext_t *ucontext = (ucontext_t*)context; ++ *pc = ucontext->uc_mcontext.__pc; ++ *bp = ucontext->uc_mcontext.__gregs[22]; ++ *sp = ucontext->uc_mcontext.__gregs[3]; + #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 910703d8b..600d2b382 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_linux.h ++++ b/libsanitizer/sanitizer_common/sanitizer_linux.h +@@ -52,14 +52,14 @@ uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5); + // (like the process-wide error reporting SEGV handler) must use + // internal_sigaction instead. + int internal_sigaction_norestorer(int signum, const void *act, void *oldact); +-#if (defined(__x86_64__) || SANITIZER_MIPS64) && !SANITIZER_GO ++#if (defined(__x86_64__) || SANITIZER_MIPS64 || SANITIZER_LOONGARCH64) && !SANITIZER_GO + // Uses a raw system call to avoid interceptors. + int internal_sigaction_syscall(int signum, const void *act, void *oldact); + #endif + 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__) ++ || defined(__arm__) || defined(__loongarch__) + 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.cc b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc +index 3b1a2174c..43551c0d1 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_linux_libcdep.cc +@@ -196,7 +196,7 @@ void InitTlsSize() { } + + #if (defined(__x86_64__) || defined(__i386__) || defined(__mips__) \ + || defined(__aarch64__) || defined(__powerpc64__) || defined(__s390__) \ +- || defined(__arm__)) && SANITIZER_LINUX && !SANITIZER_ANDROID ++ || defined(__arm__) || defined(__loongarch__)) && SANITIZER_LINUX && !SANITIZER_ANDROID + // sizeof(struct pthread) from glibc. + static atomic_uintptr_t kThreadDescriptorSize; + +@@ -251,6 +251,9 @@ uptr ThreadDescriptorSize() { + if (val) + atomic_store(&kThreadDescriptorSize, val, memory_order_relaxed); + return val; ++#elif defined(__loongarch64) ++ val = 1776; ++ return val; + #elif defined(__aarch64__) + // The sizeof (struct pthread) is the same from GLIBC 2.17 to 2.22. + val = 1776; +@@ -274,12 +277,14 @@ uptr ThreadSelfOffset() { + return kThreadSelfOffset; + } + +-#if defined(__mips__) || defined(__powerpc64__) ++#if defined(__mips__) || defined(__powerpc64__) || defined(__loongarch__) + // TlsPreTcbSize includes size of struct pthread_descr and size of tcb + // head structure. It lies before the static tls blocks. + static uptr TlsPreTcbSize() { + # if defined(__mips__) + const uptr kTcbHead = 16; // sizeof (tcbhead_t) ++# elif defined(__loongarch__) ++ const uptr kTcbHead = 16; // sizeof (tcbhead_t) + # elif defined(__powerpc64__) + const uptr kTcbHead = 88; // sizeof (tcbhead_t) + # endif +@@ -308,6 +313,10 @@ uptr ThreadSelf() { + rdhwr %0,$29;\ + .set pop" : "=r" (thread_pointer)); + descr_addr = thread_pointer - kTlsTcbOffset - TlsPreTcbSize(); ++# elif defined(__loongarch__) ++ uptr thread_pointer; ++ asm("or %0,$r2,$r0" : "=r" (thread_pointer)); ++ descr_addr = thread_pointer - TlsPreTcbSize(); + # elif defined(__aarch64__) || defined(__arm__) + descr_addr = reinterpret_cast(__builtin_thread_pointer()) - + ThreadDescriptorSize(); +@@ -360,7 +369,7 @@ static void GetTls(uptr *addr, uptr *size) { + *addr -= *size; + *addr += ThreadDescriptorSize(); + # elif defined(__mips__) || defined(__aarch64__) || defined(__powerpc64__) \ +- || defined(__arm__) ++ || defined(__arm__) || defined(__loongarch__) + *addr = ThreadSelf(); + *size = GetTlsSize(); + # else +diff --git a/libsanitizer/sanitizer_common/sanitizer_linux_loongarch64.S b/libsanitizer/sanitizer_common/sanitizer_linux_loongarch64.S +new file mode 100644 +index 000000000..245816e60 +--- /dev/null ++++ b/libsanitizer/sanitizer_common/sanitizer_linux_loongarch64.S +@@ -0,0 +1,22 @@ ++// This file is dual licensed under the MIT and the University of Illinois Open ++// Source Licenses. See LICENSE.TXT for details. ++ ++// Avoid being marked as needing an executable stack: ++#if defined(__linux__) && defined(__ELF__) ++.section .note.GNU-stack,"",%progbits ++#endif ++ ++// Further contents are loongarch64 only: ++#if defined(__linux__) && defined(__loongarch64) ++ ++.section .text ++.globl internal_sigreturn ++.type internal_sigreturn, @function ++internal_sigreturn: ++ ++ li.d $r11,139 // #139 is for SYS_rt_sigreturn ++ syscall 0 ++ ++.size internal_sigreturn, .-internal_sigreturn ++ ++#endif // defined(__linux__) && defined(__loongarch64) +diff --git a/libsanitizer/sanitizer_common/sanitizer_platform.h b/libsanitizer/sanitizer_common/sanitizer_platform.h +index 1eb4d0c61..6d91863a5 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_platform.h ++++ b/libsanitizer/sanitizer_common/sanitizer_platform.h +@@ -187,7 +187,7 @@ + #ifndef SANITIZER_CAN_USE_ALLOCATOR64 + # if (SANITIZER_ANDROID && defined(__aarch64__)) || SANITIZER_FUCHSIA + # define SANITIZER_CAN_USE_ALLOCATOR64 1 +-# elif defined(__mips64) || defined(__aarch64__) ++# elif defined(__mips64) || defined(__aarch64__) || defined(__loongarch64) + # define SANITIZER_CAN_USE_ALLOCATOR64 0 + # else + # define SANITIZER_CAN_USE_ALLOCATOR64 (SANITIZER_WORDSIZE == 64) +@@ -197,7 +197,7 @@ + // The range of addresses which can be returned my mmap. + // FIXME: this value should be different on different platforms. Larger values + // will still work but will consume more memory for TwoLevelByteMap. +-#if defined(__mips__) ++#if defined(__mips__) || defined(__loongarch__) + # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40) + #elif defined(__aarch64__) + # define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 48) +@@ -209,7 +209,7 @@ + // the upstream linux community for all new ports. Other ports may still + // use legacy syscalls. + #ifndef SANITIZER_USES_CANONICAL_LINUX_SYSCALLS +-# if defined(__aarch64__) && SANITIZER_LINUX ++# if (defined(__aarch64__) || defined(__loongarch64)) && SANITIZER_LINUX + # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 1 + # else + # define SANITIZER_USES_CANONICAL_LINUX_SYSCALLS 0 +@@ -241,6 +241,21 @@ + # define HAVE_TIRPC_RPC_XDR_H 0 + #endif + ++#if defined(__loongarch__) ++# define SANITIZER_LOONGARCH 1 ++# if defined(__loongarch64) ++# define SANITIZER_LOONGARCH32 0 ++# define SANITIZER_LOONGARCH64 1 ++# else ++# define SANITIZER_LOONGARCH32 1 ++# define SANITIZER_LOONGARCH64 0 ++# endif ++#else ++# define SANITIZER_LOONGARCH 0 ++# define SANITIZER_LOONGARCH32 0 ++# define SANITIZER_LOONGARCH64 0 ++#endif ++ + /// \macro MSC_PREREQ + /// \brief Is the compiler MSVC of at least the specified version? + /// The common \param version values to check for are: +diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +index b9eb09ad3..e8f8cfedb 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h +@@ -205,7 +205,7 @@ + #if SI_LINUX_NOT_ANDROID && \ + (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ +- defined(__s390__)) ++ defined(__s390__) || defined(__loongarch__)) + #define SANITIZER_INTERCEPT_PTRACE 1 + #else + #define SANITIZER_INTERCEPT_PTRACE 0 +@@ -382,7 +382,7 @@ + #define SANITIZER_INTERCEPT_PVALLOC \ + (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && SI_NOT_FUCHSIA) + #define SANITIZER_INTERCEPT_CFREE \ +- (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && SI_NOT_FUCHSIA) ++ (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && SI_NOT_FUCHSIA && !SANITIZER_LOONGARCH) + #define SANITIZER_INTERCEPT_ALIGNED_ALLOC (!SI_MAC) + #define SANITIZER_INTERCEPT_MALLOC_USABLE_SIZE (!SI_MAC) + #define SANITIZER_INTERCEPT_MCHECK_MPROBE SI_LINUX_NOT_ANDROID +diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc +index 23a014823..cf71e922e 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_linux.cc +@@ -64,7 +64,7 @@ namespace __sanitizer { + + #if !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__aarch64__)\ + && !defined(__mips__) && !defined(__s390__)\ +- && !defined(__sparc__) ++ && !defined(__sparc__) && !defined(__loongarch__) + COMPILER_CHECK(struct___old_kernel_stat_sz == sizeof(struct __old_kernel_stat)); + #endif + +diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc +index 5c720b2e7..e0225c4a9 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cc +@@ -115,7 +115,8 @@ + #if SANITIZER_LINUX || SANITIZER_FREEBSD + # include + # include +-# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) ++# if defined(__mips64) || defined(__aarch64__) || defined(__arm__) || \ ++ defined(__loongarch64) + # include + # ifdef __arm__ + typedef struct user_fpregs elf_fpregset_t; +@@ -153,7 +154,7 @@ typedef struct user_fpregs elf_fpregset_t; + #include + #include + #include +-#if defined(__mips64) ++#if defined(__mips64) || defined(__loongarch64) + # include + #endif + #include +@@ -253,10 +254,11 @@ 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__) ++ || defined(__x86_64__) || defined(__loongarch64) + #define SIZEOF_STRUCT_USTAT 32 + #elif defined(__arm__) || defined(__i386__) || defined(__mips__) \ +- || defined(__powerpc__) || defined(__s390__) || defined(__sparc__) ++ || defined(__powerpc__) || defined(__s390__) || defined(__sparc__) \ ++ || defined(__loongarch__) + #define SIZEOF_STRUCT_USTAT 20 + #else + #error Unknown size of struct ustat +@@ -326,27 +328,31 @@ 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__)) ++ defined(__s390__) || defined(__loongarch64)) + #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 defined(__aarch64__) + unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs); + unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpsimd_state); ++#elif defined(__loongarch64) ++ unsigned struct_user_regs_struct_sz = sizeof(struct user_pt_regs); ++ unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fp_state); + #elif defined(__s390__) + unsigned struct_user_regs_struct_sz = sizeof(struct _user_regs_struct); + unsigned struct_user_fpregs_struct_sz = sizeof(struct _user_fpregs_struct); + #else + unsigned struct_user_regs_struct_sz = sizeof(struct user_regs_struct); + unsigned struct_user_fpregs_struct_sz = sizeof(struct user_fpregs_struct); +-#endif // __mips64 || __powerpc64__ || __aarch64__ ++#endif // __mips64 || __powerpc64__ || __aarch64__ || __loongarch64 + #if defined(__x86_64) || defined(__mips64) || defined(__powerpc64__) || \ +- defined(__aarch64__) || defined(__arm__) || defined(__s390__) ++ defined(__aarch64__) || defined(__arm__) || defined(__s390__) || \ ++ defined(__loongarch64) + 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__ || __loongarch64 + #ifdef __arm__ + unsigned struct_user_vfpregs_struct_sz = ARM_VFPREGS_SIZE; + #else +diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h +index 9c1429623..0020448cc 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h +@@ -77,6 +77,9 @@ namespace __sanitizer { + #elif defined(__aarch64__) + const unsigned struct_kernel_stat_sz = 128; + const unsigned struct_kernel_stat64_sz = 104; ++#elif defined(__loongarch__) ++ const unsigned struct_kernel_stat_sz = 128; ++ const unsigned struct_kernel_stat64_sz = 128; + #elif defined(__powerpc__) && !defined(__powerpc64__) + const unsigned struct_kernel_stat_sz = 72; + const unsigned struct_kernel_stat64_sz = 104; +@@ -659,7 +662,7 @@ namespace __sanitizer { + + #if SANITIZER_FREEBSD + typedef __sanitizer_sigset_t __sanitizer_kernel_sigset_t; +-#elif defined(__mips__) ++#elif defined(__mips__) || defined(__loongarch__) + struct __sanitizer_kernel_sigset_t { + uptr sig[2]; + }; +@@ -827,7 +830,7 @@ namespace __sanitizer { + #if SANITIZER_LINUX && !SANITIZER_ANDROID && \ + (defined(__i386) || defined(__x86_64) || defined(__mips64) || \ + defined(__powerpc64__) || defined(__aarch64__) || defined(__arm__) || \ +- defined(__s390__)) ++ defined(__s390__) || defined(__loongarch64)) + extern unsigned struct_user_regs_struct_sz; + extern unsigned struct_user_fpregs_struct_sz; + extern unsigned struct_user_fpxregs_struct_sz; +diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc +index 2de585c32..ca79b289d 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.cc +@@ -18,7 +18,7 @@ namespace __sanitizer { + uptr StackTrace::GetNextInstructionPc(uptr pc) { + #if defined(__mips__) + return pc + 8; +-#elif defined(__powerpc__) ++#elif defined(__powerpc__) || defined(__loongarch__) + return pc + 4; + #else + return pc + 1; +diff --git a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h +index 31e99f6b9..3affe4eb7 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_stacktrace.h ++++ b/libsanitizer/sanitizer_common/sanitizer_stacktrace.h +@@ -17,7 +17,8 @@ namespace __sanitizer { + + static const u32 kStackTraceMax = 256; + +-#if SANITIZER_LINUX && (defined(__sparc__) || defined(__mips__)) ++#if SANITIZER_LINUX && (defined(__sparc__) || defined(__mips__)) || \ ++ (SANITIZER_LINUX && defined(__loongarch__)) + # define SANITIZER_CAN_FAST_UNWIND 0 + #elif SANITIZER_WINDOWS + # define SANITIZER_CAN_FAST_UNWIND 0 +@@ -74,7 +75,7 @@ uptr StackTrace::GetPreviousInstructionPc(uptr pc) { + // Cancel Thumb bit. + pc = pc & (~1); + #endif +-#if defined(__powerpc__) || defined(__powerpc64__) ++#if defined(__powerpc__) || defined(__powerpc64__) || defined(__loongarch__) + // PCs are always 4 byte aligned. + return pc - 4; + #elif defined(__sparc__) || defined(__mips__) +diff --git a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +index d746fa540..4c183efc4 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc +@@ -15,13 +15,17 @@ + #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__mips__) || \ + defined(__aarch64__) || defined(__powerpc64__) || \ + defined(__s390__) || defined(__i386__) || \ +- defined(__arm__)) ++ defined(__arm__) || defined(__loongarch__)) + + #include "sanitizer_stoptheworld.h" + + #include "sanitizer_platform_limits_posix.h" + #include "sanitizer_atomic.h" + ++#if defined(__loongarch__) ++#include ++#endif ++ + #include + #include // for CLONE_* definitions + #include +@@ -35,7 +39,7 @@ + # include + #endif + #include // for user_regs_struct +-#if SANITIZER_ANDROID && SANITIZER_MIPS ++#if SANITIZER_ANDROID && SANITIZER_MIPS || SANITIZER_LOONGARCH + # include // for mips SP register in sys/user.h + #endif + #include // for signal-related stuff +@@ -483,8 +487,14 @@ typedef pt_regs regs_struct; + + #elif defined(__mips__) + typedef struct user regs_struct; ++#elif defined(__loongarch__) ++typedef struct user_regs_struct regs_struct; ++#define ARCH_IOVEC_FOR_GETREGSET ++ + # if SANITIZER_ANDROID + # define REG_SP regs[EF_R29] ++# elif SANITIZER_LOONGARCH ++# define REG_SP gpr[3] + # else + # define REG_SP regs[EF_REG29] + # endif +diff --git a/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc +index ebf5ec094..c7cdf37df 100644 +--- a/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc ++++ b/libsanitizer/sanitizer_common/sanitizer_tls_get_addr.cc +@@ -81,6 +81,8 @@ void DTLS_Destroy() { + // "Dynamic thread vector pointers point 0x8000 past the start of each + // TLS block." + static const uptr kDtvOffset = 0x8000; ++#elif defined(__loongarch__) ++static const uptr kDtvOffset = 0x800; + #else + static const uptr kDtvOffset = 0; + #endif +diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am +index 753cb8f4f..ac5ae4117 100644 +--- a/libsanitizer/tsan/Makefile.am ++++ b/libsanitizer/tsan/Makefile.am +@@ -50,7 +50,7 @@ tsan_files = \ + tsan_sync.cc + + 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 ++EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S rtl_loongarch64.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 629056bf1..6a3477b99 100644 +--- a/libsanitizer/tsan/Makefile.in ++++ b/libsanitizer/tsan/Makefile.in +@@ -358,7 +358,7 @@ tsan_files = \ + tsan_sync.cc + + 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 ++EXTRA_libtsan_la_SOURCES = tsan_rtl_amd64.S tsan_rtl_aarch64.S tsan_rtl_mips64.S tsan_rtl_ppc64.S rtl_loongarch64.S + libtsan_la_LIBADD = \ + $(top_builddir)/sanitizer_common/libsanitizer_common.la \ + $(top_builddir)/interception/libinterception.la \ +@@ -512,6 +512,7 @@ distclean-compile: + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_aarch64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_amd64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_mips64.Plo@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_loongarch64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_mutex.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_ppc64.Plo@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tsan_rtl_proc.Plo@am__quote@ +diff --git a/libsanitizer/tsan/tsan_interceptors.cc b/libsanitizer/tsan/tsan_interceptors.cc +index 15f20d4b6..c6959862b 100644 +--- a/libsanitizer/tsan/tsan_interceptors.cc ++++ b/libsanitizer/tsan/tsan_interceptors.cc +@@ -71,7 +71,8 @@ struct ucontext_t { + }; + #endif + +-#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 ++#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 \ ++ || defined(__loongarch__) + #define PTHREAD_ABI_BASE "GLIBC_2.3.2" + #elif defined(__aarch64__) || SANITIZER_PPC64V2 + #define PTHREAD_ABI_BASE "GLIBC_2.17" +@@ -500,6 +501,8 @@ static void LongJmp(ThreadState *thr, uptr *env) { + uptr mangled_sp = env[13]; + # elif defined(__mips64) + uptr mangled_sp = env[1]; ++#elif defined(__loongarch64) ++ uptr mangled_sp = env[1]; + # else + uptr mangled_sp = env[6]; + # endif +diff --git a/libsanitizer/tsan/tsan_platform.h b/libsanitizer/tsan/tsan_platform.h +index 44a3ea991..a50dc6dbe 100644 +--- a/libsanitizer/tsan/tsan_platform.h ++++ b/libsanitizer/tsan/tsan_platform.h +@@ -129,6 +129,44 @@ struct Mapping { + static const uptr kVdsoBeg = 0x7000000000000000ull; + }; + ++#elif defined(__loongarch64) ++/* ++ * TODO same as mips64 and need to change in the future ++C/C++ on linux/loongarch64 (40-bit VMA) ++0000 0000 00 - 0100 0000 00: - (4 GB) ++0100 0000 00 - 0200 0000 00: main binary (4 GB) ++0200 0000 00 - 2000 0000 00: - (120 GB) ++2000 0000 00 - 4000 0000 00: shadow (128 GB) ++4000 0000 00 - 5000 0000 00: metainfo (memory blocks and sync objects) (64 GB) ++5000 0000 00 - aa00 0000 00: - (360 GB) ++aa00 0000 00 - ab00 0000 00: main binary (PIE) (4 GB) ++ab00 0000 00 - b000 0000 00: - (20 GB) ++b000 0000 00 - b200 0000 00: traces (8 GB) ++b200 0000 00 - fe00 0000 00: - (304 GB) ++fe00 0000 00 - ff00 0000 00: heap (4 GB) ++ff00 0000 00 - ff80 0000 00: - (2 GB) ++ff80 0000 00 - ffff ffff ff: modules and main thread stack (<2 GB) ++*/ ++struct Mapping { ++ static const uptr kMetaShadowBeg = 0x4000000000ull; ++ static const uptr kMetaShadowEnd = 0x5000000000ull; ++ static const uptr kTraceMemBeg = 0xb000000000ull; ++ static const uptr kTraceMemEnd = 0xb200000000ull; ++ static const uptr kShadowBeg = 0x2000000000ull; ++ static const uptr kShadowEnd = 0x4000000000ull; ++ static const uptr kHeapMemBeg = 0xfe00000000ull; ++ static const uptr kHeapMemEnd = 0xff00000000ull; ++ static const uptr kLoAppMemBeg = 0x0100000000ull; ++ static const uptr kLoAppMemEnd = 0x0200000000ull; ++ static const uptr kMidAppMemBeg = 0xaa00000000ull; ++ static const uptr kMidAppMemEnd = 0xab00000000ull; ++ static const uptr kHiAppMemBeg = 0xff80000000ull; ++ static const uptr kHiAppMemEnd = 0xffffffffffull; ++ static const uptr kAppMemMsk = 0xf800000000ull; ++ static const uptr kAppMemXor = 0x0800000000ull; ++ static const uptr kVdsoBeg = 0xfffff00000ull; ++}; ++ + #elif defined(__aarch64__) + // AArch64 supports multiple VMA which leads to multiple address transformation + // functions. To support these multiple VMAS transformations and mappings TSAN +diff --git a/libsanitizer/tsan/tsan_platform_posix.cc b/libsanitizer/tsan/tsan_platform_posix.cc +index 6e62575f1..e146d04fb 100644 +--- a/libsanitizer/tsan/tsan_platform_posix.cc ++++ b/libsanitizer/tsan/tsan_platform_posix.cc +@@ -59,6 +59,9 @@ void InitializeShadowMemory() { + } else { + DCHECK(0); + } ++#elif defined(__loongarch64) ++ const uptr kMadviseRangeBeg = 0xff00000000ull; ++ const uptr kMadviseRangeSize = 0x0100000000ull; + #elif defined(__powerpc64__) + uptr kMadviseRangeBeg = 0; + uptr kMadviseRangeSize = 0; +diff --git a/libsanitizer/tsan/tsan_rtl.cc b/libsanitizer/tsan/tsan_rtl.cc +index 4a1f50061..8f9c48867 100644 +--- a/libsanitizer/tsan/tsan_rtl.cc ++++ b/libsanitizer/tsan/tsan_rtl.cc +@@ -224,7 +224,7 @@ static void StartBackgroundThread() { + ctx->background_thread = internal_start_thread(&BackgroundThread, 0); + } + +-#ifndef __mips__ ++#ifndef __mips__ || defined(__loongarch__) + static void StopBackgroundThread() { + atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed); + internal_join_thread(ctx->background_thread); +@@ -401,6 +401,20 @@ void Initialize(ThreadState *thr) { + OnInitialize(); + } + ++void MaybeSpawnBackgroundThread() { ++ // On MIPS, TSan initialization is run before ++ // __pthread_initialize_minimal_internal() is finished, so we can not spawn ++ // new threads. ++#if !SANITIZER_GO && !(defined(__mips__) || defined(__loongarch__)) ++ static atomic_uint32_t bg_thread = {}; ++ if (atomic_load(&bg_thread, memory_order_relaxed) == 0 && ++ atomic_exchange(&bg_thread, 1, memory_order_relaxed) == 0) { ++ StartBackgroundThread(); ++ SetSandboxingCallback(StopBackgroundThread); ++ } ++#endif ++} ++ + int Finalize(ThreadState *thr) { + bool failed = false; + +diff --git a/libsanitizer/tsan/tsan_rtl.h b/libsanitizer/tsan/tsan_rtl.h +index 7dd9779e4..6f8800003 100644 +--- a/libsanitizer/tsan/tsan_rtl.h ++++ b/libsanitizer/tsan/tsan_rtl.h +@@ -52,7 +52,8 @@ namespace __tsan { + + #if !SANITIZER_GO + struct MapUnmapCallback; +-#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) ++#if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__) \ ++ || defined(__loongarch64) + static const uptr kAllocatorRegionSizeLog = 20; + static const uptr kAllocatorNumRegions = + SANITIZER_MMAP_RANGE_SIZE >> kAllocatorRegionSizeLog; +diff --git a/libsanitizer/tsan/tsan_rtl_loongarch64.S b/libsanitizer/tsan/tsan_rtl_loongarch64.S +new file mode 100644 +index 000000000..9331e8afa +--- /dev/null ++++ b/libsanitizer/tsan/tsan_rtl_loongarch64.S +@@ -0,0 +1,156 @@ ++.section .text ++ ++.hidden __tsan_setjmp ++.comm _ZN14__interception11real_setjmpE,8,8 ++.globl setjmp ++.type setjmp, @function ++setjmp: ++ ++ # save env parameters ++ addi.d $r3,$r3,-24 ++ st.d $r1,$r3,16 ++ st.d $r22,$r3,8 ++ ++ # save jmp_buf ++ st.d $r4,$r3,0 ++ ++ # obtain $sp ++ add.d $r4,$r0,$r3 ++ ++ # call tsan interceptor ++ addi.d $r5,$r4,24 ++ bl __tsan_setjmp ++ ++ # restore jmp_buf ++ ld.d $r4,$r3,0 ++ ++ # load libc setjmp to r20 ++ la $r20,_ZN14__interception11real_setjmpE ++ # restore env parameters ++ ld.d $r22,$r3,8 ++ ld.d $r1,$r3,16 ++ addi.d $r3,$r3,24 ++ ++ # tail jump to libc setjmp ++ ld.d $r20,$r20,0 ++ jr $r20 ++ ++.size setjmp, .-setjmp ++ ++.hidden __tsan_setjmp ++.globl _setjmp ++.comm _ZN14__interception12real__setjmpE,8,8 ++.type _setjmp, @function ++_setjmp: ++ ++ # Save env parameters ++ addi.d $r3,$r3,-24 ++ st.d $r1,$r3,16 ++ st.d $r22,$r3,8 ++ ++ # save jmp_buf ++ st.d $r4,$r3,0 ++ ++ # obtain $sp ++ add.d $r4,$r0,$r3 ++ ++ # call tsan interceptor ++ addi.d $r5,$r4,24 ++ bl __tsan_setjmp ++ ++ # restore jmp_buf ++ ld.d $r4,$r3,0 ++ ++ # load libc _setjmp to r20 ++ la $r20,_ZN14__interception12real__setjmpE ++ ++ # restore env parameters ++ ld.d $r22,$r3,8 ++ ld.d $r1,$r3,16 ++ addi.d $r3,$r3,24 ++ ++ # tail jump to libc _setjmp ++ ld.d $r20,$r20,0 ++ jr $r20 ++ ++.size _setjmp, .-_setjmp ++ ++.hidden __tsan_setjmp ++.globl sigsetjmp ++.comm _ZN14__interception14real_sigsetjmpE,8,8 ++.type sigsetjmp, @function ++sigsetjmp: ++ ++ # Save env parameters ++ addi.d $r3,$r3,-32 ++ st.d $r1,$r3,24 ++ st.d $r22,$r3,16 ++ ++ # save jmp_buf and savesig ++ st.d $r4,$r3,0 ++ st.d $r5,$r3,8 ++ ++ # obtain $sp ++ add.d $r4,$r0,$r3 ++ ++ # call tsan interceptor ++ addi.d $r5,$r4,32 ++ bl __tsan_setjmp ++ ++ # restore jmp_buf and savesig ++ ld.d $r4,$r3,0 ++ ld.d $r5,$r3,8 ++ ++ # load libc sigsetjmp to r20 ++ la $r20,_ZN14__interception14real_sigsetjmpE ++ ++ # restore env parameters ++ ld.d $r22,$r3,16 ++ ld.d $r1,$r3,24 ++ addi.d $r3,$r3,32 ++ ++ # tail jump to libc sigsetjmp ++ ld.d $r20,$r20,0 ++ jr $r20 ++ ++.size sigsetjmp, .-sigsetjmp ++ ++.hidden __tsan_setjmp ++.comm _ZN14__interception16real___sigsetjmpE,8,8 ++.globl __sigsetjmp ++.type __sigsetjmp, @function ++__sigsetjmp: ++ ++ # Save env parameters ++ addi.d $sp,$sp,-32 ++ st.d $r1,$r3,24 ++ st.d $r22,$r3,16 ++ ++ # save jmp_buf and savesig ++ st.d $r4,$r3,0 ++ st.d $r5,$r3,8 ++ ++ # obtain $sp ++ add.d $r4,$r0,$r3 ++ ++ # call tsan interceptor ++ addi.d $r5,$r4,32 ++ bl __tsan_setjmp ++ ++ # restore jmp_buf and savesig ++ ld.d $r4,$r3,0 ++ ld.d $r5,$r3,8 ++ ++ # load libc __sigsetjmp in r20 ++ la $r20,_ZN14__interception16real___sigsetjmpE ++ ++ # restore env parameters ++ ld.d $r22,$r3,16 ++ ld.d $r1,$r3,24 ++ addi.d $r3,$r3,32 ++ ++ # tail jump to libc __sigsetjmp ++ ld.d $r20,$r20,0 ++ jr $r20 ++ ++.size __sigsetjmp, .-__sigsetjmp +-- +2.27.0 + diff --git a/0002-libitm-Add-LoongArch-support.patch b/0002-libitm-Add-LoongArch-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..ab8e3c3b76d297b6a01a65798e5c58f726d4efe8 --- /dev/null +++ b/0002-libitm-Add-LoongArch-support.patch @@ -0,0 +1,285 @@ +From f5eb627874fca6f35cc733caa761d9d76b2a0d8f Mon Sep 17 00:00:00 2001 +From: Xing Li +Date: Fri, 6 Jan 2023 10:44:00 +0800 +Subject: [PATCH 2/2] libitm: Add LoongArch support. + +Signed-off-by: Xing Li +Signed-off-by: Yang Yujie +--- + libitm/config/loongarch/asm.h | 54 +++++++++++++ + libitm/config/loongarch/sjlj.S | 130 +++++++++++++++++++++++++++++++ + libitm/config/loongarch/target.h | 50 ++++++++++++ + libitm/configure.tgt | 2 + + 4 files changed, 236 insertions(+) + create mode 100644 libitm/config/loongarch/asm.h + create mode 100644 libitm/config/loongarch/sjlj.S + create mode 100644 libitm/config/loongarch/target.h + +diff --git a/libitm/config/loongarch/asm.h b/libitm/config/loongarch/asm.h +new file mode 100644 +index 000000000..e7f881b03 +--- /dev/null ++++ b/libitm/config/loongarch/asm.h +@@ -0,0 +1,54 @@ ++/* Copyright (C) 2014-2018 Free Software Foundation, Inc. ++ Contributed by Loongson Co. Ltd. ++ ++ This file is part of the GNU Transactional Memory Library (libitm). ++ ++ Libitm is free software; you can redistribute it and/or modify it ++ under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY ++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ Under Section 7 of GPL version 3, you are granted additional ++ permissions described in the GCC Runtime Library Exception, version ++ 3.1, as published by the Free Software Foundation. ++ ++ You should have received a copy of the GNU General Public License and ++ a copy of the GCC Runtime Library Exception along with this program; ++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ++ . */ ++ ++#ifndef _LA_ASM_H ++#define _LA_ASM_H ++ ++#if defined(__loongarch64) ++# define GPR_L ld.d ++# define GPR_S st.d ++# define SZ_GPR 8 ++# define ADDSP(si) addi.d $sp, $sp, si ++#elif defined(__loongarch32) ++# define GPR_L ld.w ++# define GPR_S st.w ++# define SZ_GPR 4 ++# define ADDSP(si) addi.w $sp, $sp, si ++#else ++# error Unsupported GPR size (must be 64-bit or 32-bit). ++#endif ++ ++#if defined(__loongarch_hard_float) ++# define FPR_L fld.d ++# define FPR_S fst.d ++# define SZ_FPR 8 ++#elif defined(__loongarch_single_float) ++# define FPR_L fld.s ++# define FPR_S fst.s ++# define SZ_FPR 4 ++#else ++# define SZ_FPR 0 ++#endif ++ ++#endif /* _LA_ASM_H */ +diff --git a/libitm/config/loongarch/sjlj.S b/libitm/config/loongarch/sjlj.S +new file mode 100644 +index 000000000..e8610f9b5 +--- /dev/null ++++ b/libitm/config/loongarch/sjlj.S +@@ -0,0 +1,130 @@ ++/* Copyright (C) 2014-2018 Free Software Foundation, Inc. ++ Contributed by Loongson Co. Ltd. ++ ++ This file is part of the GNU Transactional Memory Library (libitm). ++ ++ Libitm is free software; you can redistribute it and/or modify it ++ under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY ++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. ++ ++ Under Section 7 of GPL version 3, you are granted additional ++ permissions described in the GCC Runtime Library Exception, version ++ 3.1, as published by the Free Software Foundation. ++ ++ You should have received a copy of the GNU General Public License and ++ a copy of the GCC Runtime Library Exception along with this program; ++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ++ . */ ++ ++#include "asmcfi.h" ++#include "asm.h" ++ ++ .text ++ .align 2 ++ .global _ITM_beginTransaction ++ .type _ITM_beginTransaction, @function ++ ++_ITM_beginTransaction: ++ cfi_startproc ++ move $r5, $sp ++ ADDSP(-(12*SZ_GPR+8*SZ_FPR)) ++ cfi_adjust_cfa_offset(12*SZ_GPR+8*SZ_FPR) ++ ++ /* Frame Pointer */ ++ GPR_S $fp, $sp, 0*SZ_GPR ++ cfi_rel_offset(22, 0) ++ ++ /* Return Address */ ++ GPR_S $r1, $sp, 1*SZ_GPR ++ cfi_rel_offset(1, SZ_GPR) ++ ++ /* Caller's $sp */ ++ GPR_S $r5, $sp, 2*SZ_GPR ++ ++ /* Callee-saved scratch GPRs (r23-r31) */ ++ GPR_S $s0, $sp, 3*SZ_GPR ++ GPR_S $s1, $sp, 4*SZ_GPR ++ GPR_S $s2, $sp, 5*SZ_GPR ++ GPR_S $s3, $sp, 6*SZ_GPR ++ GPR_S $s4, $sp, 7*SZ_GPR ++ GPR_S $s5, $sp, 8*SZ_GPR ++ GPR_S $s6, $sp, 9*SZ_GPR ++ GPR_S $s7, $sp, 10*SZ_GPR ++ GPR_S $s8, $sp, 11*SZ_GPR ++ ++#if !defined(__loongarch_soft_float) ++ /* Callee-saved scratch FPRs (f24-f31) */ ++ FPR_S $f24, $sp, 12*SZ_GPR + 0*SZ_FPR ++ FPR_S $f25, $sp, 12*SZ_GPR + 1*SZ_FPR ++ FPR_S $f26, $sp, 12*SZ_GPR + 2*SZ_FPR ++ FPR_S $f27, $sp, 12*SZ_GPR + 3*SZ_FPR ++ FPR_S $f28, $sp, 12*SZ_GPR + 4*SZ_FPR ++ FPR_S $f29, $sp, 12*SZ_GPR + 5*SZ_FPR ++ FPR_S $f30, $sp, 12*SZ_GPR + 6*SZ_FPR ++ FPR_S $f31, $sp, 12*SZ_GPR + 7*SZ_FPR ++#endif ++ move $fp, $sp ++ ++ /* Invoke GTM_begin_transaction with the struct we've just built. */ ++ move $r5, $sp ++ bl %plt(GTM_begin_transaction) ++ ++ /* Return. (no call-saved scratch reg needs to be restored here) */ ++ GPR_L $fp, $sp, 0*SZ_GPR ++ cfi_restore(22) ++ GPR_L $r1, $sp, 1*SZ_GPR ++ cfi_restore(1) ++ ++ ADDSP(12*SZ_GPR+8*SZ_FPR) ++ cfi_adjust_cfa_offset(-(12*SZ_GPR+8*SZ_FPR)) ++ ++ jr $r1 ++ cfi_endproc ++ .size _ITM_beginTransaction, . - _ITM_beginTransaction ++ ++ .align 2 ++ .global GTM_longjmp ++ .hidden GTM_longjmp ++ .type GTM_longjmp, @function ++ ++GTM_longjmp: ++ cfi_startproc ++ GPR_L $s0, $r5, 3*SZ_GPR ++ GPR_L $s1, $r5, 4*SZ_GPR ++ GPR_L $s2, $r5, 5*SZ_GPR ++ GPR_L $s3, $r5, 6*SZ_GPR ++ GPR_L $s4, $r5, 7*SZ_GPR ++ GPR_L $s5, $r5, 8*SZ_GPR ++ GPR_L $s6, $r5, 9*SZ_GPR ++ GPR_L $s7, $r5, 10*SZ_GPR ++ GPR_L $s8, $r5, 11*SZ_GPR ++ ++#if !defined(__loongarch_soft_float) ++ /* Callee-saved scratch FPRs (f24-f31) */ ++ FPR_L $f24, $r5, 12*SZ_GPR + 0*SZ_FPR ++ FPR_L $f25, $r5, 12*SZ_GPR + 1*SZ_FPR ++ FPR_L $f26, $r5, 12*SZ_GPR + 2*SZ_FPR ++ FPR_L $f27, $r5, 12*SZ_GPR + 3*SZ_FPR ++ FPR_L $f28, $r5, 12*SZ_GPR + 4*SZ_FPR ++ FPR_L $f29, $r5, 12*SZ_GPR + 5*SZ_FPR ++ FPR_L $f30, $r5, 12*SZ_GPR + 6*SZ_FPR ++ FPR_L $f31, $r5, 12*SZ_GPR + 7*SZ_FPR ++#endif ++ ++ GPR_L $r7, $r5, 2*SZ_GPR ++ GPR_L $fp, $r5, 0*SZ_GPR ++ GPR_L $r1, $r5, 1*SZ_GPR ++ cfi_def_cfa(5, 0) ++ move $sp, $r7 ++ jr $r1 ++ cfi_endproc ++ .size GTM_longjmp, . - GTM_longjmp ++ ++#ifdef __linux__ ++.section .note.GNU-stack, "", @progbits ++#endif +diff --git a/libitm/config/loongarch/target.h b/libitm/config/loongarch/target.h +new file mode 100644 +index 000000000..2853bf203 +--- /dev/null ++++ b/libitm/config/loongarch/target.h +@@ -0,0 +1,50 @@ ++/* Copyright (C) 2014-2018 Free Software Foundation, Inc. ++ Contributed by Loongson Co. Ltd. ++ ++ This file is part of the GNU Transactional Memory Library (libitm). ++ ++ Libitm is free software; you can redistribute it and/or modify it ++ under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ Libitm is distributed in the hope that it will be useful, but WITHOUT ANY ++ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS ++ FOR A PARTICULAR PURPOSE. See the GNU General Public License for ++ more details. ++ ++ Under Section 7 of GPL version 3, you are granted additional ++ permissions described in the GCC Runtime Library Exception, version ++ 3.1, as published by the Free Software Foundation. ++ ++ You should have received a copy of the GNU General Public License and ++ a copy of the GCC Runtime Library Exception along with this program; ++ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ++ . */ ++ ++namespace GTM HIDDEN { ++ ++typedef struct gtm_jmpbuf ++ { ++ long int fp; /* Frame Pointer: r22 */ ++ long int pc; /* Return Address: r1 */ ++ void *cfa; /* CFA: r3 */ ++ long int gpr[9]; /* Callee-saved scratch GPRs: r23(s0)-r31(s8) */ ++ ++ /* Callee-saved scratch FPRs: f24-f31 */ ++#if defined(__loongarch_double_float) ++ double fpr[8]; ++#elif defined(__loongarch_single_float) ++ float fpr[8]; ++#endif ++ } gtm_jmpbuf; ++ ++#define HW_CACHELINE_SIZE 128 ++ ++static inline void ++cpu_relax (void) ++{ ++ __asm__ volatile ("" : : : "memory"); ++} ++ ++} // namespace GTM +diff --git a/libitm/configure.tgt b/libitm/configure.tgt +index 0cbb0974d..18a06e45f 100644 +--- a/libitm/configure.tgt ++++ b/libitm/configure.tgt +@@ -69,6 +69,8 @@ case "${target_cpu}" in + ARCH=x86 + ;; + ++ loongarch*) ARCH=loongarch ;; ++ + sh*) ARCH=sh ;; + + sparc) +-- +2.27.0 + diff --git a/gcc.spec b/gcc.spec index b4e229fbf1a6cf6349b60effdeec76b9b1030708..79c5d2a13056e9c32a73bbc2789986b14d12f706 100644 --- a/gcc.spec +++ b/gcc.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.3 +%define anolis_release .0.4 %global DATE 20210514 %global gitrev a3253c88425835d5b339d6998a1110a66ccd8b44 %global gcc_version 8.5.0 @@ -39,22 +39,22 @@ %else %global build_libquadmath 0 %endif -%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 +%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 loongarch64 %global build_libasan 1 %else %global build_libasan 0 %endif -%ifarch x86_64 ppc64 ppc64le aarch64 +%ifarch x86_64 ppc64 ppc64le aarch64 loongarch64 %global build_libtsan 1 %else %global build_libtsan 0 %endif -%ifarch x86_64 ppc64 ppc64le aarch64 +%ifarch x86_64 ppc64 ppc64le aarch64 loongarch64 %global build_liblsan 1 %else %global build_liblsan 0 %endif -%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 +%ifarch %{ix86} x86_64 ppc ppc64 ppc64le ppc64p7 s390 s390x %{arm} aarch64 loongarch64 %global build_libubsan 1 %else %global build_libubsan 0 @@ -64,7 +64,7 @@ %else %global build_libatomic 0 %endif -%ifarch %{ix86} x86_64 %{arm} alpha ppc ppc64 ppc64le ppc64p7 s390 s390x aarch64 +%ifarch %{ix86} x86_64 %{arm} alpha ppc ppc64 ppc64le ppc64p7 s390 s390x aarch64 loongarch64 %global build_libitm 1 %else %global build_libitm 0 @@ -304,6 +304,8 @@ Patch1004: 0002-loongarch-fix-multilib-osdirnames-to-lib64.patch Patch1005: 0001-LoongArch-Fixup-configure-file-error.patch Patch1006: 0002-LoongArch-Rename-config-file-for-loongarch.patch Patch1007: LoongArch-Fix-atomic_exchange-expanding-PR107713.patch +Patch1008: 0001-libsanitizer-Add-LoongArch-support.patch +Patch1009: 0002-libitm-Add-LoongArch-support.patch # On ARM EABI systems, we do want -gnueabi to be part of the @@ -934,6 +936,8 @@ rm -f gcc/testsuite/go.test/test/chan/goroutines.go %patch1005 -p1 %patch1006 -p1 %patch1007 -p1 +%patch1008 -p1 +%patch1009 -p1 %endif %build @@ -3240,6 +3244,10 @@ fi %endif %changelog +* Fri Jan 6 2023 Xing Li 8.5.0-10.1.0.4 +- Add libsanitizer support for LoongArch (lixing@loongson.cn) +- Add libitm support for LoongArch. (lixing@loongson.cn) + * Fri Dec 2 2022 Xing Li 8.5.0-10.1.0.3 - rename mt file for LoongArch. (lixing@loongson.cn) - Fixup LoongArch atomic_exchange error. (lixing@loongson.cn)