diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2013-08-27 22:09:06 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2013-08-27 22:09:06 +0000 |
commit | ffba4c7e69cd0d0ef346e9845b918a030ca51ae8 (patch) | |
tree | ecdabc1734fc9dc478911f25a9400b5022514a08 /lib/Transforms/Instrumentation | |
parent | 7cde9d0286a8976feebb20e61612fb999527f630 (diff) | |
download | llvm-ffba4c7e69cd0d0ef346e9845b918a030ca51ae8.tar.gz llvm-ffba4c7e69cd0d0ef346e9845b918a030ca51ae8.tar.bz2 llvm-ffba4c7e69cd0d0ef346e9845b918a030ca51ae8.tar.xz |
DataFlowSanitizer: Implement trampolines for function pointers passed to custom functions.
Differential Revision: http://llvm-reviews.chandlerc.com/D1503
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189408 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Instrumentation')
-rw-r--r-- | lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | 80 |
1 files changed, 77 insertions, 3 deletions
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 2fa33834f1..8ee5482cea 100644 --- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -48,6 +48,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/IRBuilder.h" @@ -182,6 +183,7 @@ class DataFlowSanitizer : public ModulePass { bool isInstrumented(const Function *F); bool isInstrumented(const GlobalAlias *GA); FunctionType *getArgsFunctionType(FunctionType *T); + FunctionType *getTrampolineFunctionType(FunctionType *T); FunctionType *getCustomFunctionType(FunctionType *T); InstrumentedABI getInstrumentedABI(); WrapperKind getWrapperKind(Function *F); @@ -189,6 +191,7 @@ class DataFlowSanitizer : public ModulePass { Function *buildWrapperFunction(Function *F, StringRef NewFName, GlobalValue::LinkageTypes NewFLink, FunctionType *NewFT); + Constant *getOrBuildTrampolineFunction(FunctionType *FT, StringRef FName); public: DataFlowSanitizer(StringRef ABIListFile = StringRef(), @@ -288,9 +291,10 @@ FunctionType *DataFlowSanitizer::getArgsFunctionType(FunctionType *T) { return FunctionType::get(RetType, ArgTypes, T->isVarArg()); } -FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { +FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) { assert(!T->isVarArg()); llvm::SmallVector<Type *, 4> ArgTypes; + ArgTypes.push_back(T->getPointerTo()); std::copy(T->param_begin(), T->param_end(), std::back_inserter(ArgTypes)); for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) ArgTypes.push_back(ShadowTy); @@ -300,6 +304,27 @@ FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { return FunctionType::get(T->getReturnType(), ArgTypes, false); } +FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { + assert(!T->isVarArg()); + llvm::SmallVector<Type *, 4> ArgTypes; + for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end(); i != e; ++i) { + FunctionType *FT; + if (isa<PointerType>(*i) && + (FT = dyn_cast<FunctionType>(cast<PointerType>(*i)->getElementType()))) { + ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo()); + ArgTypes.push_back(Type::getInt8PtrTy(*Ctx)); + } else { + ArgTypes.push_back(*i); + } + } + for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) + ArgTypes.push_back(ShadowTy); + Type *RetType = T->getReturnType(); + if (!RetType->isVoidTy()) + ArgTypes.push_back(ShadowPtrTy); + return FunctionType::get(T->getReturnType(), ArgTypes, false); +} + bool DataFlowSanitizer::doInitialization(Module &M) { DL = getAnalysisIfAvailable<DataLayout>(); if (!DL) @@ -417,6 +442,39 @@ DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName, return NewF; } +Constant *DataFlowSanitizer::getOrBuildTrampolineFunction(FunctionType *FT, + StringRef FName) { + FunctionType *FTT = getTrampolineFunctionType(FT); + Constant *C = Mod->getOrInsertFunction(FName, FTT); + Function *F = dyn_cast<Function>(C); + if (F && F->isDeclaration()) { + F->setLinkage(GlobalValue::LinkOnceODRLinkage); + BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); + std::vector<Value *> Args; + Function::arg_iterator AI = F->arg_begin(); ++AI; + for (unsigned N = FT->getNumParams(); N != 0; ++AI, --N) + Args.push_back(&*AI); + CallInst *CI = + CallInst::Create(&F->getArgumentList().front(), Args, "", BB); + ReturnInst *RI; + if (FT->getReturnType()->isVoidTy()) + RI = ReturnInst::Create(*Ctx, BB); + else + RI = ReturnInst::Create(*Ctx, CI, BB); + + DFSanFunction DFSF(*this, F, /*IsNativeABI=*/true); + Function::arg_iterator ValAI = F->arg_begin(), ShadowAI = AI; ++ValAI; + for (unsigned N = FT->getNumParams(); N != 0; ++ValAI, ++ShadowAI, --N) + DFSF.ValShadowMap[ValAI] = ShadowAI; + DFSanVisitor(DFSF).visitCallInst(*CI); + if (!FT->getReturnType()->isVoidTy()) + new StoreInst(DFSF.getShadow(RI->getReturnValue()), + &F->getArgumentList().back(), RI); + } + + return C; +} + bool DataFlowSanitizer::runOnModule(Module &M) { if (!DL) return false; @@ -1181,8 +1239,24 @@ void DFSanVisitor::visitCallSite(CallSite CS) { std::vector<Value *> Args; CallSite::arg_iterator i = CS.arg_begin(); - for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) - Args.push_back(*i); + for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) { + Type *T = (*i)->getType(); + FunctionType *ParamFT; + if (isa<PointerType>(T) && + (ParamFT = dyn_cast<FunctionType>( + cast<PointerType>(T)->getElementType()))) { + std::string TName = "dfst"; + TName += utostr(FT->getNumParams() - n); + TName += "$"; + TName += F->getName(); + Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName); + Args.push_back(T); + Args.push_back( + IRB.CreateBitCast(*i, Type::getInt8PtrTy(*DFSF.DFS.Ctx))); + } else { + Args.push_back(*i); + } + } i = CS.arg_begin(); for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) |