diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2013-09-19 15:22:35 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2013-09-19 15:22:35 +0000 |
commit | 6591308b7e041bb8e5e211f84bcc4a97d3764cc5 (patch) | |
tree | d60a58ca196056d63ec0a41701c7643b979cca3b /lib | |
parent | 530d09a22bd2f5c638ae1932bed560c8a46e399e (diff) | |
download | llvm-6591308b7e041bb8e5e211f84bcc4a97d3764cc5.tar.gz llvm-6591308b7e041bb8e5e211f84bcc4a97d3764cc5.tar.bz2 llvm-6591308b7e041bb8e5e211f84bcc4a97d3764cc5.tar.xz |
[msan] Wrap indirect functions.
Adds a flag to the MemorySanitizer pass that enables runtime rewriting of
indirect calls. This is part of MSanDR implementation and is needed to return
control to the DynamiRio-based helper tool on transition between instrumented
and non-instrumented modules. Disabled by default.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191006 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Transforms/Instrumentation/MemorySanitizer.cpp | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 9a67cfc5a7..cab7a7a019 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -157,6 +157,14 @@ static cl::opt<std::string> ClBlacklistFile("msan-blacklist", cl::desc("File containing the list of functions where MemorySanitizer " "should not report bugs"), cl::Hidden); +// Experimental. Wraps all indirect calls in the instrumented code with +// a call to the given function. This is needed to assist the dynamic +// helper tool (MSanDR) to regain control on transition between instrumented and +// non-instrumented code. +static cl::opt<std::string> ClWrapIndirectCalls("msan-wrap-indirect-calls", + cl::desc("Wrap indirect calls with a given function"), + cl::Hidden); + namespace { /// \brief An instrumentation pass implementing detection of uninitialized @@ -168,12 +176,12 @@ class MemorySanitizer : public FunctionPass { public: MemorySanitizer(bool TrackOrigins = false, StringRef BlacklistFile = StringRef()) - : FunctionPass(ID), - TrackOrigins(TrackOrigins || ClTrackOrigins), - TD(0), - WarningFn(0), - BlacklistFile(BlacklistFile.empty() ? ClBlacklistFile - : BlacklistFile) { } + : FunctionPass(ID), + TrackOrigins(TrackOrigins || ClTrackOrigins), + TD(0), + WarningFn(0), + BlacklistFile(BlacklistFile.empty() ? ClBlacklistFile : BlacklistFile), + WrapIndirectCalls(!ClWrapIndirectCalls.empty()) {} const char *getPassName() const { return "MemorySanitizer"; } bool runOnFunction(Function &F); bool doInitialization(Module &M); @@ -236,6 +244,12 @@ class MemorySanitizer : public FunctionPass { /// \brief An empty volatile inline asm that prevents callback merge. InlineAsm *EmptyAsm; + bool WrapIndirectCalls; + /// \brief Run-time wrapper for indirect calls. + Value *IndirectCallWrapperFn; + // Argument and return type of IndirectCallWrapperFn: void (*f)(void). + Type *AnyFunctionPtrTy; + friend struct MemorySanitizerVisitor; friend struct VarArgAMD64Helper; }; @@ -329,6 +343,13 @@ void MemorySanitizer::initializeCallbacks(Module &M) { EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), /*hasSideEffects=*/true); + + if (WrapIndirectCalls) { + AnyFunctionPtrTy = + PointerType::getUnqual(FunctionType::get(IRB.getVoidTy(), false)); + IndirectCallWrapperFn = M.getOrInsertFunction( + ClWrapIndirectCalls, AnyFunctionPtrTy, AnyFunctionPtrTy, NULL); + } } /// \brief Module-level initialization. @@ -1570,6 +1591,17 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { } } + // 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"); @@ -1608,6 +1640,10 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { } } IRBuilder<> IRB(&I); + + if (MS.WrapIndirectCalls && !CS.getCalledFunction()) + wrapIndirectCall(IRB, CS); + unsigned ArgOffset = 0; DEBUG(dbgs() << " CallSite: " << I << "\n"); for (CallSite::arg_iterator ArgIt = CS.arg_begin(), End = CS.arg_end(); @@ -1651,7 +1687,7 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> { DEBUG(dbgs() << " done with call args\n"); FunctionType *FT = - cast<FunctionType>(CS.getCalledValue()->getType()-> getContainedType(0)); + cast<FunctionType>(CS.getCalledValue()->getType()->getContainedType(0)); if (FT->isVarArg()) { VAHelper->visitCallSite(CS, IRB); } |