[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