[compiler-rt] 39295e9 - Revert "[DFSan] Cleanup code for platforms other than Linux x86_64."

Andrew Browne via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 17 14:19:57 PDT 2021


Author: Andrew Browne
Date: 2021-06-17T14:19:18-07:00
New Revision: 39295e92f7f991a745743dd2c888f0a774047f2a

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

LOG: Revert "[DFSan] Cleanup code for platforms other than Linux x86_64."

This reverts commit 8441b993bdba29437b296bad6a37464669eef35e.

Buildbot failures.

Added: 
    llvm/test/Instrumentation/DataFlowSanitizer/external_mask.ll

Modified: 
    compiler-rt/lib/dfsan/dfsan.cpp
    compiler-rt/lib/dfsan/dfsan_platform.h
    llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp
index 1b2d552f2d5cf..6e9ad107e2233 100644
--- a/compiler-rt/lib/dfsan/dfsan.cpp
+++ b/compiler-rt/lib/dfsan/dfsan.cpp
@@ -88,8 +88,72 @@ int __dfsan_get_track_origins() {
 // 45-46 are cleared to bring the address into the range
 // [0x100000008000,0x200000000000).  See the function shadow_for below.
 //
+// On Linux/MIPS64, memory is laid out as follows:
 //
+// +--------------------+ 0x10000000000 (top of memory)
+// | application memory |
+// +--------------------+ 0xF000008000 (kAppAddr)
+// |                    |
+// |       unused       |
+// |                    |
+// +--------------------+ 0x2000000000 (kUnusedAddr)
+// |   shadow memory    |
+// +--------------------+ 0x1000008000 (kShadowAddr)
+// |       unused       |
+// +--------------------+ 0x0000010000
+// | reserved by kernel |
+// +--------------------+ 0x0000000000
+
+// On Linux/AArch64 (39-bit VMA), memory is laid out as follow:
+//
+// +--------------------+ 0x8000000000 (top of memory)
+// | application memory |
+// +--------------------+ 0x7000008000 (kAppAddr)
+// |                    |
+// |       unused       |
+// |                    |
+// +--------------------+ 0x1000000000 (kUnusedAddr)
+// |   shadow memory    |
+// +--------------------+ 0x0000010000 (kShadowAddr)
+// | reserved by kernel |
+// +--------------------+ 0x0000000000
 
+// On Linux/AArch64 (42-bit VMA), memory is laid out as follow:
+//
+// +--------------------+ 0x40000000000 (top of memory)
+// | application memory |
+// +--------------------+ 0x3ff00008000 (kAppAddr)
+// |                    |
+// |       unused       |
+// |                    |
+// +--------------------+ 0x8000000000 (kUnusedAddr)
+// |   shadow memory    |
+// +--------------------+ 0x0000010000 (kShadowAddr)
+// | reserved by kernel |
+// +--------------------+ 0x0000000000
+
+// On Linux/AArch64 (48-bit VMA), memory is laid out as follow:
+//
+// +--------------------+ 0x1000000000000 (top of memory)
+// | application memory |
+// +--------------------+ 0xffff00008000 (kAppAddr)
+// |       unused       |
+// +--------------------+ 0xaaaab0000000 (top of PIE address)
+// | application PIE    |
+// +--------------------+ 0xaaaaa0000000 (top of PIE address)
+// |                    |
+// |       unused       |
+// |                    |
+// +--------------------+ 0x8000000000 (kUnusedAddr)
+// |   shadow memory    |
+// +--------------------+ 0x0000010000 (kShadowAddr)
+// | reserved by kernel |
+// +--------------------+ 0x0000000000
+
+#ifdef DFSAN_RUNTIME_VMA
+// Runtime detected VMA size.
+int __dfsan::vmaSize;
+#endif
 
 extern "C" SANITIZER_INTERFACE_ATTRIBUTE
 dfsan_label __dfsan_union_load(const dfsan_label *ls, uptr n) {
@@ -835,6 +899,22 @@ void dfsan_clear_thread_local_state() {
   }
 }
 
+static void InitializePlatformEarly() {
+  AvoidCVE_2016_2143();
+#ifdef DFSAN_RUNTIME_VMA
+  __dfsan::vmaSize =
+    (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
+  if (__dfsan::vmaSize == 39 || __dfsan::vmaSize == 42 ||
+      __dfsan::vmaSize == 48) {
+    __dfsan_shadow_ptr_mask = ShadowMask();
+  } else {
+    Printf("FATAL: DataFlowSanitizer: unsupported VMA range\n");
+    Printf("FATAL: Found %d - Supported 39, 42, and 48\n", __dfsan::vmaSize);
+    Die();
+  }
+#endif
+}
+
 extern "C" void dfsan_flush() {
   if (!MmapFixedSuperNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()))
     Die();
@@ -847,10 +927,10 @@ static void DFsanInit(int argc, char **argv, char **envp) {
   dfsan_init_is_running = true;
   SanitizerToolName = "DataflowSanitizer";
 
-  AvoidCVE_2016_2143();
-
   InitializeFlags();
 
+  ::InitializePlatformEarly();
+
   dfsan_flush();
   if (common_flags()->use_madv_dontdump)
     DontDumpShadowMemory(ShadowAddr(), UnusedAddr() - ShadowAddr());

diff  --git a/compiler-rt/lib/dfsan/dfsan_platform.h b/compiler-rt/lib/dfsan/dfsan_platform.h
index 64a093ff97d1d..8f64227c98593 100644
--- a/compiler-rt/lib/dfsan/dfsan_platform.h
+++ b/compiler-rt/lib/dfsan/dfsan_platform.h
@@ -20,6 +20,7 @@ namespace __dfsan {
 
 using __sanitizer::uptr;
 
+#if defined(__x86_64__)
 struct Mapping {
   static const uptr kShadowAddr = 0x100000008000;
   static const uptr kOriginAddr = 0x200000008000;
@@ -27,10 +28,46 @@ struct Mapping {
   static const uptr kAppAddr = 0x700000008000;
   static const uptr kShadowMask = ~0x600000000000;
 };
+#elif defined(__mips64)
+struct Mapping {
+  static const uptr kShadowAddr = 0x1000008000;
+  static const uptr kUnusedAddr = 0x2000000000;
+  static const uptr kAppAddr = 0xF000008000;
+  static const uptr kShadowMask = ~0xE000000000;
+};
+#elif defined(__aarch64__)
+struct Mapping39 {
+  static const uptr kShadowAddr = 0x10000;
+  static const uptr kUnusedAddr = 0x1000000000;
+  static const uptr kAppAddr = 0x7000008000;
+  static const uptr kShadowMask = ~0x7800000000;
+};
+
+struct Mapping42 {
+  static const uptr kShadowAddr = 0x10000;
+  static const uptr kUnusedAddr = 0x8000000000;
+  static const uptr kAppAddr = 0x3ff00008000;
+  static const uptr kShadowMask = ~0x3c000000000;
+};
+
+struct Mapping48 {
+  static const uptr kShadowAddr = 0x10000;
+  static const uptr kUnusedAddr = 0x8000000000;
+  static const uptr kAppAddr = 0xffff00008000;
+  static const uptr kShadowMask = ~0xfffff0000000;
+};
+
+extern int vmaSize;
+# define DFSAN_RUNTIME_VMA 1
+#else
+# error "DFSan not supported for this platform!"
+#endif
 
 enum MappingType {
   MAPPING_SHADOW_ADDR,
+#if defined(__x86_64__)
   MAPPING_ORIGIN_ADDR,
+#endif
   MAPPING_UNUSED_ADDR,
   MAPPING_APP_ADDR,
   MAPPING_SHADOW_MASK
@@ -53,7 +90,17 @@ uptr MappingImpl(void) {
 
 template<int Type>
 uptr MappingArchImpl(void) {
+#ifdef __aarch64__
+  switch (vmaSize) {
+    case 39: return MappingImpl<Mapping39, Type>();
+    case 42: return MappingImpl<Mapping42, Type>();
+    case 48: return MappingImpl<Mapping48, Type>();
+  }
+  DCHECK(0);
+  return 0;
+#else
   return MappingImpl<Mapping, Type>();
+#endif
 }
 
 ALWAYS_INLINE
@@ -63,7 +110,11 @@ uptr ShadowAddr() {
 
 ALWAYS_INLINE
 uptr OriginAddr() {
+#if defined(__x86_64__)
   return MappingArchImpl<MAPPING_ORIGIN_ADDR>();
+#else
+  return 0;
+#endif
 }
 
 ALWAYS_INLINE

diff  --git a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index 708df2895a0d5..ae375314f994d 100644
--- a/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -123,6 +123,11 @@ static const Align MinOriginAlignment = Align(4);
 static const unsigned ArgTLSSize = 800;
 static const unsigned RetvalTLSSize = 800;
 
+// External symbol to be used when generating the shadow address for
+// architectures with multiple VMAs. Instead of using a constant integer
+// the runtime will set the external mask based on the VMA range.
+const char DFSanExternShadowPtrMask[] = "__dfsan_shadow_ptr_mask";
+
 // The -dfsan-preserve-alignment flag controls whether this pass assumes that
 // alignment requirements provided by the input IR are correct.  For example,
 // if the input IR contains a load with alignment 8, this flag will cause
@@ -398,6 +403,7 @@ class DataFlowSanitizer {
   Constant *ArgOriginTLS;
   Constant *RetvalTLS;
   Constant *RetvalOriginTLS;
+  Constant *ExternalShadowMask;
   FunctionType *DFSanUnionLoadFnTy;
   FunctionType *DFSanLoadLabelAndOriginFnTy;
   FunctionType *DFSanUnimplementedFnTy;
@@ -431,6 +437,7 @@ class DataFlowSanitizer {
   DFSanABIList ABIList;
   DenseMap<Value *, Function *> UnwrappedFnMap;
   AttrBuilder ReadOnlyNoneAttrs;
+  bool DFSanRuntimeShadowMask = false;
 
   Value *getShadowOffset(Value *Addr, IRBuilder<> &IRB);
   Value *getShadowAddress(Value *Addr, Instruction *Pos);
@@ -1006,11 +1013,6 @@ bool DataFlowSanitizer::init(Module &M) {
   Triple TargetTriple(M.getTargetTriple());
   const DataLayout &DL = M.getDataLayout();
 
-  if (TargetTriple.getOS() != Triple::Linux)
-    report_fatal_error("unsupported operating system");
-  if (TargetTriple.getArch() != Triple::x86_64)
-    report_fatal_error("unsupported architecture");
-
   Mod = &M;
   Ctx = &M.getContext();
   Int8Ptr = Type::getInt8PtrTy(*Ctx);
@@ -1022,9 +1024,27 @@ bool DataFlowSanitizer::init(Module &M) {
   ZeroPrimitiveShadow = ConstantInt::getSigned(PrimitiveShadowTy, 0);
   ZeroOrigin = ConstantInt::getSigned(OriginTy, 0);
 
+  // TODO: these should be platform-specific and set in the switch-stmt below.
   ShadowBase = ConstantInt::get(IntptrTy, 0x100000008000LL);
   OriginBase = ConstantInt::get(IntptrTy, 0x200000008000LL);
-  ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x600000000000LL);
+
+  switch (TargetTriple.getArch()) {
+  case Triple::x86_64:
+    ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x600000000000LL);
+    break;
+  case Triple::mips64:
+  case Triple::mips64el:
+    ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xE000000000LL);
+    break;
+  case Triple::aarch64:
+  case Triple::aarch64_be:
+    // AArch64 supports multiple VMAs and the shadow mask is set at runtime.
+    DFSanRuntimeShadowMask = true;
+    break;
+  default:
+    report_fatal_error("unsupported triple");
+  }
+
   Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
   DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
                                          /*isVarArg=*/false);
@@ -1370,6 +1390,9 @@ bool DataFlowSanitizer::runImpl(Module &M) {
 
   injectMetadataGlobals(M);
 
+  ExternalShadowMask =
+      Mod->getOrInsertGlobal(DFSanExternShadowPtrMask, IntptrTy);
+
   initializeCallbackFunctions(M);
   initializeRuntimeFunctions(M);
 
@@ -1718,8 +1741,13 @@ void DFSanFunction::setShadow(Instruction *I, Value *Shadow) {
 Value *DataFlowSanitizer::getShadowOffset(Value *Addr, IRBuilder<> &IRB) {
   // Returns Addr & shadow_mask
   assert(Addr != RetvalTLS && "Reinstrumenting?");
+  Value *ShadowPtrMaskValue;
+  if (DFSanRuntimeShadowMask)
+    ShadowPtrMaskValue = IRB.CreateLoad(IntptrTy, ExternalShadowMask);
+  else
+    ShadowPtrMaskValue = ShadowPtrMask;
   return IRB.CreateAnd(IRB.CreatePtrToInt(Addr, IntptrTy),
-                       IRB.CreatePtrToInt(ShadowPtrMask, IntptrTy));
+                       IRB.CreatePtrToInt(ShadowPtrMaskValue, IntptrTy));
 }
 
 std::pair<Value *, Value *>

diff  --git a/llvm/test/Instrumentation/DataFlowSanitizer/external_mask.ll b/llvm/test/Instrumentation/DataFlowSanitizer/external_mask.ll
new file mode 100644
index 0000000000000..26491f50a00f2
--- /dev/null
+++ b/llvm/test/Instrumentation/DataFlowSanitizer/external_mask.ll
@@ -0,0 +1,13 @@
+; RUN: opt < %s -dfsan -S | FileCheck %s
+target datalayout = "e-m:e-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-unknown-linux-gnu"
+
+define i32 @test(i32 %a, i32* nocapture readonly %b) #0 {
+  ; CHECK: @"dfs$test"
+  ; CHECK: %[[RV:.*]] load{{.*}}__dfsan_shadow_ptr_mask
+  ; CHECK: ptrtoint i32* {{.*}} to i64
+  ; CHECK: and {{.*}}%[[RV:.*]]
+  %1 = load i32, i32* %b, align 4
+  %2 = add nsw i32 %1, %a
+  ret i32 %2
+}


        


More information about the llvm-commits mailing list