[compiler-rt] de5416c - [dfsan] Support Linux AArch64

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 3 13:17:44 PST 2023


Author: Fangrui Song
Date: 2023-01-03T13:17:39-08:00
New Revision: de5416cb59b0cffbc98f8fdfeaae67ca2495faa1

URL: https://github.com/llvm/llvm-project/commit/de5416cb59b0cffbc98f8fdfeaae67ca2495faa1
DIFF: https://github.com/llvm/llvm-project/commit/de5416cb59b0cffbc98f8fdfeaae67ca2495faa1.diff

LOG: [dfsan] Support Linux AArch64

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake:ALL_DFSAN_SUPPORTED_ARCH
allows AArch64 but currently the instrumentation will crash.

Port Linux AArch64 memory mappings from msan but use
SizeClassAllocator64 for a slightly more efficient allocator (used by
asan/lsan). Change dfsan/lit.cfg.py to allow Linux aarch64. All tests
should pass.

* dfsan/origin_invalid.c uses x86_64 assembly. Just make it x86_64 specific.
* dfsan/interceptors.c our mallinfo interceptor takes an argument
  instead of returning a struct. This does not work on AArch64 which
  uses different registers for the two function types. Disable AArch64
  as msan/Linux/mallinfo.cpp does.

Reviewed By: #sanitizers, vitalybuka

Differential Revision: https://reviews.llvm.org/D140770

Added: 
    

Modified: 
    compiler-rt/lib/dfsan/dfsan_allocator.cpp
    compiler-rt/lib/dfsan/dfsan_platform.h
    compiler-rt/test/dfsan/interceptors.c
    compiler-rt/test/dfsan/lit.cfg.py
    compiler-rt/test/dfsan/origin_invalid.c
    llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/dfsan/dfsan_allocator.cpp b/compiler-rt/lib/dfsan/dfsan_allocator.cpp
index c50aee7a55a0..5fb8fef213b9 100644
--- a/compiler-rt/lib/dfsan/dfsan_allocator.cpp
+++ b/compiler-rt/lib/dfsan/dfsan_allocator.cpp
@@ -33,8 +33,12 @@ struct DFsanMapUnmapCallback {
   void OnUnmap(uptr p, uptr size) const { dfsan_set_label(0, (void *)p, size); }
 };
 
