diff options
Diffstat (limited to 'lib/Transforms/Instrumentation/DataFlowSanitizer.cpp')
-rw-r--r-- | lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | 137 |
1 files changed, 110 insertions, 27 deletions
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 09bcbb282653..bb0e4379d1a8 100644 --- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -56,6 +56,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Attributes.h" @@ -90,7 +91,6 @@ #include "llvm/Support/SpecialCaseList.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -211,6 +211,72 @@ class DFSanABIList { } }; +/// TransformedFunction is used to express the result of transforming one +/// function type into another. This struct is immutable. It holds metadata +/// useful for updating calls of the old function to the new type. +struct TransformedFunction { + TransformedFunction(FunctionType* OriginalType, + FunctionType* TransformedType, + std::vector<unsigned> ArgumentIndexMapping) + : OriginalType(OriginalType), + TransformedType(TransformedType), + ArgumentIndexMapping(ArgumentIndexMapping) {} + + // Disallow copies. + TransformedFunction(const TransformedFunction&) = delete; + TransformedFunction& operator=(const TransformedFunction&) = delete; + + // Allow moves. + TransformedFunction(TransformedFunction&&) = default; + TransformedFunction& operator=(TransformedFunction&&) = default; + + /// Type of the function before the transformation. + FunctionType* const OriginalType; + + /// Type of the function after the transformation. + FunctionType* const TransformedType; + + /// Transforming a function may change the position of arguments. This + /// member records the mapping from each argument's old position to its new + /// position. Argument positions are zero-indexed. If the transformation + /// from F to F' made the first argument of F into the third argument of F', + /// then ArgumentIndexMapping[0] will equal 2. + const std::vector<unsigned> ArgumentIndexMapping; +}; + +/// Given function attributes from a call site for the original function, +/// return function attributes appropriate for a call to the transformed +/// function. +AttributeList TransformFunctionAttributes( + const TransformedFunction& TransformedFunction, + LLVMContext& Ctx, AttributeList CallSiteAttrs) { + + // Construct a vector of AttributeSet for each function argument. + std::vector<llvm::AttributeSet> ArgumentAttributes( + TransformedFunction.TransformedType->getNumParams()); + + // Copy attributes from the parameter of the original function to the + // transformed version. 'ArgumentIndexMapping' holds the mapping from + // old argument position to new. + for (unsigned i=0, ie = TransformedFunction.ArgumentIndexMapping.size(); + i < ie; ++i) { + unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[i]; + ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttributes(i); + } + + // Copy annotations on varargs arguments. + for (unsigned i = TransformedFunction.OriginalType->getNumParams(), + ie = CallSiteAttrs.getNumAttrSets(); i<ie; ++i) { + ArgumentAttributes.push_back(CallSiteAttrs.getParamAttributes(i)); + } + + return AttributeList::get( + Ctx, + CallSiteAttrs.getFnAttributes(), + CallSiteAttrs.getRetAttributes(), + llvm::makeArrayRef(ArgumentAttributes)); +} + class DataFlowSanitizer : public ModulePass { friend struct DFSanFunction; friend class DFSanVisitor; @@ -294,7 +360,7 @@ class DataFlowSanitizer : public ModulePass { bool isInstrumented(const GlobalAlias *GA); FunctionType *getArgsFunctionType(FunctionType *T); FunctionType *getTrampolineFunctionType(FunctionType *T); - FunctionType *getCustomFunctionType(FunctionType *T); + TransformedFunction getCustomFunctionType(FunctionType *T); InstrumentedABI getInstrumentedABI(); WrapperKind getWrapperKind(Function *F); void addGlobalNamePrefix(GlobalValue *GV); @@ -437,17 +503,25 @@ FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) { return FunctionType::get(T->getReturnType(), ArgTypes, false); } -FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { +TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { SmallVector<Type *, 4> ArgTypes; - for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end(); - i != e; ++i) { + + // Some parameters of the custom function being constructed are + // parameters of T. Record the mapping from parameters of T to + // parameters of the custom function, so that parameter attributes + // at call sites can be updated. + std::vector<unsigned> ArgumentIndexMapping; + for (unsigned i = 0, ie = T->getNumParams(); i != ie; ++i) { + Type* param_type = T->getParamType(i); FunctionType *FT; - if (isa<PointerType>(*i) && (FT = dyn_cast<FunctionType>(cast<PointerType>( - *i)->getElementType()))) { + if (isa<PointerType>(param_type) && (FT = dyn_cast<FunctionType>( + cast<PointerType>(param_type)->getElementType()))) { + ArgumentIndexMapping.push_back(ArgTypes.size()); ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo()); ArgTypes.push_back(Type::getInt8PtrTy(*Ctx)); } else { - ArgTypes.push_back(*i); + ArgumentIndexMapping.push_back(ArgTypes.size()); + ArgTypes.push_back(param_type); } } for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) @@ -457,14 +531,15 @@ FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { Type *RetType = T->getReturnType(); if (!RetType->isVoidTy()) ArgTypes.push_back(ShadowPtrTy); - return FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()); + return TransformedFunction( + T, FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()), + ArgumentIndexMapping); } bool DataFlowSanitizer::doInitialization(Module &M) { Triple TargetTriple(M.getTargetTriple()); bool IsX86_64 = TargetTriple.getArch() == Triple::x86_64; - bool IsMIPS64 = TargetTriple.getArch() == Triple::mips64 || - TargetTriple.getArch() == Triple::mips64el; + bool IsMIPS64 = TargetTriple.isMIPS64(); bool IsAArch64 = TargetTriple.getArch() == Triple::aarch64 || TargetTriple.getArch() == Triple::aarch64_be; @@ -783,9 +858,17 @@ bool DataFlowSanitizer::runOnModule(Module &M) { FunctionType *NewFT = getInstrumentedABI() == IA_Args ? getArgsFunctionType(FT) : FT; + + // If the function being wrapped has local linkage, then preserve the + // function's linkage in the wrapper function. + GlobalValue::LinkageTypes wrapperLinkage = + F.hasLocalLinkage() + ? F.getLinkage() + : GlobalValue::LinkOnceODRLinkage; + Function *NewF = buildWrapperFunction( &F, std::string("dfsw$") + std::string(F.getName()), - GlobalValue::LinkOnceODRLinkage, NewFT); + wrapperLinkage, NewFT); if (getInstrumentedABI() == IA_TLS) NewF->removeAttributes(AttributeList::FunctionIndex, ReadOnlyNoneAttrs); @@ -1382,20 +1465,19 @@ void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) { Value *LenShadow = IRB.CreateMul( I.getLength(), ConstantInt::get(I.getLength()->getType(), DFSF.DFS.ShadowWidth / 8)); - Value *AlignShadow; - if (ClPreserveAlignment) { - AlignShadow = IRB.CreateMul(I.getAlignmentCst(), - ConstantInt::get(I.getAlignmentCst()->getType(), - DFSF.DFS.ShadowWidth / 8)); - } else { - AlignShadow = ConstantInt::get(I.getAlignmentCst()->getType(), - DFSF.DFS.ShadowWidth / 8); - } Type *Int8Ptr = Type::getInt8PtrTy(*DFSF.DFS.Ctx); DestShadow = IRB.CreateBitCast(DestShadow, Int8Ptr); SrcShadow = IRB.CreateBitCast(SrcShadow, Int8Ptr); - IRB.CreateCall(I.getCalledValue(), {DestShadow, SrcShadow, LenShadow, - AlignShadow, I.getVolatileCst()}); + auto *MTI = cast<MemTransferInst>( + IRB.CreateCall(I.getCalledValue(), + {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()})); + if (ClPreserveAlignment) { + MTI->setDestAlignment(I.getDestAlignment() * (DFSF.DFS.ShadowWidth / 8)); + MTI->setSourceAlignment(I.getSourceAlignment() * (DFSF.DFS.ShadowWidth / 8)); + } else { + MTI->setDestAlignment(DFSF.DFS.ShadowWidth / 8); + MTI->setSourceAlignment(DFSF.DFS.ShadowWidth / 8); + } } void DFSanVisitor::visitReturnInst(ReturnInst &RI) { @@ -1460,11 +1542,11 @@ void DFSanVisitor::visitCallSite(CallSite CS) { // wrapper. if (CallInst *CI = dyn_cast<CallInst>(CS.getInstruction())) { FunctionType *FT = F->getFunctionType(); - FunctionType *CustomFT = DFSF.DFS.getCustomFunctionType(FT); + TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT); std::string CustomFName = "__dfsw_"; CustomFName += F->getName(); - Constant *CustomF = - DFSF.DFS.Mod->getOrInsertFunction(CustomFName, CustomFT); + Constant *CustomF = DFSF.DFS.Mod->getOrInsertFunction( + CustomFName, CustomFn.TransformedType); if (Function *CustomFn = dyn_cast<Function>(CustomF)) { CustomFn->copyAttributesFrom(F); @@ -1532,7 +1614,8 @@ void DFSanVisitor::visitCallSite(CallSite CS) { CallInst *CustomCI = IRB.CreateCall(CustomF, Args); CustomCI->setCallingConv(CI->getCallingConv()); - CustomCI->setAttributes(CI->getAttributes()); + CustomCI->setAttributes(TransformFunctionAttributes(CustomFn, + CI->getContext(), CI->getAttributes())); // Update the parameter attributes of the custom call instruction to // zero extend the shadow parameters. This is required for targets |