[llvm] r194697 - [msan] Fast path optimization for wrap-indirect-calls feature of MemorySanitizer.
Timur Iskhodzhanov
timurrrr at google.com
Fri Nov 15 07:35:47 PST 2013
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