[compiler-rt] [llvm] [RISCV][sanitizer] Fix sanitizer support for different virtual memory layout (PR #66743)

Hau Hsu via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 3 20:52:07 PDT 2024


https://github.com/hau-hsu updated https://github.com/llvm/llvm-project/pull/66743

>From 3e53c64b88ca051ca0f344ce920771fe85f4a42e Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at gmail.com>
Date: Tue, 19 Sep 2023 14:45:32 +0800
Subject: [PATCH 1/3] [RISCV][sanitizer] Enable AP64 for RISCV64

D92403 has use AP32 by default for RISCV64 and then D126825 has move
this logic into sanitizer_common/sanitizer_platform.h which will effect
both asan and lsan, however asan are using AP64 and lsan using AP32
before D126825, and AP64 should work well for all 64-bit platform (ASan use that
before, so that's kind of evidence), not sure why we choose AP32 for lsan
before.

We have 2 option here: 1) only limited lsan use AP32 for RISCV64, 2) or also
relax that for lsan to using AP64.
---
 compiler-rt/lib/sanitizer_common/sanitizer_platform.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index 5965281555059..140dccdbe63c3 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -295,8 +295,8 @@
 // For such platforms build this code with -DSANITIZER_CAN_USE_ALLOCATOR64=0 or
 // change the definition of SANITIZER_CAN_USE_ALLOCATOR64 here.
 #ifndef SANITIZER_CAN_USE_ALLOCATOR64
-#  if (SANITIZER_RISCV64 && !SANITIZER_FUCHSIA) || SANITIZER_IOS || \
-      SANITIZER_DRIVERKIT
+#  if (SANITIZER_RISCV64 && !SANITIZER_FUCHSIA && !SANITIZER_LINUX) || \
+      SANITIZER_IOS || SANITIZER_DRIVERKIT
 #    define SANITIZER_CAN_USE_ALLOCATOR64 0
 #  elif defined(__mips64) || defined(__hexagon__)
 #    define SANITIZER_CAN_USE_ALLOCATOR64 0

>From b011f128e87608d2f401578e5721811eb85d8ac2 Mon Sep 17 00:00:00 2001
From: Kito Cheng <kito.cheng at gmail.com>
Date: Tue, 19 Sep 2023 14:40:51 +0800
Subject: [PATCH 2/3] [RISCV][Asan] Use dynamic shadow offset to make it work
 on different width of virtual-memory system.

The original asan port was support Sv39 only, however Sv48 support has
landed to linux kernel[1] for a while, so we are trying to make it support
both Sv39 and Sv48, the key point is we need to use a dynamic offset for the
shadow region, this bring extra runtime overhead, but compare to other
overhead in ASan, this should be acceptable.

[1] https://www.phoronix.com/news/Linux-5.17-RISC-V-sv48
---
 compiler-rt/lib/asan/asan_mapping.h                      | 7 +++++--
 compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp     | 6 +++---
 llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | 2 +-
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h
index c5f95c07a2105..91fe60db6329a 100644
--- a/compiler-rt/lib/asan/asan_mapping.h
+++ b/compiler-rt/lib/asan/asan_mapping.h
@@ -72,7 +72,10 @@
 // || `[0x2000000000, 0x23ffffffff]` || LowShadow  ||
 // || `[0x0000000000, 0x1fffffffff]` || LowMem     ||
 //
-// Default Linux/RISCV64 Sv39 mapping:
+// Default Linux/RISCV64 Sv39 mapping with SHADOW_OFFSET == 0xd55550000;
+// (the exact location of SHADOW_OFFSET may vary depending the dynamic probing
+//  by FindDynamicShadowStart).
+//
 // || `[0x1555550000, 0x3fffffffff]` || HighMem    ||
 // || `[0x0fffffa000, 0x1555555fff]` || HighShadow ||
 // || `[0x0effffa000, 0x0fffff9fff]` || ShadowGap  ||
@@ -186,7 +189,7 @@
 #  elif SANITIZER_FREEBSD && defined(__aarch64__)
 #    define ASAN_SHADOW_OFFSET_CONST 0x0000800000000000
 #  elif SANITIZER_RISCV64
