iii updated this revision to Diff 358431.
iii added a comment.
- Fix style issues (seems like arc diff is linting only the top commit?).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D105629/new/
https://reviews.llvm.org/D105629
Files:
clang/lib/Driver/ToolChains/Linux.cpp
compiler-rt/cmake/config-ix.cmake
compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
compiler-rt/lib/tsan/CMakeLists.txt
compiler-rt/lib/tsan/go/buildgo.sh
compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
compiler-rt/lib/tsan/rtl/tsan_interface.h
compiler-rt/lib/tsan/rtl/tsan_platform.h
compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp
compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S
compiler-rt/test/tsan/CMakeLists.txt
compiler-rt/test/tsan/ignore_lib0.cpp
compiler-rt/test/tsan/ignore_lib1.cpp
compiler-rt/test/tsan/ignore_lib5.cpp
compiler-rt/test/tsan/map32bit.cpp
compiler-rt/test/tsan/mmap_large.cpp
llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn
Index: llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn
+++ llvm/utils/gn/secondary/compiler-rt/lib/tsan/BUILD.gn
@@ -125,6 +125,8 @@
sources += [ "rtl/tsan_rtl_ppc64.S" ]
} else if (target_cpu == "mips64") {
sources += [ "rtl/tsan_rtl_mips64.S" ]
+ } else if (target_cpu == "s390x") {
+ sources += [ "rtl/tsan_rtl_s390x.S" ]
}
# To be able to include sanitizer_common.
Index: llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
+++ llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp
@@ -312,12 +312,21 @@
Type *Ty = Type::getIntNTy(M.getContext(), BitSize);
Type *PtrTy = Ty->getPointerTo();
SmallString<32> AtomicLoadName("__tsan_atomic" + BitSizeStr + "_load");
- TsanAtomicLoad[i] =
- M.getOrInsertFunction(AtomicLoadName, Attr, Ty, PtrTy, OrdTy);
+ {
+ AttributeList AL = Attr;
+ AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
+ TsanAtomicLoad[i] =
+ M.getOrInsertFunction(AtomicLoadName, AL, Ty, PtrTy, OrdTy);
+ }
SmallString<32> AtomicStoreName("__tsan_atomic" + BitSizeStr + "_store");
- TsanAtomicStore[i] = M.getOrInsertFunction(
- AtomicStoreName, Attr, IRB.getVoidTy(), PtrTy, Ty, OrdTy);
+ {
+ AttributeList AL = Attr;
+ AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
+ AL = AL.addParamAttribute(M.getContext(), 2, Attribute::ZExt);
+ TsanAtomicStore[i] = M.getOrInsertFunction(
+ AtomicStoreName, AL, IRB.getVoidTy(), PtrTy, Ty, OrdTy);
+ }
for (unsigned Op = AtomicRMWInst::FIRST_BINOP;
Op <= AtomicRMWInst::LAST_BINOP; ++Op) {
@@ -340,24 +349,44 @@
else
continue;
SmallString<32> RMWName("__tsan_atomic" + itostr(BitSize) + NamePart);
- TsanAtomicRMW[Op][i] =
- M.getOrInsertFunction(RMWName, Attr, Ty, PtrTy, Ty, OrdTy);
+ {
+ AttributeList AL = Attr;
+ AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
+ AL = AL.addParamAttribute(M.getContext(), 2, Attribute::ZExt);
+ TsanAtomicRMW[Op][i] =
+ M.getOrInsertFunction(RMWName, AL, Ty, PtrTy, Ty, OrdTy);
+ }
}
SmallString<32> AtomicCASName("__tsan_atomic" + BitSizeStr +
"_compare_exchange_val");
- TsanAtomicCAS[i] = M.getOrInsertFunction(AtomicCASName, Attr, Ty, PtrTy, Ty,
- Ty, OrdTy, OrdTy);
+ {
+ AttributeList AL = Attr;
+ AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
+ AL = AL.addParamAttribute(M.getContext(), 2, Attribute::ZExt);
+ AL = AL.addParamAttribute(M.getContext(), 3, Attribute::ZExt);
+ AL = AL.addParamAttribute(M.getContext(), 4, Attribute::ZExt);
+ TsanAtomicCAS[i] = M.getOrInsertFunction(AtomicCASName, AL, Ty, PtrTy, Ty,
+ Ty, OrdTy, OrdTy);
+ }
}
TsanVptrUpdate =
M.getOrInsertFunction("__tsan_vptr_update", Attr, IRB.getVoidTy(),
IRB.getInt8PtrTy(), IRB.getInt8PtrTy());
TsanVptrLoad = M.getOrInsertFunction("__tsan_vptr_read", Attr,
IRB.getVoidTy(), IRB.getInt8PtrTy());
- TsanAtomicThreadFence = M.getOrInsertFunction("__tsan_atomic_thread_fence",
- Attr, IRB.getVoidTy(), OrdTy);
- TsanAtomicSignalFence = M.getOrInsertFunction("__tsan_atomic_signal_fence",
- Attr, IRB.getVoidTy(), OrdTy);
+ {
+ AttributeList AL = Attr;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ TsanAtomicThreadFence = M.getOrInsertFunction("__tsan_atomic_thread_fence",
+ AL, IRB.getVoidTy(), OrdTy);
+ }
+ {
+ AttributeList AL = Attr;
+ AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
+ TsanAtomicSignalFence = M.getOrInsertFunction("__tsan_atomic_signal_fence",
+ AL, IRB.getVoidTy(), OrdTy);
+ }
MemmoveFn =
M.getOrInsertFunction("memmove", Attr, IRB.getInt8PtrTy(),
Index: compiler-rt/test/tsan/mmap_large.cpp
===================================================================
--- compiler-rt/test/tsan/mmap_large.cpp
+++ compiler-rt/test/tsan/mmap_large.cpp
@@ -21,6 +21,8 @@
const size_t kLog2Size = 32;
#elif defined(__powerpc64__)
const size_t kLog2Size = 39;
+#elif defined(__s390x__)
+ const size_t kLog2Size = 43;
#endif
const uintptr_t kLocation = 0x40ULL << kLog2Size;
void *p = mmap(
Index: compiler-rt/test/tsan/map32bit.cpp
===================================================================
--- compiler-rt/test/tsan/map32bit.cpp
+++ compiler-rt/test/tsan/map32bit.cpp
@@ -11,6 +11,7 @@
// XFAIL: mips
// XFAIL: aarch64
// XFAIL: powerpc64
+// XFAIL: s390x
// MAP_32BIT doesn't exist on OS X and NetBSD.
// UNSUPPORTED: darwin,netbsd
Index: compiler-rt/test/tsan/ignore_lib5.cpp
===================================================================
--- compiler-rt/test/tsan/ignore_lib5.cpp
+++ compiler-rt/test/tsan/ignore_lib5.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t-dir
// RUN: mkdir %t-dir
-// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so
+// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so
// RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable
// RUN: echo running w/o suppressions:
// RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP
Index: compiler-rt/test/tsan/ignore_lib1.cpp
===================================================================
--- compiler-rt/test/tsan/ignore_lib1.cpp
+++ compiler-rt/test/tsan/ignore_lib1.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t-dir
// RUN: mkdir %t-dir
-// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so
+// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib1.so
// RUN: %clangxx_tsan -O1 %s %link_libcxx_tsan -o %t-dir/executable
// RUN: echo running w/o suppressions:
// RUN: %deflake %run %t-dir/executable | FileCheck %s --check-prefix=CHECK-NOSUPP
Index: compiler-rt/test/tsan/ignore_lib0.cpp
===================================================================
--- compiler-rt/test/tsan/ignore_lib0.cpp
+++ compiler-rt/test/tsan/ignore_lib0.cpp
@@ -1,7 +1,7 @@
// RUN: rm -rf %t-dir
// RUN: mkdir %t-dir
-// RUN: %clangxx_tsan -O1 %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so
+// RUN: %clangxx_tsan -O1 -fno-builtin %s -DLIB -fPIC -fno-sanitize=thread -shared -o %t-dir/libignore_lib0.so
// RUN: %clangxx_tsan -O1 %s -L%t-dir -lignore_lib0 %link_libcxx_tsan -o %t
// RUN: echo running w/o suppressions:
// RUN: env LD_LIBRARY_PATH=%t-dir${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %deflake %run %t | FileCheck %s --check-prefix=CHECK-NOSUPP
Index: compiler-rt/test/tsan/CMakeLists.txt
===================================================================
--- compiler-rt/test/tsan/CMakeLists.txt
+++ compiler-rt/test/tsan/CMakeLists.txt
@@ -1,7 +1,7 @@
set(TSAN_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(TSAN_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS})
-if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "x86_64")
+if(${COMPILER_RT_DEFAULT_TARGET_ARCH} MATCHES "(x86_64|s390x)")
list(APPEND TSAN_TEST_DEPS GotsanRuntimeCheck)
endif()
if(NOT COMPILER_RT_STANDALONE_BUILD)
Index: compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S
===================================================================
--- /dev/null
+++ compiler-rt/lib/tsan/rtl/tsan_rtl_s390x.S
@@ -0,0 +1,47 @@
+#include "sanitizer_common/sanitizer_asm.h"
+
+#define CFA_OFFSET 160
+#define R2_REL_OFFSET 16
+#define R3_REL_OFFSET 24
+#define R14_REL_OFFSET 112
+#define R15_REL_OFFSET 120
+#define FRAME_SIZE 160
+
+.text
+
+ASM_HIDDEN(__tsan_setjmp)
+
+.macro intercept symbol, real
+.comm \real, 8, 8
+.globl ASM_SYMBOL_INTERCEPTOR(\symbol)
+ASM_TYPE_FUNCTION(ASM_SYMBOL_INTERCEPTOR(\symbol))
+ASM_SYMBOL_INTERCEPTOR(\symbol):
+ CFI_STARTPROC
+ stmg %r2, %r3, R2_REL_OFFSET(%r15)
+ CFI_REL_OFFSET(%r2, R2_REL_OFFSET)
+ CFI_REL_OFFSET(%r3, R3_REL_OFFSET)
+ stmg %r14, %r15, R14_REL_OFFSET(%r15)
+ CFI_REL_OFFSET(%r14, R14_REL_OFFSET)
+ CFI_REL_OFFSET(%r15, R15_REL_OFFSET)
+ aghi %r15, -FRAME_SIZE
+ CFI_ADJUST_CFA_OFFSET(FRAME_SIZE)
+ la %r2, FRAME_SIZE(%r15)
+ brasl %r14, ASM_SYMBOL(__tsan_setjmp)
+ lmg %r14, %r15, FRAME_SIZE + R14_REL_OFFSET(%r15)
+ CFI_RESTORE(%r14)
+ CFI_RESTORE(%r15)
+ CFI_DEF_CFA_OFFSET(CFA_OFFSET)
+ lmg %r2, %r3, R2_REL_OFFSET(%r15)
+ CFI_RESTORE(%r2)
+ CFI_RESTORE(%r3)
+ larl %r1, \real
+ lg %r1, 0(%r1)
+ br %r1
+ CFI_ENDPROC
+ ASM_SIZE(ASM_SYMBOL_INTERCEPTOR(\symbol))
+.endm
+
+intercept setjmp, _ZN14__interception11real_setjmpE
+intercept _setjmp, _ZN14__interception12real__setjmpE
+intercept sigsetjmp, _ZN14__interception14real_sigsetjmpE
+intercept __sigsetjmp, _ZN14__interception16real___sigsetjmpE
Index: compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -77,7 +77,7 @@
}
#endif
-static char thread_registry_placeholder[sizeof(ThreadRegistry)];
+static ALIGNED(64) char thread_registry_placeholder[sizeof(ThreadRegistry)];
static ThreadContextBase *CreateThreadContext(u32 tid) {
// Map thread trace when context is created.
Index: compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp
@@ -72,11 +72,15 @@
InitializeShadowMemoryPlatform();
}
-static void ProtectRange(uptr beg, uptr end) {
+static bool TryProtectRange(uptr beg, uptr end) {
CHECK_LE(beg, end);
if (beg == end)
- return;
- if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) {
+ return true;
+ return beg == (uptr)MmapFixedNoAccess(beg, end - beg);
+}
+
+static void ProtectRange(uptr beg, uptr end) {
+ if (!TryProtectRange(beg, end)) {
Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
Printf("FATAL: Make sure you are not using unlimited stack\n");
Die();
@@ -118,6 +122,16 @@
ProtectRange(TraceMemEnd(), HeapMemBeg());
ProtectRange(HeapEnd(), HiAppMemBeg());
#endif
+
+#if defined(__s390x__)
+ // Protect the rest of the address space.
+ const uptr user_addr_max_l4 = 0x0020000000000000ull;
+ const uptr user_addr_max_l5 = 0xfffffffffffff000ull;
+ // All the maintained s390x kernels support at least 4-level page tables.
+ ProtectRange(HiAppMemEnd(), user_addr_max_l4);
+ // Older s390x kernels may not support 5-level page tables.
+ TryProtectRange(user_addr_max_l4, user_addr_max_l5);
+#endif
}
#endif
Index: compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -391,6 +391,10 @@
return mangled_sp ^ xor_key;
#elif defined(__mips__)
return mangled_sp;
+#elif defined(__s390x__)
+ // tcbhead_t.stack_guard
+ uptr xor_key = ((uptr *)__builtin_thread_pointer())[5];
+ return mangled_sp ^ xor_key;
#else
#error "Unknown platform"
#endif
@@ -411,6 +415,8 @@
# define LONG_JMP_SP_ENV_SLOT 13
# elif defined(__mips64)
# define LONG_JMP_SP_ENV_SLOT 1
+# elif defined(__s390x__)
+# define LONG_JMP_SP_ENV_SLOT 9
# else
# define LONG_JMP_SP_ENV_SLOT 6
# endif
Index: compiler-rt/lib/tsan/rtl/tsan_platform.h
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -365,6 +365,38 @@
// Indicates the runtime will define the memory regions at runtime.
#define TSAN_RUNTIME_VMA 1
+#elif defined(__s390x__)
+/*
+C/C++ on linux/s390x
+While the kernel provides a 64-bit address space, we have to restrict ourselves
+to 48 bits due to how e.g. SyncVar::GetId() works.
+0000 0000 1000 - 0e00 0000 0000: binary, modules, stacks - 14 TiB
+0e00 0000 0000 - 4000 0000 0000: -
+4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app)
+8000 0000 0000 - 9000 0000 0000: -
+9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app)
+9800 0000 0000 - a000 0000 0000: -
+a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads)
+b000 0000 0000 - be00 0000 0000: -
+be00 0000 0000 - c000 0000 0000: heap - 2TiB (max supported by the allocator)
+*/
+struct Mapping {
+ static const uptr kMetaShadowBeg = 0x900000000000ull;
+ static const uptr kMetaShadowEnd = 0x980000000000ull;
+ static const uptr kTraceMemBeg = 0xa00000000000ull;
+ static const uptr kTraceMemEnd = 0xb00000000000ull;
+ static const uptr kShadowBeg = 0x400000000000ull;
+ static const uptr kShadowEnd = 0x800000000000ull;
+ static const uptr kHeapMemBeg = 0xbe0000000000ull;
+ static const uptr kHeapMemEnd = 0xc00000000000ull;
+ static const uptr kLoAppMemBeg = 0x000000001000ull;
+ static const uptr kLoAppMemEnd = 0x0e0000000000ull;
+ static const uptr kHiAppMemBeg = 0xc00000004000ull;
+ static const uptr kHiAppMemEnd = 0xc00000004000ull;
+ static const uptr kAppMemMsk = 0xb00000000000ull;
+ static const uptr kAppMemXor = 0x100000000000ull;
+ static const uptr kVdsoBeg = 0xfffffffff000ull;
+};
#endif
#elif SANITIZER_GO && !SANITIZER_WINDOWS && HAS_48_BIT_ADDRESS_SPACE
@@ -528,6 +560,28 @@
#define TSAN_RUNTIME_VMA 1
+#elif SANITIZER_GO && defined(__s390x__)
+/*
+Go on linux/s390x
+0000 0000 1000 - 1000 0000 0000: executable and heap - 16 TiB
+1000 0000 0000 - 4000 0000 0000: -
+4000 0000 0000 - 8000 0000 0000: shadow - 64TiB (4 * app)
+8000 0000 0000 - 9000 0000 0000: -
+9000 0000 0000 - 9800 0000 0000: metainfo - 8TiB (0.5 * app)
+9800 0000 0000 - a000 0000 0000: -
+a000 0000 0000 - b000 0000 0000: traces - 16TiB (max history * 128k threads)
+*/
+struct Mapping {
+ static const uptr kMetaShadowBeg = 0x900000000000ull;
+ static const uptr kMetaShadowEnd = 0x980000000000ull;
+ static const uptr kTraceMemBeg = 0xa00000000000ull;
+ static const uptr kTraceMemEnd = 0xb00000000000ull;
+ static const uptr kShadowBeg = 0x400000000000ull;
+ static const uptr kShadowEnd = 0x800000000000ull;
+ static const uptr kAppMemBeg = 0x000000001000ull;
+ static const uptr kAppMemEnd = 0x100000000000ull;
+};
+
#else
# error "Unknown platform"
#endif
Index: compiler-rt/lib/tsan/rtl/tsan_interface.h
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_interface.h
+++ compiler-rt/lib/tsan/rtl/tsan_interface.h
@@ -196,7 +196,8 @@
typedef unsigned int a32;
typedef unsigned long long a64;
#if !SANITIZER_GO && (defined(__SIZEOF_INT128__) \
- || (__clang_major__ * 100 + __clang_minor__ >= 302)) && !defined(__mips64)
+ || (__clang_major__ * 100 + __clang_minor__ >= 302)) && \
+ !defined(__mips64) && !defined(__s390x__)
__extension__ typedef __int128 a128;
# define __TSAN_HAS_INT128 1
#else
Index: compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -71,7 +71,8 @@
};
#endif
-#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1
+#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
+ defined(__s390x__)
#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
#elif defined(__aarch64__) || SANITIZER_PPC64V2
#define PTHREAD_ABI_BASE "GLIBC_2.17"
@@ -2270,6 +2271,7 @@
#define NEED_TLS_GET_ADDR
#endif
#undef SANITIZER_INTERCEPT_TLS_GET_ADDR
+#define SANITIZER_INTERCEPT_TLS_GET_OFFSET 1
#undef SANITIZER_INTERCEPT_PTHREAD_SIGMASK
#define COMMON_INTERCEPT_FUNCTION(name) INTERCEPT_FUNCTION(name)
@@ -2585,6 +2587,20 @@
#include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
#ifdef NEED_TLS_GET_ADDR
+
+static void handle_tls_addr(void *arg, void *res) {
+ ThreadState *thr = cur_thread();
+ if (!thr)
+ return;
+ DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
+ thr->tls_addr + thr->tls_size);
+ if (!dtv)
+ return;
+ // New DTLS block has been allocated.
+ MemoryResetRange(thr, 0, dtv->beg, dtv->size);
+}
+
+#if !SANITIZER_S390
// Define own interceptor instead of sanitizer_common's for three reasons:
// 1. It must not process pending signals.
// Signal handlers may contain MOVDQA instruction (see below).
@@ -2597,18 +2613,18 @@
// execute MOVDQA with stack addresses.
TSAN_INTERCEPTOR(void *, __tls_get_addr, void *arg) {
void *res = REAL(__tls_get_addr)(arg);
- ThreadState *thr = cur_thread();
- if (!thr)
- return res;
- DTLS::DTV *dtv = DTLS_on_tls_get_addr(arg, res, thr->tls_addr,
- thr->tls_addr + thr->tls_size);
- if (!dtv)
- return res;
- // New DTLS block has been allocated.
- MemoryResetRange(thr, 0, dtv->beg, dtv->size);
+ handle_tls_addr(arg, res);
+ return res;
+}
+#else // SANITIZER_S390
+TSAN_INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
+ uptr res = __tls_get_offset_wrapper(arg, REAL(__tls_get_offset));
+ char *tp = static_cast<char *>(__builtin_thread_pointer());
+ handle_tls_addr(arg, res + tp);
return res;
}
#endif
+#endif
#if SANITIZER_NETBSD
TSAN_INTERCEPTOR(void, _lwp_exit) {
@@ -2830,7 +2846,12 @@
TSAN_INTERCEPT(_exit);
#ifdef NEED_TLS_GET_ADDR
+#if !SANITIZER_S390
TSAN_INTERCEPT(__tls_get_addr);
+#else
+ TSAN_INTERCEPT(__tls_get_addr_internal);
+ TSAN_INTERCEPT(__tls_get_offset);
+#endif
#endif
TSAN_MAYBE_INTERCEPT__LWP_EXIT;
Index: compiler-rt/lib/tsan/go/buildgo.sh
===================================================================
--- compiler-rt/lib/tsan/go/buildgo.sh
+++ compiler-rt/lib/tsan/go/buildgo.sh
@@ -72,6 +72,10 @@
SUFFIX="linux_mips64"
ARCHCFLAGS="-mips64 -EB"
fi
+ elif [ "`uname -a | grep s390x`" != "" ]; then
+ SRCS="$SRCS ../../sanitizer_common/sanitizer_linux_s390.cpp"
+ SUFFIX="linux_s390x"
+ ARCHCFLAGS=""
fi
elif [ "`uname -a | grep FreeBSD`" != "" ]; then
# The resulting object still depends on libc.
Index: compiler-rt/lib/tsan/CMakeLists.txt
===================================================================
--- compiler-rt/lib/tsan/CMakeLists.txt
+++ compiler-rt/lib/tsan/CMakeLists.txt
@@ -219,6 +219,20 @@
add_asm_sources(TSAN_ASM_SOURCES
rtl/tsan_rtl_mips64.S
)
+ elseif(arch MATCHES "s390x")
+ add_asm_sources(TSAN_ASM_SOURCES
+ rtl/tsan_rtl_s390x.S
+ )
+ # Sanity check for Go runtime.
+ set(BUILDGO_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/go/buildgo.sh)
+ add_custom_target(GotsanRuntimeCheck
+ COMMAND env "CC=${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}"
+ EXTRA_CFLAGS=${EXTRA_CFLAGS}
+ IN_TMPDIR=1 SILENT=1 ${BUILDGO_SCRIPT}
+ DEPENDS clang_rt.tsan-${arch} ${BUILDGO_SCRIPT}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/go
+ COMMENT "Checking TSan Go runtime..."
+ VERBATIM)
else()
set(TSAN_ASM_SOURCES)
endif()
Index: compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -650,14 +650,14 @@
#endif // !SANITIZER_ANDROID
#if defined(__mips__)
-struct __sanitizer_kernel_sigset_t {
- uptr sig[2];
-};
+#define __SANITIZER_KERNEL_NSIG 128
#else
+#define __SANITIZER_KERNEL_NSIG 64
+#endif
+
struct __sanitizer_kernel_sigset_t {
- u8 sig[8];
+ uptr sig[__SANITIZER_KERNEL_NSIG / (sizeof(uptr) * 8)];
};
-#endif
// Linux system headers define the 'sa_handler' and 'sa_sigaction' macros.
#if SANITIZER_MIPS
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux_libcdep.cpp
@@ -317,21 +317,44 @@
};
} // namespace
+#ifdef __s390__
+extern "C" uptr __tls_get_offset(void *arg);
+
+static uptr TlsGetOffset(uptr ti_module, uptr ti_offset) {
+ // The __tls_get_offset ABI requires %r12 to point to GOT and %r2 to be an
+ // offset of a struct tls_index inside GOT. We don't possess either of the
+ // two, so violate the letter of the "ELF Handling For Thread-Local
+ // Storage" document and assume that the implementation just dereferences
+ // %r2 + %r12.
+ uptr tls_index[2] = {ti_module, ti_offset};
+ register uptr r2 asm("2") = 0;
+ register void *r12 asm("12") = tls_index;
+ asm("basr %%r14, %[__tls_get_offset]"
+ : "+r"(r2)
+ : [__tls_get_offset] "r"(__tls_get_offset), "r"(r12)
+ : "memory", "cc", "0", "1", "3", "4", "5", "14");
+ return r2;
+}
+#else
extern "C" void *__tls_get_addr(size_t *);
+#endif
static int CollectStaticTlsBlocks(struct dl_phdr_info *info, size_t size,
void *data) {
if (!info->dlpi_tls_modid)
return 0;
uptr begin = (uptr)info->dlpi_tls_data;
-#ifndef __s390__
if (!g_use_dlpi_tls_data) {
// Call __tls_get_addr as a fallback. This forces TLS allocation on glibc
// and FreeBSD.
+#ifdef __s390__
+ begin = (uptr)__builtin_thread_pointer() +
+ TlsGetOffset(info->dlpi_tls_modid, 0);
+#else
size_t mod_and_off[2] = {info->dlpi_tls_modid, 0};
begin = (uptr)__tls_get_addr(mod_and_off);
- }
#endif
+ }
for (unsigned i = 0; i != info->dlpi_phnum; ++i)
if (info->dlpi_phdr[i].p_type == PT_TLS) {
static_cast<InternalMmapVector<TlsBlock> *>(data)->push_back(
Index: compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -878,7 +878,7 @@
__sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
- k_set->sig[idx] &= ~(1 << bit);
+ k_set->sig[idx] &= ~((uptr)1 << bit);
}
bool internal_sigismember(__sanitizer_sigset_t *set, int signum) {
@@ -888,7 +888,7 @@
__sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set;
const uptr idx = signum / (sizeof(k_set->sig[0]) * 8);
const uptr bit = signum % (sizeof(k_set->sig[0]) * 8);
- return k_set->sig[idx] & (1 << bit);
+ return k_set->sig[idx] & ((uptr)1 << bit);
}
#elif SANITIZER_FREEBSD
void internal_sigdelset(__sanitizer_sigset_t *set, int signum) {
Index: compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
===================================================================
--- compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
+++ compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc
@@ -5303,6 +5303,12 @@
#define INIT_TIMES
#endif
+#if SANITIZER_S390 && \
+ (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
+extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
+DEFINE_REAL(uptr, __tls_get_offset, void *arg)
+#endif
+
#if SANITIZER_INTERCEPT_TLS_GET_ADDR
#if !SANITIZER_S390
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_addr)
@@ -5342,11 +5348,7 @@
// descriptor offset as an argument instead of a pointer. GOT address
// is passed in r12, so it's necessary to write it in assembly. This is
// the function used by the compiler.
-extern "C" uptr __tls_get_offset_wrapper(void *arg, uptr (*fn)(void *arg));
#define INIT_TLS_GET_ADDR COMMON_INTERCEPT_FUNCTION(__tls_get_offset)
-DEFINE_REAL(uptr, __tls_get_offset, void *arg)
-extern "C" uptr __tls_get_offset(void *arg);
-extern "C" uptr __interceptor___tls_get_offset(void *arg);
INTERCEPTOR(uptr, __tls_get_addr_internal, void *arg) {
void *ctx;
COMMON_INTERCEPTOR_ENTER(ctx, __tls_get_addr_internal, arg);
@@ -5362,6 +5364,15 @@
}
return res;
}
+#endif // SANITIZER_S390
+#else
+#define INIT_TLS_GET_ADDR
+#endif
+
+#if SANITIZER_S390 && \
+ (SANITIZER_INTERCEPT_TLS_GET_ADDR || SANITIZER_INTERCEPT_TLS_GET_OFFSET)
+extern "C" uptr __tls_get_offset(void *arg);
+extern "C" uptr __interceptor___tls_get_offset(void *arg);
// We need a hidden symbol aliasing the above, so that we can jump
// directly to it from the assembly below.
extern "C" __attribute__((alias("__interceptor___tls_get_addr_internal"),
@@ -5400,9 +5411,6 @@
"br %r3\n"
".size __tls_get_offset_wrapper, .-__tls_get_offset_wrapper\n"
);
-#endif // SANITIZER_S390
-#else
-#define INIT_TLS_GET_ADDR
#endif
#if SANITIZER_INTERCEPT_LISTXATTR
Index: compiler-rt/cmake/config-ix.cmake
===================================================================
--- compiler-rt/cmake/config-ix.cmake
+++ compiler-rt/cmake/config-ix.cmake
@@ -329,7 +329,7 @@
set(ALL_MEMPROF_SUPPORTED_ARCH ${X86_64})
set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC64}
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9})
-set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64})
+set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X})
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9})
set(ALL_SAFESTACK_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM64} ${MIPS32} ${MIPS64})
Index: clang/lib/Driver/ToolChains/Linux.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Linux.cpp
+++ clang/lib/Driver/ToolChains/Linux.cpp
@@ -709,7 +709,7 @@
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch || IsPowerPC64 ||
IsRISCV64 || IsSystemZ)
Res |= SanitizerKind::Leak;
- if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64)
+ if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ)
Res |= SanitizerKind::Thread;
if (IsX86_64)
Res |= SanitizerKind::KernelMemory;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits