Index: lib/Transforms/Instrumentation/DataFlowSanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -262,7 +262,7 @@ bool isInstrumented(const GlobalAlias *GA); FunctionType *getArgsFunctionType(FunctionType *T); FunctionType *getTrampolineFunctionType(FunctionType *T); - FunctionType *getCustomFunctionType(FunctionType *T); + Constant *getCustomFunction(Function *F); InstrumentedABI getInstrumentedABI(); WrapperKind getWrapperKind(Function *F); void addGlobalNamePrefix(GlobalValue *GV); @@ -404,8 +404,10 @@ return FunctionType::get(T->getReturnType(), ArgTypes, false); } -FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { +Constant * DataFlowSanitizer::getCustomFunction(Function *F) { + FunctionType * T = F->getFunctionType(); llvm::SmallVector ArgTypes; + for (FunctionType::param_iterator i = T->param_begin(), e = T->param_end(); i != e; ++i) { FunctionType *FT; @@ -417,14 +419,44 @@ ArgTypes.push_back(*i); } } - for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) + + // ShadowTy may not be legal on all targets. Using it as a function + // parameter may lead to anyextends being generated which may cause + // unpredictable effects on some targets where i16 is not a legal + // type, e.g. MIPS. + const unsigned ShadowParamStart = ArgTypes.size() + 1; + AttrBuilder ZExtAttrs = AttrBuilder(); + for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) { ArgTypes.push_back(ShadowTy); + ZExtAttrs.addAttribute(Attribute::ZExt); + } + if (T->isVarArg()) ArgTypes.push_back(ShadowPtrTy); Type *RetType = T->getReturnType(); if (!RetType->isVoidTy()) ArgTypes.push_back(ShadowPtrTy); - return FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()); + + FunctionType * CustomFT = + FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()); + std::string CustomFName = "__dfsw_"; + CustomFName += F->getName(); + + Constant *CustomF = Mod->getOrInsertFunction(CustomFName, CustomFT); + if (Function *CustomFn = dyn_cast(CustomF)) { + CustomFn->copyAttributesFrom(F); + + // Enforce zero extensions on shadow parameters. + CustomFn->addAttributes(ShadowParamStart, ZExtAttrs); + + // Custom functions returning non-void will write to the return label. + if (!T->getReturnType()->isVoidTy()) { + CustomFn->removeAttributes(AttributeList::FunctionIndex, + ReadOnlyNoneAttrs); + } + } + + return CustomF; } bool DataFlowSanitizer::doInitialization(Module &M) { @@ -1431,21 +1463,8 @@ // Instead, invoke the dfsw$ wrapper, which will in turn call the __dfsw_ // wrapper. if (CallInst *CI = dyn_cast(CS.getInstruction())) { - FunctionType *FT = F->getFunctionType(); - FunctionType *CustomFT = DFSF.DFS.getCustomFunctionType(FT); - std::string CustomFName = "__dfsw_"; - CustomFName += F->getName(); - Constant *CustomF = - DFSF.DFS.Mod->getOrInsertFunction(CustomFName, CustomFT); - if (Function *CustomFn = dyn_cast(CustomF)) { - CustomFn->copyAttributesFrom(F); - - // Custom functions returning non-void will write to the return label. - if (!FT->getReturnType()->isVoidTy()) { - CustomFn->removeAttributes(AttributeList::FunctionIndex, - DFSF.DFS.ReadOnlyNoneAttrs); - } - } + FunctionType * FT = F->getFunctionType(); + Constant *CustomF = DFSF.DFS.getCustomFunction(F); std::vector Args; @@ -1501,9 +1520,15 @@ for (i = CS.arg_begin() + FT->getNumParams(); i != CS.arg_end(); ++i) Args.push_back(*i); + // Create a call to the custom function, matching the calling + // convention and call attributes. We use the attributes of the custom + // function rather the existing call instruction, as the addition of shadow + // parameters would not have the necessary ZExt attributes. CallInst *CustomCI = IRB.CreateCall(CustomF, Args); + Function *CustomFn = dyn_cast(CustomF); CustomCI->setCallingConv(CI->getCallingConv()); - CustomCI->setAttributes(CI->getAttributes()); + CustomCI->setAttributes(CustomFn ? CustomFn->getAttributes() + : CI->getAttributes()); if (!FT->getReturnType()->isVoidTy()) { LoadInst *LabelLoad = IRB.CreateLoad(DFSF.LabelReturnAlloca);