From: Adhemerval Zanella Date: Fri, 27 Nov 2015 12:42:39 +0000 (+0000) Subject: [sanitizer] [dfsan] Unify aarch64 mapping X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=7fe65325391a0e349567d5ec386b46a341ae374d [sanitizer] [dfsan] Unify aarch64 mapping This patch changes the DFSan instrumentation for aarch64 to instead of using fixes application mask defined by SANITIZER_AARCH64_VMA to read the application shadow mask value from compiler-rt. The value is initialized based on runtime VAM detection. Along with this patch a compiler-rt one will also be added to export the shadow mask variable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254196 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 21ef3207e89..d459fc50d13 100644 --- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -72,15 +72,10 @@ using namespace llvm; -// VMA size definition for architecture that support multiple sizes. -// AArch64 has 3 VMA sizes: 39, 42 and 48. -#ifndef SANITIZER_AARCH64_VMA -# define SANITIZER_AARCH64_VMA 39 -#else -# if SANITIZER_AARCH64_VMA != 39 && SANITIZER_AARCH64_VMA != 42 -# error "invalid SANITIZER_AARCH64_VMA size" -# endif -#endif +// 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. +static const char *const kDFSanExternShadowPtrMask = "__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, @@ -134,6 +129,7 @@ static cl::opt ClDebugNonzeroLabels( "load or return with a nonzero label"), cl::Hidden); + namespace { StringRef GetGlobalTypeString(const GlobalValue &G) { @@ -241,6 +237,7 @@ class DataFlowSanitizer : public ModulePass { void *(*GetRetvalTLSPtr)(); Constant *GetArgTLS; Constant *GetRetvalTLS; + Constant *ExternalShadowMask; FunctionType *DFSanUnionFnTy; FunctionType *DFSanUnionLoadFnTy; FunctionType *DFSanUnimplementedFnTy; @@ -258,6 +255,7 @@ class DataFlowSanitizer : public ModulePass { DFSanABIList ABIList; DenseMap UnwrappedFnMap; AttributeSet ReadOnlyNoneAttrs; + bool DFSanRuntimeShadowMask; Value *getShadowAddress(Value *Addr, Instruction *Pos); bool isInstrumented(const Function *F); @@ -371,7 +369,8 @@ llvm::createDataFlowSanitizerPass(const std::vector &ABIListFiles, DataFlowSanitizer::DataFlowSanitizer( const std::vector &ABIListFiles, void *(*getArgTLS)(), void *(*getRetValTLS)()) - : ModulePass(ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS) { + : ModulePass(ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS), + DFSanRuntimeShadowMask(false) { std::vector AllABIListFiles(std::move(ABIListFiles)); AllABIListFiles.insert(AllABIListFiles.end(), ClABIListFiles.begin(), ClABIListFiles.end()); @@ -445,12 +444,9 @@ bool DataFlowSanitizer::doInitialization(Module &M) { ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x700000000000LL); else if (IsMIPS64) ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xF000000000LL); + // AArch64 supports multiple VMAs and the shadow mask is set at runtime. else if (IsAArch64) -#if SANITIZER_AARCH64_VMA == 39 - ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x7800000000LL); -#else - ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x3c000000000LL); -#endif + DFSanRuntimeShadowMask = true; else report_fatal_error("unsupported triple"); @@ -621,6 +617,9 @@ bool DataFlowSanitizer::runOnModule(Module &M) { G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel); } + ExternalShadowMask = + Mod->getOrInsertGlobal(kDFSanExternShadowPtrMask, IntptrTy); + DFSanUnionFn = Mod->getOrInsertFunction("__dfsan_union", DFSanUnionFnTy); if (Function *F = dyn_cast(DFSanUnionFn)) { F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); @@ -938,9 +937,15 @@ void DFSanFunction::setShadow(Instruction *I, Value *Shadow) { Value *DataFlowSanitizer::getShadowAddress(Value *Addr, Instruction *Pos) { assert(Addr != RetvalTLS && "Reinstrumenting?"); IRBuilder<> IRB(Pos); + Value *ShadowPtrMaskValue; + if (DFSanRuntimeShadowMask) + ShadowPtrMaskValue = IRB.CreateLoad(IntptrTy, ExternalShadowMask); + else + ShadowPtrMaskValue = ShadowPtrMask; return IRB.CreateIntToPtr( IRB.CreateMul( - IRB.CreateAnd(IRB.CreatePtrToInt(Addr, IntptrTy), ShadowPtrMask), + IRB.CreateAnd(IRB.CreatePtrToInt(Addr, IntptrTy), + IRB.CreatePtrToInt(ShadowPtrMaskValue, IntptrTy)), ShadowPtrMul), ShadowPtrTy); } diff --git a/test/Instrumentation/DataFlowSanitizer/external_mask.ll b/test/Instrumentation/DataFlowSanitizer/external_mask.ll new file mode 100644 index 00000000000..db4c14ed958 --- /dev/null +++ b/test/Instrumentation/DataFlowSanitizer/external_mask.ll @@ -0,0 +1,14 @@ +; 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:.*]] +; CHECK: mul i64 + %1 = load i32, i32* %b, align 4 + %2 = add nsw i32 %1, %a + ret i32 %2 +}