[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