-static const uptr kAllocatorSpace = 0x700000000000ULL;
-static const uptr kMaxAllowedMallocSize = 8UL << 30;
+#if defined(__aarch64__)
+const uptr kAllocatorSpace = 0xE00000000000ULL;
+#else
+const uptr kAllocatorSpace = 0x700000000000ULL;
+#endif
+const uptr kMaxAllowedMallocSize = 8UL << 30;
 
 struct AP64 {  // Allocator64 parameters. Deliberately using a short name.
   static const uptr kSpaceBeg = kAllocatorSpace;

diff  --git a/compiler-rt/lib/dfsan/dfsan_platform.h b/compiler-rt/lib/dfsan/dfsan_platform.h
index 9b4333ee99d0..b849b4b528ad 100644
--- a/compiler-rt/lib/dfsan/dfsan_platform.h
+++ b/compiler-rt/lib/dfsan/dfsan_platform.h
@@ -33,6 +33,32 @@ struct MappingDesc {
 
 #if SANITIZER_LINUX && SANITIZER_WORDSIZE == 64
 
+#  if defined(__aarch64__)
+// The mapping assumes 48-bit VMA. AArch64 maps:
+// - 0x0000000000000-0x0100000000000: 39/42/48-bits program own segments
+// - 0x0a00000000000-0x0b00000000000: 48-bits PIE program segments
+//   Ideally, this would extend to 0x0c00000000000 (2^45 bytes - the
+//   maximum ASLR region for 48-bit VMA) but it is too hard to fit in
+//   the larger app/shadow/origin regions.
+// - 0x0e00000000000-0x1000000000000: 48-bits libraries segments
+const MappingDesc kMemoryLayout[] = {
+    {0X0000000000000, 0X0100000000000, MappingDesc::APP, "app-10-13"},
+    {0X0100000000000, 0X0200000000000, MappingDesc::SHADOW, "shadow-14"},
+    {0X0200000000000, 0X0300000000000, MappingDesc::INVALID, "invalid"},
+    {0X0300000000000, 0X0400000000000, MappingDesc::ORIGIN, "origin-14"},
+    {0X0400000000000, 0X0600000000000, MappingDesc::SHADOW, "shadow-15"},
+    {0X0600000000000, 0X0800000000000, MappingDesc::ORIGIN, "origin-15"},
+    {0X0800000000000, 0X0A00000000000, MappingDesc::INVALID, "invalid"},
+    {0X0A00000000000, 0X0B00000000000, MappingDesc::APP, "app-14"},
+    {0X0B00000000000, 0X0C00000000000, MappingDesc::SHADOW, "shadow-10-13"},
+    {0X0C00000000000, 0X0D00000000000, MappingDesc::INVALID, "invalid"},
+    {0X0D00000000000, 0X0E00000000000, MappingDesc::ORIGIN, "origin-10-13"},
+    {0X0E00000000000, 0X1000000000000, MappingDesc::APP, "app-15"},
+};
+#    define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0xB00000000000ULL)
+#    define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x200000000000ULL)
+
+#  else
 // All of the following configurations are supported.
 // ASLR disabled: main executable and DSOs at 0x555550000000
 // PIE and ASLR: main executable and DSOs at 0x7f0000000000
@@ -51,8 +77,9 @@ const MappingDesc kMemoryLayout[] = {
     {0x600000000000ULL, 0x610000000000ULL, MappingDesc::ORIGIN, "origin-1"},
     {0x610000000000ULL, 0x700000000000ULL, MappingDesc::INVALID, "invalid"},
     {0x700000000000ULL, 0x800000000000ULL, MappingDesc::APP, "app-3"}};
-#  define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
-#  define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL)
+#    define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)
+#    define SHADOW_TO_ORIGIN(mem) (((uptr)(mem)) + 0x100000000000ULL)
+#  endif
 
 #else
 #  error "Unsupported platform"

diff  --git a/compiler-rt/test/dfsan/interceptors.c b/compiler-rt/test/dfsan/interceptors.c
index 3c111a996baa..acef141738c6 100644
--- a/compiler-rt/test/dfsan/interceptors.c
+++ b/compiler-rt/test/dfsan/interceptors.c
@@ -46,12 +46,17 @@ void test_free() {
 }
 
 void test_mallinfo() {
+  // The mallinfo interceptor takes an argument instead of returning a struct.
+  // This doesn't work on AArch64 which uses 
diff erent registers for the two
+  // function types.
+#ifdef defined(__GLIBC__) && !defined(__aarch64__)
   struct mallinfo mi = mallinfo();
   for (int i = 0; i < sizeof(struct mallinfo); ++i) {
     char c = ((char *)(&mi))[i];
     assert(!c);
     ASSERT_ZERO_LABEL(c);
   }
+#endif
 }
 
 void test_malloc() {

diff  --git a/compiler-rt/test/dfsan/lit.cfg.py b/compiler-rt/test/dfsan/lit.cfg.py
index 91a8b47b1f81..ea1d450a3453 100644
--- a/compiler-rt/test/dfsan/lit.cfg.py
+++ b/compiler-rt/test/dfsan/lit.cfg.py
@@ -24,5 +24,5 @@ def build_invocation(compile_flags):
 config.suffixes = ['.c', '.cpp']
 
 # DataFlowSanitizer tests are currently supported on Linux only.
-if not (config.host_os in ['Linux'] and config.target_arch in ['x86_64']):
+if not (config.host_os in ['Linux'] and config.target_arch in ['aarch64', 'x86_64']):
   config.unsupported = True

diff  --git a/compiler-rt/test/dfsan/origin_invalid.c b/compiler-rt/test/dfsan/origin_invalid.c
index b01d49af4b56..9d5e7caba2d9 100644
--- a/compiler-rt/test/dfsan/origin_invalid.c
+++ b/compiler-rt/test/dfsan/origin_invalid.c
@@ -1,3 +1,4 @@
+// REQUIRES: target={{x86_64-.*}}
 // RUN: %clang_dfsan -gmlt -mllvm -dfsan-track-origins=1 %s -o %t && \
 // RUN:     %run %t >%t.out 2>&1
 // RUN: FileCheck %s < %t.out

diff  --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 95c05a5f0c49..ae93be80737c 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -287,14 +287,23 @@ struct MemoryMapParams {
 
 } // end anonymous namespace
 
+// NOLINTBEGIN(readability-identifier-naming)
+// aarch64 Linux
+const MemoryMapParams Linux_AArch64_MemoryMapParams = {
+    0,               // AndMask (not used)
+    0x0B00000000000, // XorMask
+    0,               // ShadowBase (not used)
+    0x0200000000000, // OriginBase
+};
+
 // x86_64 Linux
-// NOLINTNEXTLINE(readability-identifier-naming)
-static const MemoryMapParams Linux_X86_64_MemoryMapParams = {
+const MemoryMapParams Linux_X86_64_MemoryMapParams = {
     0,              // AndMask (not used)
     0x500000000000, // XorMask
     0,              // ShadowBase (not used)
     0x100000000000, // OriginBase
 };
+// NOLINTEND(readability-identifier-naming)
 
 namespace {
 
@@ -1112,9 +1121,16 @@ bool DataFlowSanitizer::initializeModule(Module &M) {
 
   if (TargetTriple.getOS() != Triple::Linux)
     report_fatal_error("unsupported operating system");
-  if (TargetTriple.getArch() != Triple::x86_64)
+  switch (TargetTriple.getArch()) {
+  case Triple::aarch64:
+    MapParams = &Linux_AArch64_MemoryMapParams;
+    break;
+  case Triple::x86_64:
+    MapParams = &Linux_X86_64_MemoryMapParams;
+    break;
+  default:
     report_fatal_error("unsupported architecture");
-  MapParams = &Linux_X86_64_MemoryMapParams;
+  }
 
   Mod = &M;
   Ctx = &M.getContext();


        


More information about the llvm-commits mailing list