[llvm] r194697 - [msan] Fast path optimization for wrap-indirect-calls feature of MemorySanitizer.
Evgeniy Stepanov
eugeni.stepanov at gmail.com
Fri Nov 15 08:12:39 PST 2013
Makes sense, but lets see how it plays out first.
We can easily make this a common utility between msan/asan/whatever.
On Fri, Nov 15, 2013 at 7:35 PM, Timur Iskhodzhanov <timurrrr at google.com> wrote:
> Why is this specific to MSanDR?
> I'm pretty sure this is needed for DRASan too.
>
> 2013/11/14 Evgeniy Stepanov <eugeni.stepanov at gmail.com>:
>> Author: eugenis
>> Date: Thu Nov 14 06:29:04 2013
>> New Revision: 194697
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=194697&view=rev
>> Log:
>> [msan] Fast path optimization for wrap-indirect-calls feature of MemorySanitizer.
>>
>> Indirect call wrapping helps MSanDR (dynamic instrumentation companion tool
>> for MSan) to catch all cases where execution leaves a compiler-instrumented
>> module by allowing the tool to rewrite targets of indirect calls.
>>
>> This change is an optimization that skips wrapping for calls when target is
>> inside the current module. This relies on the linker providing symbols at the
>> begin and end of the module code (or code + data, does not really matter).
>> Gold linker provides such symbols by default. GNU (BFD) linker needs a link
>> flag: -Wl,--defsym=__executable_start=0.
>>
>> More info:
>> https://code.google.com/p/memory-sanitizer/wiki/MSanDR#Native_exec
>>
>> Modified:
>> llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp
>> llvm/trunk/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll
>>
>> Modified: llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp?rev=194697&r1=194696&r2=194697&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp (original)
>> +++ llvm/trunk/lib/Transforms/Instrumentation/MemorySanitizer.cpp Thu Nov 14 06:29:04 2013
>> @@ -190,6 +190,10 @@ static cl::opt<std::string> ClWrapIndire
>> cl::desc("Wrap indirect calls with a given function"),
>> cl::Hidden);
>>
>> +static cl::opt<bool> ClWrapIndirectCallsFast("msan-wrap-indirect-calls-fast",
>> + cl::desc("Do not wrap indirect calls with target in the same module"),
>> + cl::Hidden, cl::init(true));
>> +
>> namespace {
>>
>> /// \brief An instrumentation pass implementing detection of uninitialized
>> @@ -240,6 +244,9 @@ class MemorySanitizer : public FunctionP
>> /// function.
>> GlobalVariable *OriginTLS;
>>
>> + GlobalVariable *MsandrModuleStart;
>> + GlobalVariable *MsandrModuleEnd;
>> +
>> /// \brief The run-time callback to print a warning.
>> Value *WarningFn;
>> /// \brief Run-time helper that copies origin info for a memory range.
>> @@ -375,6 +382,17 @@ void MemorySanitizer::initializeCallback
>> IndirectCallWrapperFn = M.getOrInsertFunction(
>> ClWrapIndirectCalls, AnyFunctionPtrTy, AnyFunctionPtrTy, NULL);
>> }
>> +
>> + if (ClWrapIndirectCallsFast) {
>> + MsandrModuleStart = new GlobalVariable(
>> + M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage,
>> + 0, "__executable_start");
>> + MsandrModuleStart->setVisibility(GlobalVariable::HiddenVisibility);
>> + MsandrModuleEnd = new GlobalVariable(
>> + M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage,
>> + 0, "_end");
>> + MsandrModuleEnd->setVisibility(GlobalVariable::HiddenVisibility);
>> + }
>> }
>>
>> /// \brief Module-level initialization.
>> @@ -489,6 +507,7 @@ struct MemorySanitizerVisitor : public I
>> };
>> SmallVector<ShadowOriginAndInsertPoint, 16> InstrumentationList;
>> SmallVector<Instruction*, 16> StoreList;
>> + SmallVector<CallSite, 16> IndirectCallList;
>>
>> MemorySanitizerVisitor(Function &F, MemorySanitizer &MS)
>> : F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) {
>> @@ -588,6 +607,48 @@ struct MemorySanitizerVisitor : public I
>> DEBUG(dbgs() << "DONE:\n" << F);
>> }
>>
>> + void materializeIndirectCalls() {
>> + for (size_t i = 0, n = IndirectCallList.size(); i < n; i++) {
>> + CallSite CS = IndirectCallList[i];
>> + Instruction *I = CS.getInstruction();
>> + BasicBlock *B = I->getParent();
>> + IRBuilder<> IRB(I);
>> + Value *Fn0 = CS.getCalledValue();
>> + Value *Fn = IRB.CreateBitCast(Fn0, MS.AnyFunctionPtrTy);
>> +
>> + if (ClWrapIndirectCallsFast) {
>> + // Check that call target is inside this module limits.
>> + Value *Start =
>> + IRB.CreateBitCast(MS.MsandrModuleStart, MS.AnyFunctionPtrTy);
>> + Value *End = IRB.CreateBitCast(MS.MsandrModuleEnd, MS.AnyFunctionPtrTy);
>> +
>> + Value *NotInThisModule = IRB.CreateOr(IRB.CreateICmpULT(Fn, Start),
>> + IRB.CreateICmpUGE(Fn, End));
>> +
>> + PHINode *NewFnPhi =
>> + IRB.CreatePHI(Fn0->getType(), 2, "msandr.indirect_target");
>> +
>> + Instruction *CheckTerm = SplitBlockAndInsertIfThen(
>> + cast<Instruction>(NotInThisModule),
>> + /* Unreachable */ false, MS.ColdCallWeights);
>> +
>> + IRB.SetInsertPoint(CheckTerm);
>> + // Slow path: call wrapper function to possibly transform the call
>> + // target.
>> + Value *NewFn = IRB.CreateBitCast(
>> + IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->getType());
>> +
>> + NewFnPhi->addIncoming(Fn0, B);
>> + NewFnPhi->addIncoming(NewFn, dyn_cast<Instruction>(NewFn)->getParent());
>> + CS.setCalledFunction(NewFnPhi);
>> + } else {
>> + Value *NewFn = IRB.CreateBitCast(
>> + IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->getType());
>> + CS.setCalledFunction(NewFn);
>> + }
>> + }
>> + }
>> +
>> /// \brief Add MemorySanitizer instrumentation to a function.
>> bool runOnFunction() {
>> MS.initializeCallbacks(*F.getParent());
>> @@ -630,6 +691,9 @@ struct MemorySanitizerVisitor : public I
>> // Insert shadow value checks.
>> materializeChecks();
>>
>> + // Wrap indirect calls.
>> + materializeIndirectCalls();
>> +
>> return true;
>> }
>>
>> @@ -1809,17 +1873,6 @@ struct MemorySanitizerVisitor : public I
>> }
>> }
>>
>> - // Replace call to (*Fn) with a call to (*IndirectCallWrapperFn(Fn)).
>> - void wrapIndirectCall(IRBuilder<> &IRB, CallSite CS) {
>> - Value *Fn = CS.getCalledValue();
>> - Value *NewFn = IRB.CreateBitCast(
>> - IRB.CreateCall(MS.IndirectCallWrapperFn,
>> - IRB.CreateBitCast(Fn, MS.AnyFunctionPtrTy)),
>> - Fn->getType());
>> - setShadow(NewFn, getShadow(Fn));
>> - CS.setCalledFunction(NewFn);
>> - }
>> -
>> void visitCallSite(CallSite CS) {
>> Instruction &I = *CS.getInstruction();
>> assert((CS.isCall() || CS.isInvoke()) && "Unknown type of CallSite");
>> @@ -1860,7 +1913,7 @@ struct MemorySanitizerVisitor : public I
>> IRBuilder<> IRB(&I);
>>
>> if (MS.WrapIndirectCalls && !CS.getCalledFunction())
>> - wrapIndirectCall(IRB, CS);
>> + IndirectCallList.push_back(CS);
>>
>> unsigned ArgOffset = 0;
>> DEBUG(dbgs() << " CallSite: " << I << "\n");
>>
>> Modified: llvm/trunk/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll?rev=194697&r1=194696&r2=194697&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll (original)
>> +++ llvm/trunk/test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll Thu Nov 14 06:29:04 2013
>> @@ -1,4 +1,5 @@
>> -; RUN: opt < %s -msan -msan-check-access-address=0 -msan-wrap-indirect-calls=zzz -S | FileCheck %s
>> +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-wrap-indirect-calls=zzz -msan-wrap-indirect-calls-fast=0 -S | FileCheck %s
>> +; RUN: opt < %s -msan -msan-check-access-address=0 -msan-wrap-indirect-calls=zzz -msan-wrap-indirect-calls-fast=1 -S | FileCheck -check-prefix=CHECK-FAST %s
>> target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
>> target triple = "x86_64-unknown-linux-gnu"
>>
>> @@ -16,6 +17,18 @@ entry:
>> ; CHECK: @func
>> ; CHECK: bitcast i32 (i32, i32)* %f to void ()*
>> ; CHECK: call void ()* (void ()*)* @zzz(void ()*
>> -; CHECK: [[A:%[01-9a-z]+]] = bitcast void ()* {{.*}} to i32 (i32, i32)*
>> +; CHECK: [[A:%[01-9a-z_.]+]] = bitcast void ()* {{.*}} to i32 (i32, i32)*
>> ; CHECK: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}})
>> ; CHECK: ret i32
>> +
>> +; CHECK-FAST: @func
>> +; CHECK-FAST: bitcast i32 (i32, i32)* %f to void ()*
>> +; CHECK-FAST: icmp ult void ()* {{.*}}, bitcast (i32* @__executable_start to void ()*)
>> +; CHECK-FAST: icmp uge void ()* {{.*}}, bitcast (i32* @_end to void ()*)
>> +; CHECK-FAST: or i1
>> +; CHECK-FAST: br i1
>> +; CHECK-FAST: call void ()* (void ()*)* @zzz(void ()*
>> +; CHECK-FAST: br label
>> +; CHECK-FAST: [[A:%[01-9a-z_.]+]] = phi i32 (i32, i32)* [ %f, %entry ], [ {{.*}} ]
>> +; CHECK-FAST: call i32 {{.*}}[[A]](i32 {{.*}}, i32 {{.*}})
>> +; CHECK-FAST: ret i32
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list