diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2017-11-15 00:11:51 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2017-11-15 00:11:51 +0000 |
commit | cff19ee2330f86e3f3cc320b89e928c97437b932 (patch) | |
tree | f18f594c4523b2ffc7c5f302e19c9cba455205bf /llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | |
parent | 8202521cf57bf1cbe77e3fe3228e15580b1388d3 (diff) | |
download | bcm5719-llvm-cff19ee2330f86e3f3cc320b89e928c97437b932.tar.gz bcm5719-llvm-cff19ee2330f86e3f3cc320b89e928c97437b932.zip |
[asan] Prevent rematerialization of &__asan_shadow.
Summary:
In the mode when ASan shadow base is computed as the address of an
external global (__asan_shadow, currently on android/arm32 only),
regalloc prefers to rematerialize this value to save register spills.
Even in -Os. On arm32 it is rather expensive (2 loads + 1 constant
pool entry).
This changes adds an inline asm in the function prologue to suppress
this behavior. It reduces AsanTest binary size by 7%.
Reviewers: pcc, vitalybuka
Subscribers: aemerson, kristof.beyls, hiraditya, llvm-commits
Differential Revision: https://reviews.llvm.org/D40048
llvm-svn: 318235
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index d2e15ee649d..9681de4e885 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -211,7 +211,13 @@ static cl::opt<bool> ClWithIfunc("asan-with-ifunc", cl::desc("Access dynamic shadow through an ifunc global on " "platforms that support this"), - cl::Hidden, cl::init(false)); + cl::Hidden, cl::init(true)); + +static cl::opt<bool> ClWithIfuncSuppressRemat( + "asan-with-ifunc-suppress-remat", + cl::desc("Suppress rematerialization of dynamic shadow address by passing " + "it through inline asm in prologue."), + cl::Hidden, cl::init(true)); // This flag limits the number of instructions to be instrumented // in any given BB. Normally, this should be set to unlimited (INT_MAX), @@ -988,8 +994,9 @@ struct FunctionStackPoisoner : public InstVisitor<FunctionStackPoisoner> { void visitCallSite(CallSite CS) { Instruction *I = CS.getInstruction(); if (CallInst *CI = dyn_cast<CallInst>(I)) { - HasNonEmptyInlineAsm |= - CI->isInlineAsm() && !CI->isIdenticalTo(EmptyInlineAsm.get()); + HasNonEmptyInlineAsm |= CI->isInlineAsm() && + !CI->isIdenticalTo(EmptyInlineAsm.get()) && + I != ASan.LocalDynamicShadow; HasReturnsTwiceCall |= CI->canReturnTwice(); } } @@ -1121,11 +1128,6 @@ Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB) { if (Mapping.Offset == 0) return Shadow; // (Shadow >> scale) | offset Value *ShadowBase; - if (Mapping.InGlobal) - return IRB.CreatePtrToInt( - IRB.CreateGEP(AsanShadowGlobal, - {ConstantInt::get(IntptrTy, 0), Shadow}), - IntptrTy); if (LocalDynamicShadow) ShadowBase = LocalDynamicShadow; else @@ -2343,13 +2345,29 @@ bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) { void AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(Function &F) { // Generate code only when dynamic addressing is needed. - if (Mapping.Offset != kDynamicShadowSentinel || Mapping.InGlobal) + if (Mapping.Offset != kDynamicShadowSentinel) return; IRBuilder<> IRB(&F.front().front()); - Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal( - kAsanShadowMemoryDynamicAddress, IntptrTy); - LocalDynamicShadow = IRB.CreateLoad(GlobalDynamicAddress); + if (Mapping.InGlobal) { + if (ClWithIfuncSuppressRemat) { + // An empty inline asm with input reg == output reg. + // An opaque pointer-to-int cast, basically. + InlineAsm *Asm = InlineAsm::get( + FunctionType::get(IntptrTy, {AsanShadowGlobal->getType()}, false), + StringRef(""), StringRef("=r,0"), + /*hasSideEffects=*/false); + LocalDynamicShadow = + IRB.CreateCall(Asm, {AsanShadowGlobal}, ".asan.shadow"); + } else { + LocalDynamicShadow = + IRB.CreatePointerCast(AsanShadowGlobal, IntptrTy, ".asan.shadow"); + } + } else { + Value *GlobalDynamicAddress = F.getParent()->getOrInsertGlobal( + kAsanShadowMemoryDynamicAddress, IntptrTy); + LocalDynamicShadow = IRB.CreateLoad(GlobalDynamicAddress); + } } void AddressSanitizer::markEscapedLocalAllocas(Function &F) { |