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 09bcbb282653c..bb0e4379d1a8f 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  | 
