Skip to content

Commit cd0a824

Browse files
alexfanqihiraditya
authored andcommitted
add support for riscv64
Implements for sv39 and sv48 VMA layout. Userspace only has access to the bottom half of vma range. The top half is used by kernel. There is no dedicated vsyscall or heap segment. PIE program is allocated to start at TASK_SIZE/3*2. Maximum ASLR is ARCH_MMAP_RND_BITS_MAX+PAGE_SHIFT=24+12=36 Loader, vdso and other libraries are allocated below stack from the top. Also change RestoreAddr to use 4 bits to accommodate MappingRiscv64_48 Reviewed by: MaskRay, dvyukov, asb, StephenFan, luismarques, jrtc27, hiraditya, vitalybuka Differential Revision: https://reviews.llvm.org/D145214
1 parent d3af653 commit cd0a824

File tree

10 files changed

+104
-6
lines changed

10 files changed

+104
-6
lines changed

clang/lib/Driver/ToolChains/Linux.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ SanitizerMask Linux::getSupportedSanitizers() const {
801801
IsRISCV64 || IsSystemZ || IsHexagon || IsLoongArch64)
802802
Res |= SanitizerKind::Leak;
803803
if (IsX86_64 || IsMIPS64 || IsAArch64 || IsPowerPC64 || IsSystemZ ||
804-
IsLoongArch64)
804+
IsLoongArch64 || IsRISCV64)
805805
Res |= SanitizerKind::Thread;
806806
if (IsX86_64 || IsSystemZ)
807807
Res |= SanitizerKind::KernelMemory;

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ set(ALL_PROFILE_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${PPC32} ${PPC
6666
${MIPS32} ${MIPS64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
6767
${RISCV32} ${RISCV64} ${LOONGARCH64})
6868
set(ALL_TSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
69-
${LOONGARCH64})
69+
${LOONGARCH64} ${RISCV64})
7070
set(ALL_UBSAN_SUPPORTED_ARCH ${X86} ${X86_64} ${ARM32} ${ARM64} ${RISCV64}
7171
${MIPS32} ${MIPS64} ${PPC64} ${S390X} ${SPARC} ${SPARCV9} ${HEXAGON}
7272
${LOONGARCH64})

compiler-rt/lib/tsan/rtl/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ include_directories(../..)
22

33
set(TSAN_RTL_CFLAGS ${TSAN_CFLAGS})
44
append_list_if(COMPILER_RT_HAS_MSSE4_2_FLAG -msse4.2 TSAN_RTL_CFLAGS)
5-
append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=530
5+
append_list_if(SANITIZER_LIMIT_FRAME_SIZE -Wframe-larger-than=656
66
TSAN_RTL_CFLAGS)
77
append_list_if(COMPILER_RT_HAS_WGLOBAL_CONSTRUCTORS_FLAG -Wglobal-constructors
88
TSAN_RTL_CFLAGS)
@@ -220,6 +220,10 @@ else()
220220
set(TSAN_ASM_SOURCES
221221
tsan_rtl_mips64.S
222222
)
223+
elseif(arch MATCHES "riscv64")
224+
set(TSAN_ASM_SOURCES
225+
tsan_rtl_riscv64.S
226+
)
223227
elseif(arch MATCHES "s390x")
224228
set(TSAN_ASM_SOURCES
225229
tsan_rtl_s390x.S

compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ struct ucontext_t {
8181
#define PTHREAD_ABI_BASE "GLIBC_2.17"
8282
#elif SANITIZER_LOONGARCH64
8383
#define PTHREAD_ABI_BASE "GLIBC_2.36"
84+
#elif SANITIZER_RISCV64
85+
#define PTHREAD_ABI_BASE "GLIBC_2.27"
8486
#endif
8587

8688
extern "C" int pthread_attr_init(void *attr);

compiler-rt/lib/tsan/rtl/tsan_platform.h

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,71 @@ struct MappingPPC64_47 {
377377
static const uptr kMidAppMemEnd = 0;
378378
};
379379

380+
/*
381+
C/C++ on linux/riscv64 (39-bit VMA)
382+
0000 0010 00 - 0200 0000 00: main binary ( 8 GB)
383+
0200 0000 00 - 1000 0000 00: -
384+
1000 0000 00 - 4000 0000 00: shadow memory (64 GB)
385+
4000 0000 00 - 4800 0000 00: metainfo (16 GB)
386+
4800 0000 00 - 5500 0000 00: -
387+
5500 0000 00 - 5a00 0000 00: main binary (PIE) (~8 GB)
388+
5600 0000 00 - 7c00 0000 00: -
389+
7d00 0000 00 - 7fff ffff ff: libraries and main thread stack ( 8 GB)
390+
391+
mmap by default allocates from top downwards
392+
VDSO sits below loader and above dynamic libraries, within HiApp region.
393+
Heap starts after program region whose position depends on pie or non-pie.
394+
Disable tracking them since their locations are not fixed.
395+
*/
396+
struct MappingRiscv64_39 {
397+
static const uptr kLoAppMemBeg = 0x0000001000ull;
398+
static const uptr kLoAppMemEnd = 0x0200000000ull;
399+
static const uptr kShadowBeg = 0x1000000000ull;
400+
static const uptr kShadowEnd = 0x2000000000ull;
401+
static const uptr kMetaShadowBeg = 0x2000000000ull;
402+
static const uptr kMetaShadowEnd = 0x2400000000ull;
403+
static const uptr kMidAppMemBeg = 0x2aaaaaa000ull;
404+
static const uptr kMidAppMemEnd = 0x2c00000000ull;
405+
static const uptr kHeapMemBeg = 0x2c00000000ull;
406+
static const uptr kHeapMemEnd = 0x2c00000000ull;
407+
static const uptr kHiAppMemBeg = 0x3c00000000ull;
408+
static const uptr kHiAppMemEnd = 0x3fffffffffull;
409+
static const uptr kShadowMsk = 0x3800000000ull;
410+
static const uptr kShadowXor = 0x0800000000ull;
411+
static const uptr kShadowAdd = 0x0000000000ull;
412+
static const uptr kVdsoBeg = 0x4000000000ull;
413+
};
414+
415+
/*
416+
C/C++ on linux/riscv64 (48-bit VMA)
417+
0000 0000 1000 - 0500 0000 0000: main binary ( 5 TB)
418+
0500 0000 0000 - 2000 0000 0000: -
419+
2000 0000 0000 - 4000 0000 0000: shadow memory (32 TB)
420+
4000 0000 0000 - 4800 0000 0000: metainfo ( 8 TB)
421+
4800 0000 0000 - 5555 5555 5000: -
422+
5555 5555 5000 - 5a00 0000 0000: main binary (PIE) (~5 TB)
423+
5a00 0000 0000 - 7a00 0000 0000: -
424+
7a00 0000 0000 - 7fff ffff ffff: libraries and main thread stack ( 5 TB)
425+
*/
426+
struct MappingRiscv64_48 {
427+
static const uptr kLoAppMemBeg = 0x000000001000ull;
428+
static const uptr kLoAppMemEnd = 0x050000000000ull;
429+
static const uptr kShadowBeg = 0x200000000000ull;
430+
static const uptr kShadowEnd = 0x400000000000ull;
431+
static const uptr kMetaShadowBeg = 0x400000000000ull;
432+
static const uptr kMetaShadowEnd = 0x480000000000ull;
433+
static const uptr kMidAppMemBeg = 0x555555555000ull;
434+
static const uptr kMidAppMemEnd = 0x5a0000000000ull;
435+
static const uptr kHeapMemBeg = 0x5a0000000000ull;
436+
static const uptr kHeapMemEnd = 0x5a0000000000ull;
437+
static const uptr kHiAppMemBeg = 0x7a0000000000ull;
438+
static const uptr kHiAppMemEnd = 0x7fffffffffffull;
439+
static const uptr kShadowMsk = 0x700000000000ull;
440+
static const uptr kShadowXor = 0x100000000000ull;
441+
static const uptr kShadowAdd = 0x000000000000ull;
442+
static const uptr kVdsoBeg = 0x800000000000ull;
443+
};
444+
380445
/*
381446
C/C++ on linux/s390x
382447
While the kernel provides a 64-bit address space, we have to restrict ourselves
@@ -665,6 +730,13 @@ ALWAYS_INLINE auto SelectMapping(Arg arg) {
665730
}
666731
# elif defined(__mips64)
667732
return Func::template Apply<MappingMips64_40>(arg);
733+
# elif SANITIZER_RISCV64
734+
switch (vmaSize) {
735+
case 39:
736+
return Func::template Apply<MappingRiscv64_39>(arg);
737+
case 48:
738+
return Func::template Apply<MappingRiscv64_48>(arg);
739+
}
668740
# elif defined(__s390x__)
669741
return Func::template Apply<MappingS390x>(arg);
670742
# else
@@ -686,6 +758,8 @@ void ForEachMapping() {
686758
Func::template Apply<MappingPPC64_44>();
687759
Func::template Apply<MappingPPC64_46>();
688760
Func::template Apply<MappingPPC64_47>();
761+
Func::template Apply<MappingRiscv64_39>();
762+
Func::template Apply<MappingRiscv64_48>();
689763
Func::template Apply<MappingS390x>();
690764
Func::template Apply<MappingGo48>();
691765
Func::template Apply<MappingGoWindows>();
@@ -894,7 +968,7 @@ struct RestoreAddrImpl {
894968
Mapping::kMidAppMemEnd, Mapping::kHiAppMemBeg, Mapping::kHiAppMemEnd,
895969
Mapping::kHeapMemBeg, Mapping::kHeapMemEnd,
896970
};
897-
const uptr indicator = 0x0e0000000000ull;
971+
const uptr indicator = 0x0f0000000000ull;
898972
const uptr ind_lsb = 1ull << LeastSignificantSetBitIndex(indicator);
899973
for (uptr i = 0; i < ARRAY_SIZE(ranges); i += 2) {
900974
uptr beg = ranges[i];

compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,16 @@ void InitializePlatformEarly() {
267267
Die();
268268
}
269269
# endif
270+
#elif SANITIZER_RISCV64
271+
// the bottom half of vma is allocated for userspace
272+
vmaSize = vmaSize + 1;
273+
# if !SANITIZER_GO
274+
if (vmaSize != 39 && vmaSize != 48) {
275+
Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
276+
Printf("FATAL: Found %zd - Supported 39 and 48\n", vmaSize);
277+
Die();
278+
}
279+
# endif
270280
#endif
271281
}
272282

@@ -399,6 +409,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
399409
return mangled_sp ^ xor_key;
400410
#elif defined(__mips__)
401411
return mangled_sp;
412+
#elif SANITIZER_RISCV64
413+
return mangled_sp;
402414
#elif defined(__s390x__)
403415
// tcbhead_t.stack_guard
404416
uptr xor_key = ((uptr *)__builtin_thread_pointer())[5];
@@ -429,6 +441,8 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
429441
# define LONG_JMP_SP_ENV_SLOT 1
430442
# elif defined(__mips64)
431443
# define LONG_JMP_SP_ENV_SLOT 1
444+
# elif SANITIZER_RISCV64
445+
# define LONG_JMP_SP_ENV_SLOT 13
432446
# elif defined(__s390x__)
433447
# define LONG_JMP_SP_ENV_SLOT 9
434448
# else

compiler-rt/lib/tsan/rtl/tsan_rtl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ namespace __tsan {
5757
#if !SANITIZER_GO
5858
struct MapUnmapCallback;
5959
#if defined(__mips64) || defined(__aarch64__) || defined(__loongarch__) || \
60-
defined(__powerpc__)
60+
defined(__powerpc__) || SANITIZER_RISCV64
6161

6262
struct AP32 {
6363
static const uptr kSpaceBeg = 0;

compiler-rt/test/tsan/map32bit.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// XFAIL: target=powerpc64{{.*}}
1414
// XFAIL: target=s390x{{.*}}
1515
// XFAIL: target=loongarch64{{.*}}
16+
// XFAIL: target=riscv64{{.*}}
1617

1718
// MAP_32BIT doesn't exist on OS X and NetBSD.
1819
// UNSUPPORTED: darwin,target={{.*netbsd.*}}

compiler-rt/test/tsan/mmap_large.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
int main() {
1818
#ifdef __x86_64__
1919
const size_t kLog2Size = 39;
20-
#elif defined(__mips64) || defined(__aarch64__) || defined(__loongarch_lp64)
20+
#elif defined(__mips64) || defined(__aarch64__) || \
21+
defined(__loongarch_lp64) || (defined(__riscv) && __riscv_xlen == 64)
2122
const size_t kLog2Size = 32;
2223
#elif defined(__powerpc64__)
2324
const size_t kLog2Size = 39;

compiler-rt/test/tsan/test.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ unsigned long long monotonic_clock_ns() {
7676
const int kPCInc = 1;
7777
#elif defined(__sparc__) || defined(__mips__)
7878
const int kPCInc = 8;
79+
#elif defined(__riscv) && __riscv_xlen == 64
80+
const int kPCInc = 2;
7981
#else
8082
const int kPCInc = 4;
8183
#endif

0 commit comments

Comments
 (0)