diff options
Diffstat (limited to 'lib/Transforms/Instrumentation/DataFlowSanitizer.cpp')
-rw-r--r-- | lib/Transforms/Instrumentation/DataFlowSanitizer.cpp | 282 |
1 files changed, 218 insertions, 64 deletions
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp index 799e14b..c5a4860 100644 --- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp +++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp @@ -50,6 +50,8 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstVisitor.h" @@ -62,7 +64,10 @@ #include "llvm/Support/SpecialCaseList.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" +#include <algorithm> #include <iterator> +#include <set> +#include <utility> using namespace llvm; @@ -135,11 +140,11 @@ class DFSanABIList { std::unique_ptr<SpecialCaseList> SCL; public: - DFSanABIList(SpecialCaseList *SCL) : SCL(SCL) {} + DFSanABIList(std::unique_ptr<SpecialCaseList> SCL) : SCL(std::move(SCL)) {} /// Returns whether either this function or its source file are listed in the /// given category. - bool isIn(const Function &F, const StringRef Category) const { + bool isIn(const Function &F, StringRef Category) const { return isIn(*F.getParent(), Category) || SCL->inSection("fun", F.getName(), Category); } @@ -148,7 +153,7 @@ class DFSanABIList { /// /// If GA aliases a function, the alias's name is matched as a function name /// would be. Similarly, aliases of globals are matched like globals. - bool isIn(const GlobalAlias &GA, const StringRef Category) const { + bool isIn(const GlobalAlias &GA, StringRef Category) const { if (isIn(*GA.getParent(), Category)) return true; @@ -160,7 +165,7 @@ class DFSanABIList { } /// Returns whether this module is listed in the given category. - bool isIn(const Module &M, const StringRef Category) const { + bool isIn(const Module &M, StringRef Category) const { return SCL->inSection("src", M.getModuleIdentifier(), Category); } }; @@ -229,18 +234,21 @@ class DataFlowSanitizer : public ModulePass { FunctionType *DFSanUnimplementedFnTy; FunctionType *DFSanSetLabelFnTy; FunctionType *DFSanNonzeroLabelFnTy; + FunctionType *DFSanVarargWrapperFnTy; Constant *DFSanUnionFn; + Constant *DFSanCheckedUnionFn; Constant *DFSanUnionLoadFn; Constant *DFSanUnimplementedFn; Constant *DFSanSetLabelFn; Constant *DFSanNonzeroLabelFn; + Constant *DFSanVarargWrapperFn; MDNode *ColdCallWeights; DFSanABIList ABIList; DenseMap<Value *, Function *> UnwrappedFnMap; AttributeSet ReadOnlyNoneAttrs; + DenseMap<const Function *, DISubprogram> FunctionDIs; Value *getShadowAddress(Value *Addr, Instruction *Pos); - Value *combineShadows(Value *V1, Value *V2, Instruction *Pos); bool isInstrumented(const Function *F); bool isInstrumented(const GlobalAlias *GA); FunctionType *getArgsFunctionType(FunctionType *T); @@ -266,6 +274,7 @@ class DataFlowSanitizer : public ModulePass { struct DFSanFunction { DataFlowSanitizer &DFS; Function *F; + DominatorTree DT; DataFlowSanitizer::InstrumentedABI IA; bool IsNativeABI; Value *ArgTLSPtr; @@ -275,17 +284,32 @@ struct DFSanFunction { DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap; std::vector<std::pair<PHINode *, PHINode *> > PHIFixups; DenseSet<Instruction *> SkipInsts; - DenseSet<Value *> NonZeroChecks; + std::vector<Value *> NonZeroChecks; + bool AvoidNewBlocks; + + struct CachedCombinedShadow { + BasicBlock *Block; + Value *Shadow; + }; + DenseMap<std::pair<Value *, Value *>, CachedCombinedShadow> + CachedCombinedShadows; + DenseMap<Value *, std::set<Value *>> ShadowElements; DFSanFunction(DataFlowSanitizer &DFS, Function *F, bool IsNativeABI) : DFS(DFS), F(F), IA(DFS.getInstrumentedABI()), IsNativeABI(IsNativeABI), ArgTLSPtr(nullptr), RetvalTLSPtr(nullptr), - LabelReturnAlloca(nullptr) {} + LabelReturnAlloca(nullptr) { + DT.recalculate(*F); + // FIXME: Need to track down the register allocator issue which causes poor + // performance in pathological cases with large numbers of basic blocks. + AvoidNewBlocks = F->size() > 1000; + } Value *getArgTLSPtr(); Value *getArgTLS(unsigned Index, Instruction *Pos); Value *getRetvalTLS(); Value *getShadow(Value *V); void setShadow(Instruction *I, Value *Shadow); + Value *combineShadows(Value *V1, Value *V2, Instruction *Pos); Value *combineOperandShadows(Instruction *Inst); Value *loadShadow(Value *ShadowAddr, uint64_t Size, uint64_t Align, Instruction *Pos); @@ -367,7 +391,6 @@ FunctionType *DataFlowSanitizer::getTrampolineFunctionType(FunctionType *T) { } 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) { @@ -382,10 +405,12 @@ FunctionType *DataFlowSanitizer::getCustomFunctionType(FunctionType *T) { } for (unsigned i = 0, e = T->getNumParams(); i != e; ++i) ArgTypes.push_back(ShadowTy); + if (T->isVarArg()) + ArgTypes.push_back(ShadowPtrTy); Type *RetType = T->getReturnType(); if (!RetType->isVoidTy()) ArgTypes.push_back(ShadowPtrTy); - return FunctionType::get(T->getReturnType(), ArgTypes, false); + return FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()); } bool DataFlowSanitizer::doInitialization(Module &M) { @@ -415,7 +440,9 @@ bool DataFlowSanitizer::doInitialization(Module &M) { DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx), DFSanSetLabelArgs, /*isVarArg=*/false); DFSanNonzeroLabelFnTy = FunctionType::get( - Type::getVoidTy(*Ctx), ArrayRef<Type *>(), /*isVarArg=*/false); + Type::getVoidTy(*Ctx), None, /*isVarArg=*/false); + DFSanVarargWrapperFnTy = FunctionType::get( + Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx), /*isVarArg=*/false); if (GetArgTLSPtr) { Type *ArgTLSTy = ArrayType::get(ShadowTy, 64); @@ -495,15 +522,26 @@ DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName, AttributeSet::ReturnIndex)); BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", NewF); - std::vector<Value *> Args; - unsigned n = FT->getNumParams(); - for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n) - Args.push_back(&*ai); - CallInst *CI = CallInst::Create(F, Args, "", BB); - if (FT->getReturnType()->isVoidTy()) - ReturnInst::Create(*Ctx, BB); - else - ReturnInst::Create(*Ctx, CI, BB); + if (F->isVarArg()) { + NewF->removeAttributes( + AttributeSet::FunctionIndex, + AttributeSet().addAttribute(*Ctx, AttributeSet::FunctionIndex, + "split-stack")); + CallInst::Create(DFSanVarargWrapperFn, + IRBuilder<>(BB).CreateGlobalStringPtr(F->getName()), "", + BB); + new UnreachableInst(*Ctx, BB); + } else { + std::vector<Value *> Args; + unsigned n = FT->getNumParams(); + for (Function::arg_iterator ai = NewF->arg_begin(); n != 0; ++ai, --n) + Args.push_back(&*ai); + CallInst *CI = CallInst::Create(F, Args, "", BB); + if (FT->getReturnType()->isVoidTy()) + ReturnInst::Create(*Ctx, BB); + else + ReturnInst::Create(*Ctx, CI, BB); + } return NewF; } @@ -548,6 +586,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) { if (ABIList.isIn(M, "skip")) return false; + FunctionDIs = makeSubprogramMap(M); + if (!GetArgTLSPtr) { Type *ArgTLSTy = ArrayType::get(ShadowTy, 64); ArgTLS = Mod->getOrInsertGlobal("__dfsan_arg_tls", ArgTLSTy); @@ -562,6 +602,15 @@ bool DataFlowSanitizer::runOnModule(Module &M) { DFSanUnionFn = Mod->getOrInsertFunction("__dfsan_union", DFSanUnionFnTy); if (Function *F = dyn_cast<Function>(DFSanUnionFn)) { + F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); + F->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); + F->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); + F->addAttribute(1, Attribute::ZExt); + F->addAttribute(2, Attribute::ZExt); + } + DFSanCheckedUnionFn = Mod->getOrInsertFunction("dfsan_union", DFSanUnionFnTy); + if (Function *F = dyn_cast<Function>(DFSanCheckedUnionFn)) { + F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); F->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone); F->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); F->addAttribute(1, Attribute::ZExt); @@ -570,6 +619,7 @@ bool DataFlowSanitizer::runOnModule(Module &M) { DFSanUnionLoadFn = Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy); if (Function *F = dyn_cast<Function>(DFSanUnionLoadFn)) { + F->addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind); F->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadOnly); F->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); } @@ -582,16 +632,20 @@ bool DataFlowSanitizer::runOnModule(Module &M) { } DFSanNonzeroLabelFn = Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy); + DFSanVarargWrapperFn = Mod->getOrInsertFunction("__dfsan_vararg_wrapper", + DFSanVarargWrapperFnTy); std::vector<Function *> FnsToInstrument; llvm::SmallPtrSet<Function *, 2> FnsWithNativeABI; for (Module::iterator i = M.begin(), e = M.end(); i != e; ++i) { if (!i->isIntrinsic() && i != DFSanUnionFn && + i != DFSanCheckedUnionFn && i != DFSanUnionLoadFn && i != DFSanUnimplementedFn && i != DFSanSetLabelFn && - i != DFSanNonzeroLabelFn) + i != DFSanNonzeroLabelFn && + i != DFSanVarargWrapperFn) FnsToInstrument.push_back(&*i); } @@ -673,11 +727,6 @@ bool DataFlowSanitizer::runOnModule(Module &M) { } else { addGlobalNamePrefix(&F); } - // Hopefully, nobody will try to indirectly call a vararg - // function... yet. - } else if (FT->isVarArg()) { - UnwrappedFnMap[&F] = &F; - *i = nullptr; } else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) { // Build a wrapper function for F. The wrapper simply calls F, and is // added to FnsToInstrument so that any instrumentation according to its @@ -694,6 +743,12 @@ bool DataFlowSanitizer::runOnModule(Module &M) { Value *WrappedFnCst = ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT)); F.replaceAllUsesWith(WrappedFnCst); + + // Patch the pointer to LLVM function in debug info descriptor. + auto DI = FunctionDIs.find(&F); + if (DI != FunctionDIs.end()) + DI->second.replaceFunction(&F); + UnwrappedFnMap[WrappedFnCst] = &F; *i = NewF; @@ -713,6 +768,11 @@ bool DataFlowSanitizer::runOnModule(Module &M) { i = FnsToInstrument.begin() + N; e = FnsToInstrument.begin() + Count; } + // Hopefully, nobody will try to indirectly call a vararg + // function... yet. + } else if (FT->isVarArg()) { + UnwrappedFnMap[&F] = &F; + *i = nullptr; } } @@ -771,18 +831,16 @@ bool DataFlowSanitizer::runOnModule(Module &M) { // yet). To make our life easier, do this work in a pass after the main // instrumentation. if (ClDebugNonzeroLabels) { - for (DenseSet<Value *>::iterator i = DFSF.NonZeroChecks.begin(), - e = DFSF.NonZeroChecks.end(); - i != e; ++i) { + for (Value *V : DFSF.NonZeroChecks) { Instruction *Pos; - if (Instruction *I = dyn_cast<Instruction>(*i)) + if (Instruction *I = dyn_cast<Instruction>(V)) Pos = I->getNextNode(); else Pos = DFSF.F->getEntryBlock().begin(); while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos)) Pos = Pos->getNextNode(); IRBuilder<> IRB(Pos); - Value *Ne = IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow); + Value *Ne = IRB.CreateICmpNE(V, DFSF.DFS.ZeroShadow); BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( Ne, Pos, /*Unreachable=*/false, ColdCallWeights)); IRBuilder<> ThenIRB(BI); @@ -847,7 +905,7 @@ Value *DFSanFunction::getShadow(Value *V) { break; } } - NonZeroChecks.insert(Shadow); + NonZeroChecks.push_back(Shadow); } else { Shadow = DFS.ZeroShadow; } @@ -873,30 +931,82 @@ Value *DataFlowSanitizer::getShadowAddress(Value *Addr, Instruction *Pos) { // Generates IR to compute the union of the two given shadows, inserting it // before Pos. Returns the computed union Value. -Value *DataFlowSanitizer::combineShadows(Value *V1, Value *V2, - Instruction *Pos) { - if (V1 == ZeroShadow) +Value *DFSanFunction::combineShadows(Value *V1, Value *V2, Instruction *Pos) { + if (V1 == DFS.ZeroShadow) return V2; - if (V2 == ZeroShadow) + if (V2 == DFS.ZeroShadow) return V1; if (V1 == V2) return V1; + + auto V1Elems = ShadowElements.find(V1); + auto V2Elems = ShadowElements.find(V2); + if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) { + if (std::includes(V1Elems->second.begin(), V1Elems->second.end(), + V2Elems->second.begin(), V2Elems->second.end())) { + return V1; + } else if (std::includes(V2Elems->second.begin(), V2Elems->second.end(), + V1Elems->second.begin(), V1Elems->second.end())) { + return V2; + } + } else if (V1Elems != ShadowElements.end()) { + if (V1Elems->second.count(V2)) + return V1; + } else if (V2Elems != ShadowElements.end()) { + if (V2Elems->second.count(V1)) + return V2; + } + + auto Key = std::make_pair(V1, V2); + if (V1 > V2) + std::swap(Key.first, Key.second); + CachedCombinedShadow &CCS = CachedCombinedShadows[Key]; + if (CCS.Block && DT.dominates(CCS.Block, Pos->getParent())) + return CCS.Shadow; + IRBuilder<> IRB(Pos); - BasicBlock *Head = Pos->getParent(); - Value *Ne = IRB.CreateICmpNE(V1, V2); - BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( - Ne, Pos, /*Unreachable=*/false, ColdCallWeights)); - IRBuilder<> ThenIRB(BI); - CallInst *Call = ThenIRB.CreateCall2(DFSanUnionFn, V1, V2); - Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); - Call->addAttribute(1, Attribute::ZExt); - Call->addAttribute(2, Attribute::ZExt); - - BasicBlock *Tail = BI->getSuccessor(0); - PHINode *Phi = PHINode::Create(ShadowTy, 2, "", Tail->begin()); - Phi->addIncoming(Call, Call->getParent()); - Phi->addIncoming(V1, Head); - return Phi; + if (AvoidNewBlocks) { + CallInst *Call = IRB.CreateCall2(DFS.DFSanCheckedUnionFn, V1, V2); + Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); + Call->addAttribute(1, Attribute::ZExt); + Call->addAttribute(2, Attribute::ZExt); + + CCS.Block = Pos->getParent(); + CCS.Shadow = Call; + } else { + BasicBlock *Head = Pos->getParent(); + Value *Ne = IRB.CreateICmpNE(V1, V2); + BranchInst *BI = cast<BranchInst>(SplitBlockAndInsertIfThen( + Ne, Pos, /*Unreachable=*/false, DFS.ColdCallWeights, &DT)); + IRBuilder<> ThenIRB(BI); + CallInst *Call = ThenIRB.CreateCall2(DFS.DFSanUnionFn, V1, V2); + Call->addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt); + Call->addAttribute(1, Attribute::ZExt); + Call->addAttribute(2, Attribute::ZExt); + + BasicBlock *Tail = BI->getSuccessor(0); + PHINode *Phi = PHINode::Create(DFS.ShadowTy, 2, "", Tail->begin()); + Phi->addIncoming(Call, Call->getParent()); + Phi->addIncoming(V1, Head); + + CCS.Block = Tail; + CCS.Shadow = Phi; + } + + std::set<Value *> UnionElems; + if (V1Elems != ShadowElements.end()) { + UnionElems = V1Elems->second; + } else { + UnionElems.insert(V1); + } + if (V2Elems != ShadowElements.end()) { + UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end()); + } else { + UnionElems.insert(V2); + } + ShadowElements[CCS.Shadow] = std::move(UnionElems); + + return CCS.Shadow; } // A convenience function which folds the shadows of each of the operands @@ -908,7 +1018,7 @@ Value *DFSanFunction::combineOperandShadows(Instruction *Inst) { Value *Shadow = getShadow(Inst->getOperand(0)); for (unsigned i = 1, n = Inst->getNumOperands(); i != n; ++i) { - Shadow = DFS.combineShadows(Shadow, getShadow(Inst->getOperand(i)), Inst); + Shadow = combineShadows(Shadow, getShadow(Inst->getOperand(i)), Inst); } return Shadow; } @@ -961,12 +1071,11 @@ Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align, IRBuilder<> IRB(Pos); Value *ShadowAddr1 = IRB.CreateGEP(ShadowAddr, ConstantInt::get(DFS.IntptrTy, 1)); - return DFS.combineShadows(IRB.CreateAlignedLoad(ShadowAddr, ShadowAlign), - IRB.CreateAlignedLoad(ShadowAddr1, ShadowAlign), - Pos); + return combineShadows(IRB.CreateAlignedLoad(ShadowAddr, ShadowAlign), + IRB.CreateAlignedLoad(ShadowAddr1, ShadowAlign), Pos); } } - if (Size % (64 / DFS.ShadowWidth) == 0) { + if (!AvoidNewBlocks && Size % (64 / DFS.ShadowWidth) == 0) { // Fast path for the common case where each byte has identical shadow: load // shadow 64 bits at a time, fall out to a __dfsan_union_load call if any // shadow is non-equal. @@ -990,16 +1099,27 @@ Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align, BasicBlock *Head = Pos->getParent(); BasicBlock *Tail = Head->splitBasicBlock(Pos); + + if (DomTreeNode *OldNode = DT.getNode(Head)) { + std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end()); + + DomTreeNode *NewNode = DT.addNewBlock(Tail, Head); + for (auto Child : Children) + DT.changeImmediateDominator(Child, NewNode); + } + // In the following code LastBr will refer to the previous basic block's // conditional branch instruction, whose true successor is fixed up to point // to the next block during the loop below or to the tail after the final // iteration. BranchInst *LastBr = BranchInst::Create(FallbackBB, FallbackBB, ShadowsEq); ReplaceInstWithInst(Head->getTerminator(), LastBr); + DT.addNewBlock(FallbackBB, Head); for (uint64_t Ofs = 64 / DFS.ShadowWidth; Ofs != Size; Ofs += 64 / DFS.ShadowWidth) { BasicBlock *NextBB = BasicBlock::Create(*DFS.Ctx, "", F); + DT.addNewBlock(NextBB, LastBr->getParent()); IRBuilder<> NextIRB(NextBB); WideAddr = NextIRB.CreateGEP(WideAddr, ConstantInt::get(DFS.IntptrTy, 1)); Value *NextWideShadow = NextIRB.CreateAlignedLoad(WideAddr, ShadowAlign); @@ -1025,6 +1145,11 @@ Value *DFSanFunction::loadShadow(Value *Addr, uint64_t Size, uint64_t Align, void DFSanVisitor::visitLoadInst(LoadInst &LI) { uint64_t Size = DFSF.DFS.DL->getTypeStoreSize(LI.getType()); + if (Size == 0) { + DFSF.setShadow(&LI, DFSF.DFS.ZeroShadow); + return; + } + uint64_t Align; if (ClPreserveAlignment) { Align = LI.getAlignment(); @@ -1037,10 +1162,10 @@ void DFSanVisitor::visitLoadInst(LoadInst &LI) { Value *Shadow = DFSF.loadShadow(LI.getPointerOperand(), Size, Align, &LI); if (ClCombinePointerLabelsOnLoad) { Value *PtrShadow = DFSF.getShadow(LI.getPointerOperand()); - Shadow = DFSF.DFS.combineShadows(Shadow, PtrShadow, &LI); + Shadow = DFSF.combineShadows(Shadow, PtrShadow, &LI); } if (Shadow != DFSF.DFS.ZeroShadow) - DFSF.NonZeroChecks.insert(Shadow); + DFSF.NonZeroChecks.push_back(Shadow); DFSF.setShadow(&LI, Shadow); } @@ -1099,6 +1224,9 @@ void DFSanFunction::storeShadow(Value *Addr, uint64_t Size, uint64_t Align, void DFSanVisitor::visitStoreInst(StoreInst &SI) { uint64_t Size = DFSF.DFS.DL->getTypeStoreSize(SI.getValueOperand()->getType()); + if (Size == 0) + return; + uint64_t Align; if (ClPreserveAlignment) { Align = SI.getAlignment(); @@ -1111,7 +1239,7 @@ void DFSanVisitor::visitStoreInst(StoreInst &SI) { Value* Shadow = DFSF.getShadow(SI.getValueOperand()); if (ClCombinePointerLabelsOnStore) { Value *PtrShadow = DFSF.getShadow(SI.getPointerOperand()); - Shadow = DFSF.DFS.combineShadows(Shadow, PtrShadow, &SI); + Shadow = DFSF.combineShadows(Shadow, PtrShadow, &SI); } DFSF.storeShadow(SI.getPointerOperand(), Size, Align, Shadow, &SI); } @@ -1176,9 +1304,9 @@ void DFSanVisitor::visitSelectInst(SelectInst &I) { if (isa<VectorType>(I.getCondition()->getType())) { DFSF.setShadow( - &I, DFSF.DFS.combineShadows( - CondShadow, - DFSF.DFS.combineShadows(TrueShadow, FalseShadow, &I), &I)); + &I, + DFSF.combineShadows( + CondShadow, DFSF.combineShadows(TrueShadow, FalseShadow, &I), &I)); } else { Value *ShadowSel; if (TrueShadow == FalseShadow) { @@ -1187,7 +1315,7 @@ void DFSanVisitor::visitSelectInst(SelectInst &I) { ShadowSel = SelectInst::Create(I.getCondition(), TrueShadow, FalseShadow, "", &I); } - DFSF.setShadow(&I, DFSF.DFS.combineShadows(CondShadow, ShadowSel, &I)); + DFSF.setShadow(&I, DFSF.combineShadows(CondShadow, ShadowSel, &I)); } } @@ -1253,6 +1381,15 @@ void DFSanVisitor::visitCallSite(CallSite CS) { return; } + // Calls to this function are synthesized in wrappers, and we shouldn't + // instrument them. + if (F == DFSF.DFS.DFSanVarargWrapperFn) + return; + + assert(!(cast<FunctionType>( + CS.getCalledValue()->getType()->getPointerElementType())->isVarArg() && + dyn_cast<InvokeInst>(CS.getInstruction()))); + IRBuilder<> IRB(CS.getInstruction()); DenseMap<Value *, Function *>::iterator i = @@ -1324,6 +1461,20 @@ void DFSanVisitor::visitCallSite(CallSite CS) { for (unsigned n = FT->getNumParams(); n != 0; ++i, --n) Args.push_back(DFSF.getShadow(*i)); + if (FT->isVarArg()) { + auto LabelVAAlloca = + new AllocaInst(ArrayType::get(DFSF.DFS.ShadowTy, + CS.arg_size() - FT->getNumParams()), + "labelva", DFSF.F->getEntryBlock().begin()); + + for (unsigned n = 0; i != CS.arg_end(); ++i, ++n) { + auto LabelVAPtr = IRB.CreateStructGEP(LabelVAAlloca, n); + IRB.CreateStore(DFSF.getShadow(*i), LabelVAPtr); + } + + Args.push_back(IRB.CreateStructGEP(LabelVAAlloca, 0)); + } + if (!FT->getReturnType()->isVoidTy()) { if (!DFSF.LabelReturnAlloca) { DFSF.LabelReturnAlloca = @@ -1333,6 +1484,9 @@ void DFSanVisitor::visitCallSite(CallSite CS) { Args.push_back(DFSF.LabelReturnAlloca); } + for (i = CS.arg_begin() + FT->getNumParams(); i != CS.arg_end(); ++i) + Args.push_back(*i); + CallInst *CustomCI = IRB.CreateCall(CustomF, Args); CustomCI->setCallingConv(CI->getCallingConv()); CustomCI->setAttributes(CI->getAttributes()); @@ -1379,7 +1533,7 @@ void DFSanVisitor::visitCallSite(CallSite CS) { LoadInst *LI = NextIRB.CreateLoad(DFSF.getRetvalTLS()); DFSF.SkipInsts.insert(LI); DFSF.setShadow(CS.getInstruction(), LI); - DFSF.NonZeroChecks.insert(LI); + DFSF.NonZeroChecks.push_back(LI); } } @@ -1433,7 +1587,7 @@ void DFSanVisitor::visitCallSite(CallSite CS) { ExtractValueInst::Create(NewCS.getInstruction(), 1, "", Next); DFSF.SkipInsts.insert(ExShadow); DFSF.setShadow(ExVal, ExShadow); - DFSF.NonZeroChecks.insert(ExShadow); + DFSF.NonZeroChecks.push_back(ExShadow); CS.getInstruction()->replaceAllUsesWith(ExVal); } |