-#    define ASAN_SHADOW_OFFSET_CONST 0x0000000d55550000
+#    define ASAN_SHADOW_OFFSET_DYNAMIC
 #  elif defined(__aarch64__)
 #    define ASAN_SHADOW_OFFSET_CONST 0x0000001000000000
 #  elif defined(__powerpc64__)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
index 5d2dd3a7a658f..36284aa3e53c9 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
@@ -1096,7 +1096,8 @@ uptr GetMaxVirtualAddress() {
 #  if SANITIZER_NETBSD && defined(__x86_64__)
   return 0x7f7ffffff000ULL;  // (0x00007f8000000000 - PAGE_SIZE)
 #  elif SANITIZER_WORDSIZE == 64
-#    if defined(__powerpc64__) || defined(__aarch64__) || defined(__loongarch__)
+#    if defined(__powerpc64__) || defined(__aarch64__) || \
+        defined(__loongarch__) || SANITIZER_RISCV64
   // On PowerPC64 we have two different address space layouts: 44- and 46-bit.
   // We somehow need to figure out which one we are using now and choose
   // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL.
@@ -1105,9 +1106,8 @@ uptr GetMaxVirtualAddress() {
   // This should (does) work for both PowerPC64 Endian modes.
   // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit.
   // loongarch64 also has multiple address space layouts: default is 47-bit.
+  // RISC-V 64 also has multiple address space layouts: 39, 48 and 57-bit.
   return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1)) - 1;
-#    elif SANITIZER_RISCV64
-  return (1ULL << 38) - 1;
 #    elif SANITIZER_MIPS64
   return (1ULL << 40) - 1;  // 0x000000ffffffffffUL;
 #    elif defined(__s390x__)
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 9cc978dc6c16e..c6be7a9c317cb 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -108,7 +108,7 @@ static const uint64_t kMIPS32_ShadowOffset32 = 0x0aaa0000;
 static const uint64_t kMIPS64_ShadowOffset64 = 1ULL << 37;
 static const uint64_t kAArch64_ShadowOffset64 = 1ULL << 36;
 static const uint64_t kLoongArch64_ShadowOffset64 = 1ULL << 46;
-static const uint64_t kRISCV64_ShadowOffset64 = 0xd55550000;
+static const uint64_t kRISCV64_ShadowOffset64 = kDynamicShadowSentinel;
 static const uint64_t kFreeBSD_ShadowOffset32 = 1ULL << 30;
 static const uint64_t kFreeBSD_ShadowOffset64 = 1ULL << 46;
 static const uint64_t kFreeBSDAArch64_ShadowOffset64 = 1ULL << 47;

>From 299ea602abe64813e7ed89b82e75b9679a168a62 Mon Sep 17 00:00:00 2001
From: Hau Hsu <hau.hsu at sifive.com>
Date: Tue, 4 Jun 2024 03:45:28 +0000
Subject: [PATCH 3/3] [RISCV][sanitizer] Set SANITIZER_MMAP_RANGE_SIZE for sv57

This patch enables sanitizers for sv57 virtual memory mode.
Alloctor checks whether SANITIZER_MMAP_RANGE_SIZE matches possible mmap
regions:
sanitizer_allocator_primary32.h:292 "((res)) <((kNumPossibleRegions))"

Since SANITIZER_MMAP_RANGE_SIZE only controls "possible" mmap regions,
setting it to (1 << 57) also works for sv39 and sv48.
---
 compiler-rt/lib/sanitizer_common/sanitizer_platform.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
index 140dccdbe63c3..57966403c92a9 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h
@@ -322,7 +322,7 @@
 #  if SANITIZER_FUCHSIA
 #    define SANITIZER_MMAP_RANGE_SIZE (1ULL << 38)
 #  else
-#    define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 47)
+#    define SANITIZER_MMAP_RANGE_SIZE FIRST_32_SECOND_64(1ULL << 32, 1ULL << 56)
 #  endif
 #elif defined(__aarch64__)
 #  if SANITIZER_APPLE



More information about the llvm-commits mailing list