Skip to content

[TSAN] add support for riscv64 #68735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
IsRISCV64 || IsSystemZ || IsHexagon || IsLoongArch64)
Res |= SanitizerKind::Leak;
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
IsLoongArch64)
IsLoongArch64 || IsRISCV64)
Res |= SanitizerKind::Thread;
if (IsX86_64 || IsSystemZ)
Res |= SanitizerKind::KernelMemory;
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${RISCV32} ${RISCV64} ${LOONGARCH64})
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
${LOONGARCH64})
${LOONGARCH64} ${RISCV64})
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
${LOONGARCH64})
Expand Down
2 changes: 1 addition & 1 deletion compiler-rt/lib/sanitizer_common/sanitizer_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@
# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 40)
# endif
#elif SANITIZER_RISCV64
# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 38)
# define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
#elif defined(__aarch64__)
# if SANITIZER_APPLE
# if SANITIZER_OSX || SANITIZER_IOSSIM
Expand Down
4 changes: 4 additions & 0 deletions compiler-rt/lib/tsan/rtl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,10 @@ else()
set(TSAN_ASM_SOURCES
tsan_rtl_mips64.S
)
elseif(arch MATCHES "riscv64")
set(TSAN_ASM_SOURCES
tsan_rtl_riscv64.S
)
elseif(arch MATCHES "s390x")
set(TSAN_ASM_SOURCES
tsan_rtl_s390x.S
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ struct ucontext_t {
#define PTHREAD_ABI_BASE "GLIBC_2.17"
#elif SANITIZER_LOONGARCH64
#define PTHREAD_ABI_BASE "GLIBC_2.36"
#elif SANITIZER_RISCV64
# define PTHREAD_ABI_BASE "GLIBC_2.27"
#endif

extern "C" int pthread_attr_init(void *attr);
Expand Down
76 changes: 75 additions & 1 deletion compiler-rt/lib/tsan/rtl/tsan_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,71 @@ struct MappingPPC64_47 {
static const uptr kMidAppMemEnd = 0;
};

/*
C/C++ on linux/riscv64 (39-bit VMA)
0000 0010 00 - 0200 0000 00: main binary ( 8 GB)
0200 0000 00 - 1000 0000 00: -
1000 0000 00 - 4000 0000 00: shadow memory (64 GB)
4000 0000 00 - 4800 0000 00: metainfo (16 GB)
4800 0000 00 - 5500 0000 00: -
5500 0000 00 - 5a00 0000 00: main binary (PIE) (~8 GB)
5600 0000 00 - 7c00 0000 00: -
7d00 0000 00 - 7fff ffff ff: libraries and main thread stack ( 8 GB)

mmap by default allocates from top downwards
VDSO sits below loader and above dynamic libraries, within HiApp region.
Heap starts after program region whose position depends on pie or non-pie.
Disable tracking them since their locations are not fixed.
*/
struct MappingRiscv64_39 {
static const uptr kLoAppMemBeg = 0x0000001000ull;
static const uptr kLoAppMemEnd = 0x0200000000ull;
static const uptr kShadowBeg = 0x1000000000ull;
static const uptr kShadowEnd = 0x2000000000ull;
static const uptr kMetaShadowBeg = 0x2000000000ull;
static const uptr kMetaShadowEnd = 0x2400000000ull;
static const uptr kMidAppMemBeg = 0x2aaaaaa000ull;
static const uptr kMidAppMemEnd = 0x2c00000000ull;
static const uptr kHeapMemBeg = 0x2c00000000ull;
static const uptr kHeapMemEnd = 0x2c00000000ull;
static const uptr kHiAppMemBeg = 0x3c00000000ull;
static const uptr kHiAppMemEnd = 0x3fffffffffull;
static const uptr kShadowMsk = 0x3800000000ull;
static const uptr kShadowXor = 0x0800000000ull;
static const uptr kShadowAdd = 0x0000000000ull;
static const uptr kVdsoBeg = 0x4000000000ull;
};

/*
C/C++ on linux/riscv64 (48-bit VMA)
0000 0000 1000 - 0500 0000 0000: main binary ( 5 TB)
0500 0000 0000 - 2000 0000 0000: -
2000 0000 0000 - 4000 0000 0000: shadow memory (32 TB)
4000 0000 0000 - 4800 0000 0000: metainfo ( 8 TB)
4800 0000 0000 - 5555 5555 5000: -
5555 5555 5000 - 5a00 0000 0000: main binary (PIE) (~5 TB)
5a00 0000 0000 - 7a00 0000 0000: -
7a00 0000 0000 - 7fff ffff ffff: libraries and main thread stack ( 5 TB)
*/
struct MappingRiscv64_48 {
static const uptr kLoAppMemBeg = 0x000000001000ull;
static const uptr kLoAppMemEnd = 0x050000000000ull;
static const uptr kShadowBeg = 0x200000000000ull;
static const uptr kShadowEnd = 0x400000000000ull;
static const uptr kMetaShadowBeg = 0x400000000000ull;
static const uptr kMetaShadowEnd = 0x480000000000ull;
static const uptr kMidAppMemBeg = 0x555555555000ull;
static const uptr kMidAppMemEnd = 0x5a0000000000ull;
static const uptr kHeapMemBeg = 0x5a0000000000ull;
static const uptr kHeapMemEnd = 0x5a0000000000ull;
static const uptr kHiAppMemBeg = 0x7a0000000000ull;
static const uptr kHiAppMemEnd = 0x7fffffffffffull;
static const uptr kShadowMsk = 0x700000000000ull;
static const uptr kShadowXor = 0x100000000000ull;
static const uptr kShadowAdd = 0x000000000000ull;
static const uptr kVdsoBeg = 0x800000000000ull;
};

/*
C/C++ on linux/s390x
While the kernel provides a 64-bit address space, we have to restrict ourselves
Expand Down Expand Up @@ -665,6 +730,13 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
}
# elif defined(__mips64)
return Func::template Apply<MappingMips64_40>(arg);
# elif SANITIZER_RISCV64
switch (vmaSize) {
case 39:
return Func::template Apply<MappingRiscv64_39>(arg);
case 48:
return Func::template Apply<MappingRiscv64_48>(arg);
}
# elif defined(__s390x__)
return Func::template Apply<MappingS390x>(arg);
# else
Expand All @@ -686,6 +758,8 @@ void ForEachMapping() {
Func::template Apply<MappingPPC64_44>();
Func::template Apply<MappingPPC64_46>();
Func::template Apply<MappingPPC64_47>();
Func::template Apply<MappingRiscv64_39>();
Func::template Apply<MappingRiscv64_48>();
Func::template Apply<MappingS390x>();
Func::template Apply<MappingGo48>();
Func::template Apply<MappingGoWindows>();
Expand Down Expand Up @@ -894,7 +968,7 @@ struct RestoreAddrImpl {
Mapping::kMidAppMemEnd, Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd,
Mapping::kHeapMemBeg, Mapping::kHeapMemEnd,
};
const uptr indicator = 0x0e0000000000ull;
const uptr indicator = 0x0f0000000000ull;
const uptr ind_lsb = 1ull << LeastSignificantSetBitIndex(indicator);
for (uptr i = 0; i < ARRAY_SIZE(ranges); i += 2) {
uptr beg = ranges[i];
Expand Down
34 changes: 24 additions & 10 deletions compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,17 @@ void InitializePlatformEarly() {
Die();
}
# endif
#endif
# elif SANITIZER_RISCV64
// the bottom half of vma is allocated for userspace
vmaSize = vmaSize + 1;
# if !SANITIZER_GO
if (vmaSize != 39 && vmaSize != 48) {
Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
Die();
}
# endif
# endif
}

void InitializePlatform() {
Expand Down Expand Up @@ -399,13 +409,15 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
return mangled_sp ^ xor_key;
#elif defined(__mips__)
return mangled_sp;
#elif defined(__s390x__)
# elif SANITIZER_RISCV64
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
# else
# error "Unknown platform"
# endif
}

#if SANITIZER_NETBSD
Expand All @@ -429,11 +441,13 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
# define LONG_JMP_SP_ENV_SLOT 1
# 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
# elif SANITIZER_RISCV64
# define LONG_JMP_SP_ENV_SLOT 13
# elif defined(__s390x__)
# define LONG_JMP_SP_ENV_SLOT 9
# else
# define LONG_JMP_SP_ENV_SLOT 6
# endif
#endif

uptr ExtractLongJmpSp(uptr *env) {
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/lib/tsan/rtl/tsan_rtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ namespace __tsan {

#if !SANITIZER_GO
struct MapUnmapCallback;
#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
defined(__powerpc__)
# if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
defined(__powerpc__) || SANITIZER_RISCV64

struct AP32 {
static const uptr kSpaceBeg = 0;
Expand Down
Loading