[compiler-rt] [llvm] [compiler-rt][msan] Add MSan support for RISC-V 64-bit Linux (PR #206674)
Meng Zhuo via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 01:09:08 PDT 2026
https://github.com/mengzhuo created https://github.com/llvm/llvm-project/pull/206674
RISC-V uses a 5-bit address compression via
AndMask=0x3C00000000 to fold the 39-bit virtual address space (SV39, 256GB) into a ≤48GB compressed region, enabling MSan to fit within the constrained VMA. The layout accommodates the RISC-V Linux memory map where the dynamic linker and shared libraries load near the top of user space.
Memory layout (SV39-compatible, fits within 256GB):
0x0000001000 - 0x001000000000 APP-lo (64GB, program segments)
0x001000000000 - 0x001c00000000 SHADOW (48GB)
0x001c00000000 - 0x002c00000000 APP-mid (64GB, PIE / mmap)
0x002c00000000 - 0x003000000000 ALLOCATOR (16GB)
0x003000000000 - 0x003c00000000 ORIGIN (48GB)
0x003c00000000 - 0x004000000000 APP-hi (16GB, libraries / stack)
MEM_TO_SHADOW folds bits 34-37 via (addr & ~0x3C00000000) ^ 0x0800000000 then adds ShadowBase 0x1000000000. SHADOW_TO_ORIGIN adds 0x2000000000. The allocator uses SizeClassAllocator64 with a 16GB region at 0x2C00000000, and kMaxAllowedMallocSize is set to 8GB consistent with other 64-bit RISC targets.
>From 65e6d0d2952b70a2274d2393887241809e09f561 Mon Sep 17 00:00:00 2001
From: Meng Zhuo <mengzhuo at iscas.ac.cn>
Date: Tue, 30 Jun 2026 09:47:58 +0800
Subject: [PATCH] [compiler-rt][msan] Add MSan support for RISC-V 64-bit Linux
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
RISC-V uses a 5-bit address compression via
AndMask=0x3C00000000 to fold the 39-bit virtual address space (SV39,
256GB) into a ≤48GB compressed region, enabling MSan to fit within the
constrained VMA. The layout accommodates the RISC-V Linux memory map where
the dynamic linker and shared libraries load near the top of user space.
Memory layout (SV39-compatible, fits within 256GB):
0x0000001000 - 0x001000000000 APP-lo (64GB, program segments)
0x001000000000 - 0x001c00000000 SHADOW (48GB)
0x001c00000000 - 0x002c00000000 APP-mid (64GB, PIE / mmap)
0x002c00000000 - 0x003000000000 ALLOCATOR (16GB)
0x003000000000 - 0x003c00000000 ORIGIN (48GB)
0x003c00000000 - 0x004000000000 APP-hi (16GB, libraries / stack)
MEM_TO_SHADOW folds bits 34-37 via (addr & ~0x3C00000000) ^ 0x0800000000
then adds ShadowBase 0x1000000000. SHADOW_TO_ORIGIN adds 0x2000000000.
The allocator uses SizeClassAllocator64 with a 16GB region at 0x2C00000000,
and kMaxAllowedMallocSize is set to 8GB consistent with other 64-bit RISC
targets.
---
.../cmake/Modules/AllSupportedArchDefs.cmake | 2 +-
compiler-rt/lib/msan/msan.h | 14 ++++++++++++++
compiler-rt/lib/msan/msan_allocator.cpp | 15 +++++++++++++++
.../Instrumentation/MemorySanitizer.cpp | 16 ++++++++++++++++
4 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
index 9c03892dffe5a..4389df8d3fece 100644
--- a/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
+++ b/compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
@@ -89,7 +89,7 @@ if (OS_NAME MATCHES "FreeBSD")
set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${ARM64})
else()
set(ALL_MSAN_SUPPORTED_ARCH ${X86_64} ${MIPS64} ${ARM64} ${PPC64} ${S390X}
- ${LOONGARCH64} ${HEXAGON})
+ ${LOONGARCH64} ${HEXAGON} ${RISCV64})
endif()
set(ALL_NSAN_SUPPORTED_ARCH ${X86_64})
set(ALL_HWASAN_SUPPORTED_ARCH ${X86_64} ${ARM64} ${RISCV64})
diff --git a/compiler-rt/lib/msan/msan.h b/compiler-rt/lib/msan/msan.h
index 8e2dc075cb79c..f51518966c6c0 100644
--- a/compiler-rt/lib/msan/msan.h
+++ b/compiler-rt/lib/msan/msan.h
@@ -142,6 +142,20 @@ const MappingDesc kMemoryLayout[] = {
#define MEM_TO_SHADOW(mem) (LINEARIZE_MEM((mem)) + 0x080000000000ULL)
#define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x140000000000ULL)
+#elif SANITIZER_LINUX && SANITIZER_RISCV64
+// RISC-V 64 SV39 layout (256GB VMA).
+const MappingDesc kMemoryLayout[] = {
+ {0x000000000000ULL, 0x000000001000ULL, MappingDesc::INVALID, "null"},
+ {0x000000001000ULL, 0x001000000000ULL, MappingDesc::APP, "app-lo"},
+ {0x001000000000ULL, 0x001c00000000ULL, MappingDesc::SHADOW, "shadow"},
+ {0x001c00000000ULL, 0x002c00000000ULL, MappingDesc::APP, "app-mid"},
+ {0x002c00000000ULL, 0x003000000000ULL, MappingDesc::ALLOCATOR, "alloc"},
+ {0x003000000000ULL, 0x003c00000000ULL, MappingDesc::ORIGIN, "origin"},
+ {0x003c00000000ULL, 0x004000000000ULL, MappingDesc::APP, "app-hi"},
+};
+# define MEM_TO_SHADOW(mem) ((((uptr)(mem) & ~0x3c00000000ULL) ^ 0x0800000000ULL) + 0x1000000000ULL)
+# define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x2000000000ULL)
+
#elif SANITIZER_LINUX && SANITIZER_S390_64
const MappingDesc kMemoryLayout[] = {
{0x000000000000ULL, 0x040000000000ULL, MappingDesc::APP, "low memory"},
diff --git a/compiler-rt/lib/msan/msan_allocator.cpp b/compiler-rt/lib/msan/msan_allocator.cpp
index 532657f73590a..20c49307c4d59 100644
--- a/compiler-rt/lib/msan/msan_allocator.cpp
+++ b/compiler-rt/lib/msan/msan_allocator.cpp
@@ -129,6 +129,21 @@ struct AP64 { // Allocator64 parameters. Deliberately using a short name.
using AddressSpaceView = LocalAddressSpaceView;
};
+using PrimaryAllocator = SizeClassAllocator64<AP64>;
+#elif defined(__riscv) && __riscv_xlen == 64
+const uptr kAllocatorSpace = 0x2c00000000ULL;
+const uptr kMaxAllowedMallocSize = 8UL << 30;
+
+struct AP64 {
+ static const uptr kSpaceBeg = kAllocatorSpace;
+ static const uptr kSpaceSize = 0x0400000000; // 16GB.
+ static const uptr kMetadataSize = sizeof(Metadata);
+ using SizeClassMap = DefaultSizeClassMap;
+ using MapUnmapCallback = MsanMapUnmapCallback;
+ static const uptr kFlags = 0;
+ using AddressSpaceView = LocalAddressSpaceView;
+};
+
using PrimaryAllocator = SizeClassAllocator64<AP64>;
#elif SANITIZER_LINUX && defined(__hexagon__)
const uptr kMaxAllowedMallocSize = 1UL << 30; // 1G
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
index cdce2e039154f..3779d8c1c55ee 100644
--- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
@@ -520,6 +520,14 @@ static const MemoryMapParams Linux_Hexagon_MemoryMapParams = {
// FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
// after picking good constants
+// riscv64 Linux — SV39 (256GB)
+static const MemoryMapParams Linux_RISCV64_MemoryMapParams = {
+ 0x3C00000000, // AndMask (fold bits 34-37)
+ 0x0800000000, // XorMask (flip bit 35)
+ 0x1000000000, // ShadowBase (shadow at 64GB)
+ 0x3000000000, // OriginBase (origin at 192GB)
+};
+
// aarch64 FreeBSD
static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams = {
0x1800000000000, // AndMask
@@ -587,6 +595,11 @@ static const PlatformMemoryMapParams Linux_Hexagon_MemoryMapParams_P = {
nullptr,
};
+static const PlatformMemoryMapParams Linux_RISCV_MemoryMapParams = {
+ nullptr,
+ &Linux_RISCV64_MemoryMapParams,
+};
+
static const PlatformMemoryMapParams FreeBSD_ARM_MemoryMapParams = {
nullptr,
&FreeBSD_AArch64_MemoryMapParams,
@@ -1117,6 +1130,9 @@ void MemorySanitizer::initializeModule(Module &M) {
case Triple::hexagon:
MapParams = Linux_Hexagon_MemoryMapParams_P.bits32;
break;
+ case Triple::riscv64:
+ MapParams = Linux_RISCV_MemoryMapParams.bits64;
+ break;
default:
report_fatal_error("unsupported architecture");
}
More information about the llvm-commits
mailing list