87 "dfsan-preserve-alignment",
100 cl::desc(
"File listing native ABI functions and how the pass treats them"),
107 cl::desc(
"Use the argument ABI rather than the TLS ABI"),
113 "dfsan-combine-pointer-labels-on-load",
114 cl::desc(
"Combine the label of the pointer with the label of the data when "
115 "loading from memory."),
121 "dfsan-combine-pointer-labels-on-store",
122 cl::desc(
"Combine the label of the pointer with the label of the data when "
123 "storing in memory."),
127 "dfsan-debug-nonzero-labels",
128 cl::desc(
"Insert calls to __dfsan_nonzero_label on observing a parameter, "
129 "load or return with a nonzero label"),
139 if (
StructType *SGType = dyn_cast<StructType>(GType)) {
140 if (!SGType->isLiteral())
141 return SGType->getName();
143 return "<unknown type>";
147 std::unique_ptr<SpecialCaseList> SCL;
152 void set(std::unique_ptr<SpecialCaseList>
List) { SCL = std::move(List); }
173 SCL->inSection(
"type", GetGlobalTypeString(GA), Category);
183 friend struct DFSanFunction;
184 friend class DFSanVisitor;
191 enum InstrumentedABI {
236 void *(*GetArgTLSPtr)();
237 void *(*GetRetvalTLSPtr)();
255 DFSanABIList ABIList;
258 bool DFSanRuntimeShadowMask;
261 bool isInstrumented(
const Function *F);
266 InstrumentedABI getInstrumentedABI();
267 WrapperKind getWrapperKind(
Function *F);
276 const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
277 void *(*getArgTLS)() =
nullptr,
void *(*getRetValTLS)() =
nullptr);
279 bool doInitialization(
Module &M)
override;
280 bool runOnModule(
Module &M)
override;
283 struct DFSanFunction {
284 DataFlowSanitizer &
DFS;
287 DataFlowSanitizer::InstrumentedABI IA;
294 std::vector<std::pair<PHINode *, PHINode *> > PHIFixups;
296 std::vector<Value *> NonZeroChecks;
299 struct CachedCombinedShadow {
304 CachedCombinedShadows;
307 DFSanFunction(DataFlowSanitizer &
DFS,
Function *F,
bool IsNativeABI)
308 : DFS(DFS), F(F), IA(DFS.getInstrumentedABI()),
309 IsNativeABI(IsNativeABI), ArgTLSPtr(nullptr), RetvalTLSPtr(nullptr),
310 LabelReturnAlloca(nullptr) {
314 AvoidNewBlocks = F->
size() > 1000;
316 Value *getArgTLSPtr();
318 Value *getRetvalTLS();
323 Value *loadShadow(
Value *ShadowAddr, uint64_t Size, uint64_t Align,
325 void storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
Value *Shadow,
329 class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
332 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
338 void visitCmpInst(
CmpInst &CI);
344 void visitPHINode(
PHINode &PN);
360 "DataFlowSanitizer: dynamic data flow analysis.",
false,
false)
364 void *(*getArgTLS)(),
365 void *(*getRetValTLS)()) {
366 return new DataFlowSanitizer(ABIListFiles, getArgTLS, getRetValTLS);
369 DataFlowSanitizer::DataFlowSanitizer(
370 const std::vector<std::string> &ABIListFiles,
void *(*getArgTLS)(),
371 void *(*getRetValTLS)())
372 :
ModulePass(
ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS),
373 DFSanRuntimeShadowMask(
false) {
374 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
375 AllABIListFiles.insert(AllABIListFiles.end(),
ClABIListFiles.begin(),
377 ABIList.set(SpecialCaseList::createOrDie(AllABIListFiles));
384 ArgTypes.push_back(ShadowPtrTy);
387 RetType = StructType::get(RetType, ShadowTy, (
Type *)
nullptr);
388 return FunctionType::get(RetType, ArgTypes, T->
isVarArg());
399 ArgTypes.push_back(ShadowPtrTy);
400 return FunctionType::get(T->
getReturnType(), ArgTypes,
false);
409 *
i)->getElementType()))) {
410 ArgTypes.
push_back(getTrampolineFunctionType(FT)->getPointerTo());
411 ArgTypes.
push_back(Type::getInt8PtrTy(*Ctx));
426 bool DataFlowSanitizer::doInitialization(
Module &M) {
438 ShadowTy = IntegerType::get(*Ctx, ShadowWidth);
439 ShadowPtrTy = PointerType::getUnqual(ShadowTy);
441 ZeroShadow = ConstantInt::getSigned(ShadowTy, 0);
442 ShadowPtrMul = ConstantInt::getSigned(IntptrTy, ShadowWidth / 8);
444 ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x700000000000LL);
446 ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0xF000000000LL);
449 DFSanRuntimeShadowMask =
true;
453 Type *DFSanUnionArgs[2] = { ShadowTy, ShadowTy };
455 FunctionType::get(ShadowTy, DFSanUnionArgs,
false);
456 Type *DFSanUnionLoadArgs[2] = { ShadowPtrTy, IntptrTy };
458 FunctionType::get(ShadowTy, DFSanUnionLoadArgs,
false);
459 DFSanUnimplementedFnTy = FunctionType::get(
460 Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx),
false);
461 Type *DFSanSetLabelArgs[3] = { ShadowTy, Type::getInt8PtrTy(*Ctx), IntptrTy };
462 DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
463 DFSanSetLabelArgs,
false);
464 DFSanNonzeroLabelFnTy = FunctionType::get(
465 Type::getVoidTy(*Ctx),
None,
false);
466 DFSanVarargWrapperFnTy = FunctionType::get(
467 Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx),
false);
470 Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
472 GetArgTLS = ConstantExpr::getIntToPtr(
473 ConstantInt::get(IntptrTy, uintptr_t(GetArgTLSPtr)),
474 PointerType::getUnqual(
475 FunctionType::get(PointerType::getUnqual(ArgTLSTy),
478 if (GetRetvalTLSPtr) {
480 GetRetvalTLS = ConstantExpr::getIntToPtr(
481 ConstantInt::get(IntptrTy, uintptr_t(GetRetvalTLSPtr)),
482 PointerType::getUnqual(
483 FunctionType::get(PointerType::getUnqual(ShadowTy),
491 bool DataFlowSanitizer::isInstrumented(
const Function *F) {
492 return !ABIList.isIn(*F,
"uninstrumented");
495 bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
496 return !ABIList.isIn(*GA,
"uninstrumented");
499 DataFlowSanitizer::InstrumentedABI DataFlowSanitizer::getInstrumentedABI() {
503 DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *F) {
504 if (ABIList.isIn(*F,
"functional"))
505 return WK_Functional;
506 if (ABIList.isIn(*F,
"discard"))
508 if (ABIList.isIn(*F,
"custom"))
514 void DataFlowSanitizer::addGlobalNamePrefix(
GlobalValue *GV) {
524 std::string SearchStr =
".symver " + GVName +
",";
525 size_t Pos = Asm.find(SearchStr);
526 if (Pos != std::string::npos) {
527 Asm.replace(Pos, SearchStr.size(),
538 Function *NewF = Function::Create(NewFT, NewFLink, NewFName,
542 AttributeSet::ReturnIndex,
543 AttributeSet::get(F->
getContext(), AttributeSet::ReturnIndex,
546 BasicBlock *BB = BasicBlock::Create(*Ctx,
"entry", NewF);
549 AttributeSet::FunctionIndex,
550 AttributeSet().addAttribute(*Ctx, AttributeSet::FunctionIndex,
552 CallInst::Create(DFSanVarargWrapperFn,
557 std::vector<Value *>
Args;
560 Args.push_back(&*ai);
561 CallInst *CI = CallInst::Create(F, Args,
"", BB);
563 ReturnInst::Create(*Ctx, BB);
565 ReturnInst::Create(*Ctx, CI, BB);
574 Constant *
C = Mod->getOrInsertFunction(FName, FTT);
577 F->
setLinkage(GlobalValue::LinkOnceODRLinkage);
578 BasicBlock *BB = BasicBlock::Create(*Ctx,
"entry", F);
579 std::vector<Value *>
Args;
582 Args.push_back(&*AI);
587 RI = ReturnInst::Create(*Ctx, BB);
589 RI = ReturnInst::Create(*Ctx, CI, BB);
591 DFSanFunction DFSF(*
this, F,
true);
593 for (
unsigned N = FT->
getNumParams();
N != 0; ++ValAI, ++ShadowAI, --
N)
594 DFSF.ValShadowMap[&*ValAI] = &*ShadowAI;
595 DFSanVisitor(DFSF).visitCallInst(*CI);
597 new StoreInst(DFSF.getShadow(RI->getReturnValue()),
604 bool DataFlowSanitizer::runOnModule(
Module &M) {
605 if (ABIList.isIn(M,
"skip"))
609 Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
610 ArgTLS = Mod->getOrInsertGlobal(
"__dfsan_arg_tls", ArgTLSTy);
614 if (!GetRetvalTLSPtr) {
615 RetvalTLS = Mod->getOrInsertGlobal(
"__dfsan_retval_tls", ShadowTy);
623 DFSanUnionFn = Mod->getOrInsertFunction(
"__dfsan_union", DFSanUnionFnTy);
624 if (
Function *F = dyn_cast<Function>(DFSanUnionFn)) {
625 F->
addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
626 F->
addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
627 F->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
631 DFSanCheckedUnionFn = Mod->getOrInsertFunction(
"dfsan_union", DFSanUnionFnTy);
632 if (
Function *F = dyn_cast<Function>(DFSanCheckedUnionFn)) {
633 F->
addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
634 F->
addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
635 F->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
640 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy);
641 if (
Function *F = dyn_cast<Function>(DFSanUnionLoadFn)) {
642 F->
addAttribute(AttributeSet::FunctionIndex, Attribute::NoUnwind);
644 F->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
646 DFSanUnimplementedFn =
647 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
649 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy);
650 if (
Function *F = dyn_cast<Function>(DFSanSetLabelFn)) {
653 DFSanNonzeroLabelFn =
654 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
655 DFSanVarargWrapperFn = Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
656 DFSanVarargWrapperFnTy);
658 std::vector<Function *> FnsToInstrument;
661 if (!
i.isIntrinsic() &&
662 &
i != DFSanUnionFn &&
663 &
i != DFSanCheckedUnionFn &&
664 &
i != DFSanUnionLoadFn &&
665 &
i != DFSanUnimplementedFn &&
666 &
i != DFSanSetLabelFn &&
667 &
i != DFSanNonzeroLabelFn &&
668 &
i != DFSanVarargWrapperFn)
669 FnsToInstrument.push_back(&
i);
680 bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
681 if (GAInst && FInst) {
682 addGlobalNamePrefix(GA);
683 }
else if (GAInst != FInst) {
692 FnsToInstrument.push_back(NewF);
699 ReadOnlyNoneAttrs = AttributeSet::get(*Ctx, AttributeSet::FunctionIndex, B);
703 for (std::vector<Function *>::iterator
i = FnsToInstrument.begin(),
704 e = FnsToInstrument.end();
712 if (isInstrumented(&F)) {
715 if (getInstrumentedABI() == IA_Args && !IsZeroArgsVoidRet) {
720 AttributeSet::ReturnIndex,
721 AttributeSet::get(NewF->
getContext(), AttributeSet::ReturnIndex,
726 FArg != FArgEnd; ++FArg, ++NewFArg) {
727 FArg->replaceAllUsesWith(&*NewFArg);
742 ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT)));
746 addGlobalNamePrefix(NewF);
748 addGlobalNamePrefix(&F);
750 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
755 ? getArgsFunctionType(FT)
757 Function *NewF = buildWrapperFunction(
758 &F, std::string(
"dfsw$") + std::string(F.
getName()),
759 GlobalValue::LinkOnceODRLinkage, NewFT);
760 if (getInstrumentedABI() == IA_TLS)
763 Value *WrappedFnCst =
764 ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT));
767 UnwrappedFnMap[WrappedFnCst] = &
F;
775 FnsWithNativeABI.
insert(&F);
780 size_t N =
i - FnsToInstrument.begin(),
781 Count = e - FnsToInstrument.begin();
782 FnsToInstrument.push_back(&F);
783 i = FnsToInstrument.begin() +
N;
784 e = FnsToInstrument.begin() + Count;
789 UnwrappedFnMap[&
F] = &
F;
795 if (!
i ||
i->isDeclaration())
800 DFSanFunction DFSF(*
this,
i, FnsWithNativeABI.
count(
i));
815 bool IsTerminator = isa<TerminatorInst>(Inst);
816 if (!DFSF.SkipInsts.count(Inst))
817 DFSanVisitor(DFSF).visit(Inst);
828 for (std::vector<std::pair<PHINode *, PHINode *> >::iterator
829 i = DFSF.PHIFixups.begin(),
830 e = DFSF.PHIFixups.end();
832 for (
unsigned val = 0, n =
i->first->getNumIncomingValues(); val != n;
834 i->second->setIncomingValue(
835 val, DFSF.getShadow(
i->first->getIncomingValue(val)));
844 for (
Value *V : DFSF.NonZeroChecks) {
847 Pos =
I->getNextNode();
849 Pos = &DFSF.F->getEntryBlock().front();
850 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
853 Value *Ne = IRB.CreateICmpNE(V, DFSF.DFS.ZeroShadow);
855 Ne, Pos,
false, ColdCallWeights));
857 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
865 Value *DFSanFunction::getArgTLSPtr() {
869 return ArgTLSPtr =
DFS.ArgTLS;
875 Value *DFSanFunction::getRetvalTLS() {
879 return RetvalTLSPtr =
DFS.RetvalTLS;
887 return IRB.CreateConstGEP2_64(getArgTLSPtr(), 0, Idx);
891 if (!isa<Argument>(V) && !isa<Instruction>(V))
892 return DFS.ZeroShadow;
893 Value *&Shadow = ValShadowMap[V];
895 if (
Argument *
A = dyn_cast<Argument>(V)) {
897 return DFS.ZeroShadow;
899 case DataFlowSanitizer::IA_TLS: {
900 Value *ArgTLSPtr = getArgTLSPtr();
903 : cast<Instruction>(ArgTLSPtr)->getNextNode();
905 Shadow = IRB.CreateLoad(getArgTLS(
A->getArgNo(), ArgTLSPos));
908 case DataFlowSanitizer::IA_Args: {
918 NonZeroChecks.push_back(Shadow);
920 Shadow =
DFS.ZeroShadow;
927 assert(!ValShadowMap.count(I));
929 ValShadowMap[
I] = Shadow;
933 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
935 Value *ShadowPtrMaskValue;
936 if (DFSanRuntimeShadowMask)
937 ShadowPtrMaskValue = IRB.CreateLoad(IntptrTy, ExternalShadowMask);
939 ShadowPtrMaskValue = ShadowPtrMask;
940 return IRB.CreateIntToPtr(
942 IRB.CreateAnd(IRB.CreatePtrToInt(Addr, IntptrTy),
943 IRB.CreatePtrToInt(ShadowPtrMaskValue, IntptrTy)),
951 if (V1 ==
DFS.ZeroShadow)
953 if (V2 ==
DFS.ZeroShadow)
958 auto V1Elems = ShadowElements.find(V1);
959 auto V2Elems = ShadowElements.find(V2);
960 if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) {
961 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
962 V2Elems->second.begin(), V2Elems->second.end())) {
964 }
else if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
965 V1Elems->second.begin(), V1Elems->second.end())) {
968 }
else if (V1Elems != ShadowElements.end()) {
969 if (V1Elems->second.count(V2))
971 }
else if (V2Elems != ShadowElements.end()) {
972 if (V2Elems->second.count(V1))
976 auto Key = std::make_pair(V1, V2);
979 CachedCombinedShadow &CCS = CachedCombinedShadows[Key];
980 if (CCS.Block && DT.dominates(CCS.Block, Pos->
getParent()))
984 if (AvoidNewBlocks) {
986 Call->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
994 Value *Ne = IRB.CreateICmpNE(V1, V2);
996 Ne, Pos,
false,
DFS.ColdCallWeights, &DT));
998 CallInst *Call = ThenIRB.CreateCall(
DFS.DFSanUnionFn, {V1, V2});
999 Call->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
1012 std::set<Value *> UnionElems;
1013 if (V1Elems != ShadowElements.end()) {
1014 UnionElems = V1Elems->second;
1016 UnionElems.insert(V1);
1018 if (V2Elems != ShadowElements.end()) {
1019 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
1021 UnionElems.insert(V2);
1023 ShadowElements[CCS.Shadow] = std::move(UnionElems);
1033 return DFS.ZeroShadow;
1037 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
i)), Inst);
1042 void DFSanVisitor::visitOperandShadowInst(
Instruction &I) {
1043 Value *CombinedShadow = DFSF.combineOperandShadows(&I);
1044 DFSF.setShadow(&I, CombinedShadow);
1049 Value *DFSanFunction::loadShadow(
Value *Addr, uint64_t Size, uint64_t Align,
1051 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
1053 AllocaShadowMap.find(AI);
1054 if (i != AllocaShadowMap.end()) {
1056 return IRB.CreateLoad(i->second);
1060 uint64_t ShadowAlign = Align *
DFS.ShadowWidth / 8;
1063 bool AllConstants =
true;
1064 for (
Value *Obj : Objs) {
1065 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
1067 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->isConstant())
1070 AllConstants =
false;
1074 return DFS.ZeroShadow;
1076 Value *ShadowAddr =
DFS.getShadowAddress(Addr, Pos);
1079 return DFS.ZeroShadow;
1087 Value *ShadowAddr1 = IRB.CreateGEP(
DFS.ShadowTy, ShadowAddr,
1088 ConstantInt::get(
DFS.IntptrTy, 1));
1089 return combineShadows(IRB.CreateAlignedLoad(ShadowAddr, ShadowAlign),
1090 IRB.CreateAlignedLoad(ShadowAddr1, ShadowAlign), Pos);
1093 if (!AvoidNewBlocks && Size % (64 /
DFS.ShadowWidth) == 0) {
1097 BasicBlock *FallbackBB = BasicBlock::Create(*
DFS.Ctx,
"", F);
1099 CallInst *FallbackCall = FallbackIRB.CreateCall(
1100 DFS.DFSanUnionLoadFn,
1101 {ShadowAddr, ConstantInt::get(
DFS.IntptrTy, Size)});
1102 FallbackCall->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
1108 IRB.CreateBitCast(ShadowAddr, Type::getInt64PtrTy(*
DFS.Ctx));
1109 Value *WideShadow = IRB.CreateAlignedLoad(WideAddr, ShadowAlign);
1110 Value *TruncShadow = IRB.CreateTrunc(WideShadow,
DFS.ShadowTy);
1111 Value *ShlShadow = IRB.CreateShl(WideShadow,
DFS.ShadowWidth);
1112 Value *ShrShadow = IRB.CreateLShr(WideShadow, 64 -
DFS.ShadowWidth);
1113 Value *RotShadow = IRB.CreateOr(ShlShadow, ShrShadow);
1114 Value *ShadowsEq = IRB.CreateICmpEQ(WideShadow, RotShadow);
1120 std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end());
1122 DomTreeNode *NewNode = DT.addNewBlock(Tail, Head);
1123 for (
auto Child : Children)
1124 DT.changeImmediateDominator(Child, NewNode);
1131 BranchInst *LastBr = BranchInst::Create(FallbackBB, FallbackBB, ShadowsEq);
1133 DT.addNewBlock(FallbackBB, Head);
1135 for (uint64_t Ofs = 64 /
DFS.ShadowWidth; Ofs != Size;
1136 Ofs += 64 /
DFS.ShadowWidth) {
1138 DT.addNewBlock(NextBB, LastBr->
getParent());
1140 WideAddr = NextIRB.CreateGEP(Type::getInt64Ty(*
DFS.Ctx), WideAddr,
1141 ConstantInt::get(
DFS.IntptrTy, 1));
1142 Value *NextWideShadow = NextIRB.CreateAlignedLoad(WideAddr, ShadowAlign);
1143 ShadowsEq = NextIRB.CreateICmpEQ(WideShadow, NextWideShadow);
1145 LastBr = NextIRB.CreateCondBr(ShadowsEq, FallbackBB, FallbackBB);
1149 FallbackIRB.CreateBr(Tail);
1150 PHINode *Shadow = PHINode::Create(
DFS.ShadowTy, 2,
"", &Tail->
front());
1157 CallInst *FallbackCall = IRB.CreateCall(
1158 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(
DFS.IntptrTy, Size)});
1159 FallbackCall->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
1160 return FallbackCall;
1163 void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
1167 DFSF.setShadow(&LI, DFSF.DFS.ZeroShadow);
1183 Shadow = DFSF.combineShadows(Shadow, PtrShadow, &LI);
1185 if (Shadow != DFSF.DFS.ZeroShadow)
1186 DFSF.NonZeroChecks.push_back(Shadow);
1188 DFSF.setShadow(&LI, Shadow);
1191 void DFSanFunction::storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
1193 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
1195 AllocaShadowMap.find(AI);
1196 if (i != AllocaShadowMap.end()) {
1198 IRB.CreateStore(Shadow, i->second);
1203 uint64_t ShadowAlign = Align *
DFS.ShadowWidth / 8;
1205 Value *ShadowAddr =
DFS.getShadowAddress(Addr, Pos);
1206 if (Shadow ==
DFS.ZeroShadow) {
1208 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
1209 Value *ExtShadowAddr =
1210 IRB.CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowTy));
1211 IRB.CreateAlignedStore(ExtZeroShadow, ExtShadowAddr, ShadowAlign);
1215 const unsigned ShadowVecSize = 128 /
DFS.ShadowWidth;
1217 if (Size >= ShadowVecSize) {
1218 VectorType *ShadowVecTy = VectorType::get(
DFS.ShadowTy, ShadowVecSize);
1219 Value *ShadowVec = UndefValue::get(ShadowVecTy);
1220 for (
unsigned i = 0; i != ShadowVecSize; ++
i) {
1221 ShadowVec = IRB.CreateInsertElement(
1222 ShadowVec, Shadow, ConstantInt::get(Type::getInt32Ty(*
DFS.Ctx), i));
1224 Value *ShadowVecAddr =
1225 IRB.CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowVecTy));
1227 Value *CurShadowVecAddr =
1228 IRB.CreateConstGEP1_32(ShadowVecTy, ShadowVecAddr, Offset);
1229 IRB.CreateAlignedStore(ShadowVec, CurShadowVecAddr, ShadowAlign);
1230 Size -= ShadowVecSize;
1232 }
while (Size >= ShadowVecSize);
1233 Offset *= ShadowVecSize;
1236 Value *CurShadowAddr =
1237 IRB.CreateConstGEP1_32(
DFS.ShadowTy, ShadowAddr, Offset);
1238 IRB.CreateAlignedStore(Shadow, CurShadowAddr, ShadowAlign);
1244 void DFSanVisitor::visitStoreInst(
StoreInst &
SI) {
1262 Shadow = DFSF.combineShadows(Shadow, PtrShadow, &SI);
1268 visitOperandShadowInst(BO);
1271 void DFSanVisitor::visitCastInst(
CastInst &CI) { visitOperandShadowInst(CI); }
1273 void DFSanVisitor::visitCmpInst(
CmpInst &CI) { visitOperandShadowInst(CI); }
1276 visitOperandShadowInst(GEPI);
1280 visitOperandShadowInst(I);
1284 visitOperandShadowInst(I);
1288 visitOperandShadowInst(I);
1292 visitOperandShadowInst(I);
1296 visitOperandShadowInst(I);
1299 void DFSanVisitor::visitAllocaInst(
AllocaInst &I) {
1300 bool AllLoadsStores =
true;
1302 if (isa<LoadInst>(U))
1305 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
1310 AllLoadsStores =
false;
1313 if (AllLoadsStores) {
1315 DFSF.AllocaShadowMap[&
I] = IRB.CreateAlloca(DFSF.DFS.ShadowTy);
1317 DFSF.setShadow(&I, DFSF.DFS.ZeroShadow);
1320 void DFSanVisitor::visitSelectInst(
SelectInst &I) {
1328 DFSF.combineShadows(
1329 CondShadow, DFSF.combineShadows(TrueShadow, FalseShadow, &I), &
I));
1332 if (TrueShadow == FalseShadow) {
1333 ShadowSel = TrueShadow;
1336 SelectInst::Create(I.
getCondition(), TrueShadow, FalseShadow,
"", &
I);
1338 DFSF.setShadow(&I, DFSF.combineShadows(CondShadow, ShadowSel, &I));
1342 void DFSanVisitor::visitMemSetInst(
MemSetInst &I) {
1345 IRB.CreateCall(DFSF.DFS.DFSanSetLabelFn,
1346 {ValShadow, IRB.CreateBitCast(I.
getDest(), Type::getInt8PtrTy(
1348 IRB.CreateZExtOrTrunc(I.
getLength(), DFSF.DFS.IntptrTy)});
1353 Value *DestShadow = DFSF.DFS.getShadowAddress(I.
getDest(), &
I);
1355 Value *LenShadow = IRB.CreateMul(
1362 DFSF.DFS.ShadowWidth / 8));
1365 DFSF.DFS.ShadowWidth / 8);
1367 Type *Int8Ptr = Type::getInt8PtrTy(*DFSF.DFS.Ctx);
1368 DestShadow = IRB.CreateBitCast(DestShadow, Int8Ptr);
1369 SrcShadow = IRB.CreateBitCast(SrcShadow, Int8Ptr);
1370 IRB.CreateCall(I.
getCalledValue(), {DestShadow, SrcShadow, LenShadow,
1374 void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
1377 case DataFlowSanitizer::IA_TLS: {
1380 IRB.CreateStore(S, DFSF.getRetvalTLS());
1383 case DataFlowSanitizer::IA_Args: {
1385 Type *RT = DFSF.F->getFunctionType()->getReturnType();
1387 IRB.CreateInsertValue(UndefValue::get(RT), RI.
getReturnValue(), 0);
1389 IRB.CreateInsertValue(InsVal, DFSF.getShadow(RI.
getReturnValue()), 1);
1397 void DFSanVisitor::visitCallSite(
CallSite CS) {
1406 if (F == DFSF.DFS.DFSanVarargWrapperFn)
1413 if (i != DFSF.DFS.UnwrappedFnMap.end()) {
1415 switch (DFSF.DFS.getWrapperKind(F)) {
1416 case DataFlowSanitizer::WK_Warning: {
1418 IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
1419 IRB.CreateGlobalStringPtr(F->
getName()));
1423 case DataFlowSanitizer::WK_Discard: {
1428 case DataFlowSanitizer::WK_Functional: {
1433 case DataFlowSanitizer::WK_Custom: {
1439 FunctionType *CustomFT = DFSF.DFS.getCustomFunctionType(FT);
1440 std::string CustomFName =
"__dfsw_";
1443 DFSF.DFS.Mod->getOrInsertFunction(CustomFName, CustomFT);
1444 if (
Function *CustomFn = dyn_cast<Function>(CustomF)) {
1445 CustomFn->copyAttributesFrom(F);
1449 CustomFn->removeAttributes(AttributeSet::FunctionIndex,
1450 DFSF.DFS.ReadOnlyNoneAttrs);
1454 std::vector<Value *>
Args;
1456 CallSite::arg_iterator i = CS.
arg_begin();
1458 Type *T = (*i)->getType();
1460 if (isa<PointerType>(T) &&
1461 (ParamFT = dyn_cast<FunctionType>(
1462 cast<PointerType>(T)->getElementType()))) {
1463 std::string TName =
"dfst";
1467 Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
1470 IRB.CreateBitCast(*i, Type::getInt8PtrTy(*DFSF.DFS.Ctx)));
1478 Args.push_back(DFSF.getShadow(*i));
1481 auto *LabelVATy = ArrayType::get(DFSF.DFS.ShadowTy,
1484 LabelVATy,
"labelva", &DFSF.F->getEntryBlock().front());
1486 for (
unsigned n = 0; i != CS.
arg_end(); ++
i, ++n) {
1487 auto LabelVAPtr = IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, n);
1488 IRB.CreateStore(DFSF.getShadow(*i), LabelVAPtr);
1491 Args.push_back(IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, 0));
1495 if (!DFSF.LabelReturnAlloca) {
1496 DFSF.LabelReturnAlloca =
1497 new AllocaInst(DFSF.DFS.ShadowTy,
"labelreturn",
1498 &DFSF.F->getEntryBlock().front());
1500 Args.push_back(DFSF.LabelReturnAlloca);
1506 CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
1511 LoadInst *LabelLoad = IRB.CreateLoad(DFSF.LabelReturnAlloca);
1512 DFSF.setShadow(CustomCI, LabelLoad);
1526 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1528 IRB.CreateStore(DFSF.getShadow(CS.
getArgument(i)),
1536 if (II->getNormalDest()->getSinglePredecessor()) {
1537 Next = &II->getNormalDest()->front();
1540 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
1541 Next = &NewBB->
front();
1545 Next = CS->getNextNode();
1548 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1550 LoadInst *LI = NextIRB.CreateLoad(DFSF.getRetvalTLS());
1551 DFSF.SkipInsts.insert(LI);
1553 DFSF.NonZeroChecks.push_back(LI);
1559 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_Args) {
1560 FunctionType *NewFT = DFSF.DFS.getArgsFunctionType(FT);
1562 IRB.CreateBitCast(CS.
getCalledValue(), PointerType::getUnqual(NewFT));
1563 std::vector<Value *>
Args;
1571 Args.push_back(DFSF.getShadow(*i));
1575 ArrayType *VarArgArrayTy = ArrayType::get(DFSF.DFS.ShadowTy, VarArgSize);
1577 new AllocaInst(VarArgArrayTy,
"", &DFSF.F->getEntryBlock().front());
1578 Args.push_back(IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, 0));
1579 for (
unsigned n = 0; i != e; ++
i, ++n) {
1582 IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, n));
1589 NewCS = IRB.CreateInvoke(Func, II->getNormalDest(), II->getUnwindDest(),
1592 NewCS = IRB.CreateCall(Func, Args);
1596 *DFSF.DFS.Ctx, AttributeSet::ReturnIndex,
1602 DFSF.SkipInsts.insert(ExVal);
1605 DFSF.SkipInsts.insert(ExShadow);
1606 DFSF.setShadow(ExVal, ExShadow);
1607 DFSF.NonZeroChecks.push_back(ExShadow);
1616 void DFSanVisitor::visitPHINode(
PHINode &PN) {
1621 Value *UndefShadow = UndefValue::get(DFSF.DFS.ShadowTy);
1627 DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
1628 DFSF.setShadow(&PN, ShadowPN);
AttributeSet getAttributes() const
Return the parameter attributes for this call.
Return a value (possibly void), from a function.
Value * getValueOperand()
const Value * getCalledValue() const
Get a pointer to the function that is invoked by this instruction.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static cl::list< std::string > ClABIListFiles("dfsan-abilist", cl::desc("File listing native ABI functions and how the pass treats them"), cl::Hidden)
void push_back(const T &Elt)
A parsed version of the target data layout string in and methods for querying it. ...
LinkageTypes getLinkage() const
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
void ReplaceInstWithInst(BasicBlock::InstListType &BIL, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
This class is the base class for the comparison instructions.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
LLVM Argument representation.
Base class for instruction visitors.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
A Module instance is used to store all the information related to an LLVM module. ...
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
ConstantInt * getAlignmentCst() const
Value * getValue() const
Return the arguments to the instruction.
Implements a dense probed hash-table based set.
unsigned getNumOperands() const
Type::subtype_iterator param_iterator
BBTy * getParent() const
Get the basic block containing the call site.
Type * getValueType() const
This class represents a function call, abstracting a target machine's calling convention.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
size_type count(PtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void setAttributes(AttributeSet PAL)
This instruction constructs a fixed permutation of two input vectors.
This class wraps the llvm.memset intrinsic.
const Instruction & front() const
An instruction for reading from memory.
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
void GetUnderlyingObjects(Value *V, SmallVectorImpl< Value * > &Objects, const DataLayout &DL, LoopInfo *LI=nullptr, unsigned MaxLookup=6)
This method is similar to GetUnderlyingObject except that it can look through phi and select instruct...
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
Type * getPointerElementType() const
unsigned arg_size() const
StringRef getName() const
Return a constant reference to the value's name.
block_iterator block_end()
iterator begin()
Instruction iterator methods.
void removeAttributes(unsigned i, AttributeSet Attrs)
removes the attributes from the list of attributes.
void setCallingConv(CallingConv::ID CC)
static cl::opt< bool > ClArgsABI("dfsan-args-abi", cl::desc("Use the argument ABI rather than the TLS ABI"), cl::Hidden)
The address of a basic block.
This class represents the LLVM 'select' instruction.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
This is the base class for all instructions that perform data casts.
Class to represent struct types.
param_iterator param_end() const
ValTy * getCalledValue() const
getCalledValue - Return the pointer to function that is being called.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void setThreadLocalMode(ThreadLocalMode Val)
void setModuleInlineAsm(StringRef Asm)
Set the module-scope inline assembly blocks.
void setName(const Twine &Name)
Change the name of the value.
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
static cl::opt< bool > ClCombinePointerLabelsOnStore("dfsan-combine-pointer-labels-on-store", cl::desc("Combine the label of the pointer with the label of the data when ""storing in memory."), cl::Hidden, cl::init(false))
block_iterator block_begin()
Class to represent function types.
CallingConv::ID getCallingConv() const
getCallingConv/setCallingConv - get or set the calling convention of the call.
Class to represent array types.
Function Alias Analysis false
BasicBlock * getSuccessor(unsigned i) const
Base class for the actual dominator tree node.
static std::string utostr(uint64_t X, bool isNeg=false)
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void takeName(Value *V)
Transfer the name from V to this value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Class to represent pointers.
void setAttributes(AttributeSet Attrs)
Set the parameter attributes for this call.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
initializer< Ty > init(const Ty &Val)
This instruction inserts a single (scalar) element into a VectorType value.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
Conditional or Unconditional Branch instruction.
This function has undefined behavior.
This is an important base class in LLVM.
const Value * getCondition() const
param_iterator param_begin() const
static const char *const kDFSanExternShadowPtrMask
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void addAttribute(unsigned i, Attribute::AttrKind Kind)
adds the attribute to the list of attributes.
void splice(iterator where, iplist_impl &L2)
const GlobalObject * getBaseObject() const
ConstantInt * getVolatileCst() const
void setCallingConv(CallingConv::ID CC)
void copyAttributesFrom(const GlobalValue *Src) override
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Value * getOperand(unsigned i) const
Value * getPointerOperand()
self_iterator getIterator()
Class to represent integer types.
void setAlignment(unsigned Align)
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
Type * getType() const
getType - Return the type of the instruction that generated this call site
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
const Value * getTrueValue() const
Triple - Helper class for working with autoconf configuration names.
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
const std::string & getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
AttributeSet getAttributes() const
getAttributes/setAttributes - get or set the parameter attributes of the call.
IntegerType * getIntPtrType(LLVMContext &C, unsigned AddressSpace=0) const
Returns an integer type with size at least as big as that of a pointer in the given address space...
unsigned getABITypeAlignment(Type *Ty) const
Returns the minimum ABI-required alignment for the specified type.
Iterator for intrusive lists based on ilist_node.
const BasicBlockListType & getBasicBlockList() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
InstrTy * getInstruction() const
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions that feed it, giving the original input.
bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI=nullptr)
Remove all blocks that can not be reached from the function's entry.
ValTy * getArgument(unsigned ArgNo) const
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Type * getType() const
All values are typed, get the type of this value.
static ManagedStatic< CodeViewErrorCategory > Category
TerminatorInst * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
static cl::opt< bool > ClDebugNonzeroLabels("dfsan-debug-nonzero-labels", cl::desc("Insert calls to __dfsan_nonzero_label on observing a parameter, ""load or return with a nonzero label"), cl::Hidden)
Value * getLength() const
BasicBlock * getBasicBlock() const
const BasicBlock & getEntryBlock() const
void setLinkage(LinkageTypes LT)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
void setOperand(unsigned i, Value *Val)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static cl::opt< bool > ClPreserveAlignment("dfsan-preserve-alignment", cl::desc("respect alignment requirements provided by input IR"), cl::Hidden, cl::init(false))
AttributeSet removeAttributes(LLVMContext &C, unsigned Index, AttributeSet Attrs) const
Remove the specified attributes at the specified index from this attribute list.
Class to represent vector types.
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
LinkageTypes
An enumeration for the kinds of linkage for global values.
INITIALIZE_PASS(DataFlowSanitizer,"dfsan","DataFlowSanitizer: dynamic data flow analysis.", false, false) ModulePass *llvm
iterator_range< user_iterator > users()
void eraseFromParent() override
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
Value * getSource() const
This is just like getRawSource, but it strips off any cast instructions that feed it...
PointerType * getType() const
Global values are always pointers.
This class wraps the llvm.memcpy/memmove intrinsics.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
unsigned getAlignment() const
Return the alignment of the access that is being performed.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
FunctionType * getFunctionType() const
Returns the FunctionType for me.
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
CallInst * CreateCall(Value *Callee, ArrayRef< Value * > Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
uint64_t getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
iterator_range< df_iterator< T > > depth_first(const T &G)
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
FunTy * getCalledFunction() const
getCalledFunction - Return the function being called if this is a direct call, otherwise return null ...
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
const ArgumentListType & getArgumentList() const
Get the underlying elements of the Function...
AttrBuilder typeIncompatible(Type *Ty)
Which attributes cannot be applied to a type.
ModulePass * createDataFlowSanitizerPass(const std::vector< std::string > &ABIListFiles=std::vector< std::string >(), void *(*getArgTLS)()=nullptr, void *(*getRetValTLS)()=nullptr)
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr)
Split the edge connecting specified block.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
const Value * getFalseValue() const
StringRef - Represent a constant reference to a string, i.e.
CallingConv::ID getCallingConv() const
getCallingConv/setCallingConv - Get or set the calling convention of this function call...
void addAttribute(unsigned i, Attribute::AttrKind Kind)
adds the attribute to the list of attributes.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
static cl::opt< bool > ClCombinePointerLabelsOnLoad("dfsan-combine-pointer-labels-on-load", cl::desc("Combine the label of the pointer with the label of the data when ""loading from memory."), cl::Hidden, cl::init(true))
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Value * getPointerOperand()
void setCalledFunction(Value *V)
setCalledFunction - Set the callee to the specified value.
const BasicBlock * getParent() const
LLVMContext & getContext() const
Get the global data context.
bool isVoidTy() const
Return true if this is 'void'.
an instruction to allocate memory on the stack
This instruction inserts a struct field of array element value into an aggregate value.