104 using namespace llvm;
118 "dfsan-preserve-alignment",
131 cl::desc(
"File listing native ABI functions and how the pass treats them"),
138 cl::desc(
"Use the argument ABI rather than the TLS ABI"),
144 "dfsan-combine-pointer-labels-on-load",
145 cl::desc(
"Combine the label of the pointer with the label of the data when " 146 "loading from memory."),
152 "dfsan-combine-pointer-labels-on-store",
153 cl::desc(
"Combine the label of the pointer with the label of the data when " 154 "storing in memory."),
158 "dfsan-debug-nonzero-labels",
159 cl::desc(
"Insert calls to __dfsan_nonzero_label on observing a parameter, " 160 "load or return with a nonzero label"),
167 if (
StructType *SGType = dyn_cast<StructType>(GType)) {
168 if (!SGType->isLiteral())
169 return SGType->getName();
171 return "<unknown type>";
177 std::unique_ptr<SpecialCaseList> SCL;
180 DFSanABIList() =
default;
182 void set(std::unique_ptr<SpecialCaseList>
List) { SCL = std::move(
List); }
188 SCL->inSection(
"dataflow",
"fun", F.
getName(), Category);
200 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
202 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
216 struct TransformedFunction {
219 std::vector<unsigned> ArgumentIndexMapping)
220 : OriginalType(OriginalType),
221 TransformedType(TransformedType),
222 ArgumentIndexMapping(ArgumentIndexMapping) {}
225 TransformedFunction(
const TransformedFunction&) =
delete;
226 TransformedFunction& operator=(
const TransformedFunction&) =
delete;
229 TransformedFunction(TransformedFunction&&) =
default;
230 TransformedFunction& operator=(TransformedFunction&&) =
default;
243 std::vector<unsigned> ArgumentIndexMapping;
250 const TransformedFunction& TransformedFunction,
254 std::vector<llvm::AttributeSet> ArgumentAttributes(
255 TransformedFunction.TransformedType->getNumParams());
260 for (
unsigned i=0, ie = TransformedFunction.ArgumentIndexMapping.size();
262 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[i];
267 for (
unsigned i = TransformedFunction.OriginalType->getNumParams(),
280 friend struct DFSanFunction;
281 friend class DFSanVisitor;
288 enum InstrumentedABI {
333 void *(*GetArgTLSPtr)();
334 void *(*GetRetvalTLSPtr)();
354 DFSanABIList ABIList;
357 bool DFSanRuntimeShadowMask =
false;
364 TransformedFunction getCustomFunctionType(
FunctionType *T);
365 InstrumentedABI getInstrumentedABI();
366 WrapperKind getWrapperKind(
Function *F);
377 const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
378 void *(*getArgTLS)() =
nullptr,
void *(*getRetValTLS)() =
nullptr);
380 bool doInitialization(
Module &M)
override;
381 bool runOnModule(
Module &M)
override;
384 struct DFSanFunction {
385 DataFlowSanitizer &
DFS;
388 DataFlowSanitizer::InstrumentedABI IA;
390 Value *ArgTLSPtr =
nullptr;
391 Value *RetvalTLSPtr =
nullptr;
395 std::vector<std::pair<PHINode *, PHINode *>> PHIFixups;
397 std::vector<Value *> NonZeroChecks;
400 struct CachedCombinedShadow {
405 CachedCombinedShadows;
408 DFSanFunction(DataFlowSanitizer &DFS,
Function *F,
bool IsNativeABI)
409 :
DFS(DFS),
F(F), IA(DFS.getInstrumentedABI()), IsNativeABI(IsNativeABI) {
413 AvoidNewBlocks = F->
size() > 1000;
416 Value *getArgTLSPtr();
418 Value *getRetvalTLS();
425 void storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
Value *Shadow,
429 class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
433 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
436 return DFSF.F->getParent()->getDataLayout();
443 void visitCmpInst(
CmpInst &CI);
449 void visitPHINode(
PHINode &PN);
466 "DataFlowSanitizer: dynamic data flow analysis.",
false,
false)
470 void *(*getArgTLS)(),
471 void *(*getRetValTLS)()) {
472 return new DataFlowSanitizer(ABIListFiles, getArgTLS, getRetValTLS);
475 DataFlowSanitizer::DataFlowSanitizer(
476 const std::vector<std::string> &ABIListFiles,
void *(*getArgTLS)(),
477 void *(*getRetValTLS)())
478 :
ModulePass(
ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS) {
479 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
480 AllABIListFiles.insert(AllABIListFiles.end(),
ClABIListFiles.begin(),
489 ArgTypes.push_back(ShadowPtrTy);
504 ArgTypes.push_back(ShadowPtrTy);
508 TransformedFunction DataFlowSanitizer::getCustomFunctionType(
FunctionType *T) {
515 std::vector<unsigned> ArgumentIndexMapping;
516 for (
unsigned i = 0, ie = T->
getNumParams(); i != ie; ++i) {
519 if (isa<PointerType>(param_type) && (FT = dyn_cast<FunctionType>(
520 cast<PointerType>(param_type)->getElementType()))) {
521 ArgumentIndexMapping.push_back(ArgTypes.
size());
522 ArgTypes.
push_back(getTrampolineFunctionType(FT)->getPointerTo());
525 ArgumentIndexMapping.push_back(ArgTypes.
size());
536 return TransformedFunction(
538 ArgumentIndexMapping);
541 bool DataFlowSanitizer::doInitialization(
Module &M) {
544 bool IsMIPS64 = TargetTriple.isMIPS64();
563 DFSanRuntimeShadowMask =
true;
567 Type *DFSanUnionArgs[2] = { ShadowTy, ShadowTy };
570 Type *DFSanUnionLoadArgs[2] = { ShadowPtrTy, IntptrTy };
577 DFSanSetLabelArgs,
false);
591 if (GetRetvalTLSPtr) {
603 bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
604 return !ABIList.isIn(*F,
"uninstrumented");
607 bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
608 return !ABIList.isIn(*GA,
"uninstrumented");
611 DataFlowSanitizer::InstrumentedABI DataFlowSanitizer::getInstrumentedABI() {
615 DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *F) {
616 if (ABIList.isIn(*F,
"functional"))
617 return WK_Functional;
618 if (ABIList.isIn(*F,
"discard"))
620 if (ABIList.isIn(*F,
"custom"))
626 void DataFlowSanitizer::addGlobalNamePrefix(
GlobalValue *GV) {
636 std::string SearchStr =
".symver " + GVName +
",";
637 size_t Pos = Asm.find(SearchStr);
638 if (Pos != std::string::npos) {
639 Asm.replace(Pos, SearchStr.size(),
666 std::vector<Value *>
Args;
669 Args.push_back(&*ai);
688 std::vector<Value *>
Args;
691 Args.push_back(&*AI);
699 DFSanFunction DFSF(*
this, F,
true);
701 for (
unsigned N = FT->
getNumParams();
N != 0; ++ValAI, ++ShadowAI, --
N)
702 DFSF.ValShadowMap[&*ValAI] = &*ShadowAI;
703 DFSanVisitor(DFSF).visitCallInst(*CI);
705 new StoreInst(DFSF.getShadow(RI->getReturnValue()),
706 &*std::prev(F->
arg_end()), RI);
712 bool DataFlowSanitizer::runOnModule(
Module &M) {
713 if (ABIList.isIn(M,
"skip"))
718 ArgTLS =
Mod->getOrInsertGlobal(
"__dfsan_arg_tls", ArgTLSTy);
722 if (!GetRetvalTLSPtr) {
723 RetvalTLS =
Mod->getOrInsertGlobal(
"__dfsan_retval_tls", ShadowTy);
729 Mod->getOrInsertGlobal(kDFSanExternShadowPtrMask, IntptrTy);
734 Attribute::NoUnwind);
736 Attribute::ReadNone);
742 Mod->getOrInsertFunction(
"__dfsan_union", DFSanUnionFnTy, AL);
748 Attribute::NoUnwind);
750 Attribute::ReadNone);
755 DFSanCheckedUnionFn =
756 Mod->getOrInsertFunction(
"dfsan_union", DFSanUnionFnTy, AL);
761 Attribute::NoUnwind);
763 Attribute::ReadOnly);
767 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
769 DFSanUnimplementedFn =
770 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
775 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
777 DFSanNonzeroLabelFn =
778 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
779 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
780 DFSanVarargWrapperFnTy);
782 std::vector<Function *> FnsToInstrument;
785 if (!i.isIntrinsic() &&
786 &i != DFSanUnionFn.getCallee()->stripPointerCasts() &&
787 &i != DFSanCheckedUnionFn.getCallee()->stripPointerCasts() &&
788 &i != DFSanUnionLoadFn.getCallee()->stripPointerCasts() &&
789 &i != DFSanUnimplementedFn.getCallee()->stripPointerCasts() &&
790 &i != DFSanSetLabelFn.getCallee()->stripPointerCasts() &&
791 &i != DFSanNonzeroLabelFn.getCallee()->stripPointerCasts() &&
792 &i != DFSanVarargWrapperFn.getCallee()->stripPointerCasts())
793 FnsToInstrument.push_back(&i);
804 bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
805 if (GAInst && FInst) {
806 addGlobalNamePrefix(GA);
807 }
else if (GAInst != FInst) {
816 FnsToInstrument.push_back(NewF);
821 ReadOnlyNoneAttrs.addAttribute(Attribute::ReadOnly)
822 .addAttribute(Attribute::ReadNone);
826 for (std::vector<Function *>::iterator i = FnsToInstrument.begin(),
827 e = FnsToInstrument.end();
835 if (isInstrumented(&F)) {
838 if (getInstrumentedABI() == IA_Args && !IsZeroArgsVoidRet) {
849 FArg != FArgEnd; ++FArg, ++NewFArg) {
850 FArg->replaceAllUsesWith(&*NewFArg);
869 addGlobalNamePrefix(NewF);
871 addGlobalNamePrefix(&F);
873 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
878 ? getArgsFunctionType(FT)
888 Function *NewF = buildWrapperFunction(
889 &F, std::string(
"dfsw$") + std::string(F.
getName()),
890 wrapperLinkage, NewFT);
891 if (getInstrumentedABI() == IA_TLS)
894 Value *WrappedFnCst =
898 UnwrappedFnMap[WrappedFnCst] = &
F;
906 FnsWithNativeABI.
insert(&F);
911 size_t N = i - FnsToInstrument.begin(),
912 Count =
e - FnsToInstrument.begin();
913 FnsToInstrument.push_back(&F);
914 i = FnsToInstrument.begin() +
N;
915 e = FnsToInstrument.begin() + Count;
920 UnwrappedFnMap[&
F] = &
F;
925 for (
Function *i : FnsToInstrument) {
926 if (!i || i->isDeclaration())
931 DFSanFunction DFSF(*
this, i, FnsWithNativeABI.
count(i));
947 if (!DFSF.SkipInsts.count(Inst))
948 DFSanVisitor(DFSF).visit(Inst);
959 for (std::vector<std::pair<PHINode *, PHINode *>>::iterator
960 i = DFSF.PHIFixups.begin(),
961 e = DFSF.PHIFixups.end();
963 for (
unsigned val = 0, n = i->first->getNumIncomingValues(); val != n;
965 i->second->setIncomingValue(
966 val, DFSF.getShadow(i->first->getIncomingValue(val)));
975 for (
Value *V : DFSF.NonZeroChecks) {
978 Pos =
I->getNextNode();
980 Pos = &DFSF.F->getEntryBlock().front();
981 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
986 Ne, Pos,
false, ColdCallWeights));
988 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
996 Value *DFSanFunction::getArgTLSPtr() {
1000 return ArgTLSPtr =
DFS.ArgTLS;
1006 Value *DFSanFunction::getRetvalTLS() {
1008 return RetvalTLSPtr;
1010 return RetvalTLSPtr =
DFS.RetvalTLS;
1013 return RetvalTLSPtr =
1020 getArgTLSPtr(), 0, Idx);
1024 if (!isa<Argument>(V) && !isa<Instruction>(V))
1025 return DFS.ZeroShadow;
1026 Value *&Shadow = ValShadowMap[V];
1028 if (
Argument *A = dyn_cast<Argument>(V)) {
1030 return DFS.ZeroShadow;
1032 case DataFlowSanitizer::IA_TLS: {
1033 Value *ArgTLSPtr = getArgTLSPtr();
1036 : cast<Instruction>(ArgTLSPtr)->getNextNode();
1039 IRB.
CreateLoad(
DFS.ShadowTy, getArgTLS(A->getArgNo(), ArgTLSPos));
1042 case DataFlowSanitizer::IA_Args: {
1043 unsigned ArgIdx = A->getArgNo() + F->
arg_size() / 2;
1052 NonZeroChecks.push_back(Shadow);
1054 Shadow =
DFS.ZeroShadow;
1061 assert(!ValShadowMap.count(I));
1063 ValShadowMap[
I] = Shadow;
1067 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
1069 Value *ShadowPtrMaskValue;
1070 if (DFSanRuntimeShadowMask)
1071 ShadowPtrMaskValue = IRB.
CreateLoad(IntptrTy, ExternalShadowMask);
1073 ShadowPtrMaskValue = ShadowPtrMask;
1085 if (V1 ==
DFS.ZeroShadow)
1087 if (V2 ==
DFS.ZeroShadow)
1092 auto V1Elems = ShadowElements.find(V1);
1093 auto V2Elems = ShadowElements.find(V2);
1094 if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) {
1095 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1096 V2Elems->second.begin(), V2Elems->second.end())) {
1098 }
else if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1099 V1Elems->second.begin(), V1Elems->second.end())) {
1102 }
else if (V1Elems != ShadowElements.end()) {
1103 if (V1Elems->second.count(V2))
1105 }
else if (V2Elems != ShadowElements.end()) {
1106 if (V2Elems->second.count(V1))
1110 auto Key = std::make_pair(V1, V2);
1113 CachedCombinedShadow &CCS = CachedCombinedShadows[
Key];
1114 if (CCS.Block && DT.dominates(CCS.Block, Pos->
getParent()))
1118 if (AvoidNewBlocks) {
1130 Ne, Pos,
false,
DFS.ColdCallWeights, &DT));
1132 CallInst *Call = ThenIRB.CreateCall(
DFS.DFSanUnionFn, {V1, V2});
1146 std::set<Value *> UnionElems;
1147 if (V1Elems != ShadowElements.end()) {
1148 UnionElems = V1Elems->second;
1150 UnionElems.insert(V1);
1152 if (V2Elems != ShadowElements.end()) {
1153 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
1155 UnionElems.insert(V2);
1157 ShadowElements[CCS.Shadow] = std::move(UnionElems);
1167 return DFS.ZeroShadow;
1171 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(i)), Inst);
1176 void DFSanVisitor::visitOperandShadowInst(
Instruction &I) {
1177 Value *CombinedShadow = DFSF.combineOperandShadows(&I);
1178 DFSF.setShadow(&I, CombinedShadow);
1185 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
1186 const auto i = AllocaShadowMap.find(AI);
1187 if (i != AllocaShadowMap.end()) {
1193 uint64_t ShadowAlign = Align *
DFS.ShadowWidth / 8;
1196 bool AllConstants =
true;
1197 for (
const Value *Obj : Objs) {
1198 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
1200 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
1203 AllConstants =
false;
1207 return DFS.ZeroShadow;
1209 Value *ShadowAddr =
DFS.getShadowAddress(Addr, Pos);
1212 return DFS.ZeroShadow;
1222 return combineShadows(
1227 if (!AvoidNewBlocks && Size % (64 /
DFS.ShadowWidth) == 0) {
1234 DFS.DFSanUnionLoadFn,
1235 {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
1255 std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end());
1257 DomTreeNode *NewNode = DT.addNewBlock(Tail, Head);
1258 for (
auto Child : Children)
1259 DT.changeImmediateDominator(Child, NewNode);
1268 DT.addNewBlock(FallbackBB, Head);
1270 for (uint64_t Ofs = 64 /
DFS.ShadowWidth; Ofs != Size;
1271 Ofs += 64 /
DFS.ShadowWidth) {
1273 DT.addNewBlock(NextBB, LastBr->
getParent());
1278 WideAddr, ShadowAlign);
1279 ShadowsEq = NextIRB.
CreateICmpEQ(WideShadow, NextWideShadow);
1281 LastBr = NextIRB.
CreateCondBr(ShadowsEq, FallbackBB, FallbackBB);
1294 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
1296 return FallbackCall;
1299 void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
1303 DFSF.setShadow(&LI, DFSF.DFS.ZeroShadow);
1311 Align = DL.getABITypeAlignment(LI.
getType());
1319 Shadow = DFSF.combineShadows(Shadow, PtrShadow, &LI);
1321 if (Shadow != DFSF.DFS.ZeroShadow)
1322 DFSF.NonZeroChecks.push_back(Shadow);
1324 DFSF.setShadow(&LI, Shadow);
1327 void DFSanFunction::storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
1329 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
1330 const auto i = AllocaShadowMap.find(AI);
1331 if (i != AllocaShadowMap.end()) {
1338 uint64_t ShadowAlign = Align *
DFS.ShadowWidth / 8;
1340 Value *ShadowAddr =
DFS.getShadowAddress(Addr, Pos);
1341 if (Shadow ==
DFS.ZeroShadow) {
1344 Value *ExtShadowAddr =
1350 const unsigned ShadowVecSize = 128 /
DFS.ShadowWidth;
1352 if (Size >= ShadowVecSize) {
1355 for (
unsigned i = 0; i != ShadowVecSize; ++i) {
1359 Value *ShadowVecAddr =
1362 Value *CurShadowVecAddr =
1365 Size -= ShadowVecSize;
1367 }
while (Size >= ShadowVecSize);
1368 Offset *= ShadowVecSize;
1371 Value *CurShadowAddr =
1379 void DFSanVisitor::visitStoreInst(
StoreInst &
SI) {
1397 Shadow = DFSF.combineShadows(Shadow, PtrShadow, &SI);
1403 visitOperandShadowInst(UO);
1407 visitOperandShadowInst(BO);
1410 void DFSanVisitor::visitCastInst(
CastInst &CI) { visitOperandShadowInst(CI); }
1412 void DFSanVisitor::visitCmpInst(
CmpInst &CI) { visitOperandShadowInst(CI); }
1415 visitOperandShadowInst(GEPI);
1419 visitOperandShadowInst(I);
1423 visitOperandShadowInst(I);
1427 visitOperandShadowInst(I);
1431 visitOperandShadowInst(I);
1435 visitOperandShadowInst(I);
1438 void DFSanVisitor::visitAllocaInst(
AllocaInst &I) {
1439 bool AllLoadsStores =
true;
1441 if (isa<LoadInst>(U))
1444 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
1449 AllLoadsStores =
false;
1452 if (AllLoadsStores) {
1454 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.ShadowTy);
1456 DFSF.setShadow(&I, DFSF.DFS.ZeroShadow);
1459 void DFSanVisitor::visitSelectInst(
SelectInst &I) {
1467 DFSF.combineShadows(
1468 CondShadow, DFSF.combineShadows(TrueShadow, FalseShadow, &I), &
I));
1471 if (TrueShadow == FalseShadow) {
1472 ShadowSel = TrueShadow;
1477 DFSF.setShadow(&I, DFSF.combineShadows(CondShadow, ShadowSel, &I));
1481 void DFSanVisitor::visitMemSetInst(
MemSetInst &I) {
1485 {ValShadow, IRB.CreateBitCast(I.getDest(), Type::getInt8PtrTy(
1487 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
1492 Value *DestShadow = DFSF.DFS.getShadowAddress(I.
getDest(), &
I);
1500 auto *MTI = cast<MemTransferInst>(
1507 MTI->setDestAlignment(DFSF.DFS.ShadowWidth / 8);
1508 MTI->setSourceAlignment(DFSF.DFS.ShadowWidth / 8);
1512 void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
1515 case DataFlowSanitizer::IA_TLS: {
1521 case DataFlowSanitizer::IA_Args: {
1523 Type *RT = DFSF.F->getFunctionType()->getReturnType();
1535 void DFSanVisitor::visitCallSite(
CallSite CS) {
1551 if (i != DFSF.DFS.UnwrappedFnMap.end()) {
1553 switch (DFSF.DFS.getWrapperKind(F)) {
1554 case DataFlowSanitizer::WK_Warning:
1556 IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
1557 IRB.CreateGlobalStringPtr(F->
getName()));
1560 case DataFlowSanitizer::WK_Discard:
1564 case DataFlowSanitizer::WK_Functional:
1568 case DataFlowSanitizer::WK_Custom:
1574 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
1575 std::string CustomFName =
"__dfsw_";
1578 CustomFName, CustomFn.TransformedType);
1580 CustomFn->copyAttributesFrom(F);
1585 DFSF.DFS.ReadOnlyNoneAttrs);
1589 std::vector<Value *>
Args;
1592 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n) {
1593 Type *T = (*i)->getType();
1595 if (isa<PointerType>(T) &&
1596 (ParamFT = dyn_cast<FunctionType>(
1597 cast<PointerType>(T)->getElementType()))) {
1598 std::string TName =
"dfst";
1602 Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
1612 const unsigned ShadowArgStart = Args.size();
1613 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1614 Args.push_back(DFSF.getShadow(*i));
1620 LabelVATy, getDataLayout().getAllocaAddrSpace(),
1621 "labelva", &DFSF.F->getEntryBlock().front());
1623 for (
unsigned n = 0; i != CS.
arg_end(); ++i, ++n) {
1624 auto LabelVAPtr = IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, n);
1625 IRB.CreateStore(DFSF.getShadow(*i), LabelVAPtr);
1628 Args.push_back(IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, 0));
1632 if (!DFSF.LabelReturnAlloca) {
1633 DFSF.LabelReturnAlloca =
1635 getDataLayout().getAllocaAddrSpace(),
1636 "labelreturn", &DFSF.F->getEntryBlock().front());
1638 Args.push_back(DFSF.LabelReturnAlloca);
1644 CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
1646 CustomCI->
setAttributes(TransformFunctionAttributes(CustomFn,
1653 const unsigned ArgNo = ShadowArgStart + n;
1660 IRB.CreateLoad(DFSF.DFS.ShadowTy, DFSF.LabelReturnAlloca);
1661 DFSF.setShadow(CustomCI, LabelLoad);
1674 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1675 for (
unsigned i = 0, n = FT->
getNumParams(); i != n; ++i) {
1676 IRB.CreateStore(DFSF.getShadow(CS.
getArgument(i)),
1684 if (II->getNormalDest()->getSinglePredecessor()) {
1685 Next = &II->getNormalDest()->front();
1688 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
1689 Next = &NewBB->
front();
1693 Next = CS->getNextNode();
1696 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1699 DFSF.SkipInsts.insert(LI);
1701 DFSF.NonZeroChecks.push_back(LI);
1707 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_Args) {
1708 FunctionType *NewFT = DFSF.DFS.getArgsFunctionType(FT);
1711 std::vector<Value *>
Args;
1714 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1718 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1719 Args.push_back(DFSF.getShadow(*i));
1725 new AllocaInst(VarArgArrayTy, getDataLayout().getAllocaAddrSpace(),
1726 "", &DFSF.F->getEntryBlock().front());
1727 Args.push_back(IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, 0));
1728 for (
unsigned n = 0; i !=
e; ++i, ++n) {
1731 IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, n));
1738 NewCS = IRB.CreateInvoke(NewFT, Func, II->getNormalDest(),
1739 II->getUnwindDest(),
Args);
1741 NewCS = IRB.CreateCall(NewFT, Func, Args);
1751 DFSF.SkipInsts.insert(ExVal);
1754 DFSF.SkipInsts.insert(ExShadow);
1755 DFSF.setShadow(ExVal, ExShadow);
1756 DFSF.NonZeroChecks.push_back(ExShadow);
1765 void DFSanVisitor::visitPHINode(
PHINode &PN) {
1776 DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
1777 DFSF.setShadow(&PN, ShadowPN);
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Return a value (possibly void), from a function.
Value * getValueOperand()
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
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)
A parsed version of the target data layout string in and methods for querying it. ...
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
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.
Value * CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name="")
static bool isConstant(const MachineInstr &MI)
bool hasLocalLinkage() const
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
This class represents an incoming formal argument to a Function.
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Base class for instruction visitors.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
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.
This class represents lattice values for constants.
Type * getParamType(unsigned i) const
Parameter type accessors.
void setAttributes(AttributeList PAL)
Set the parameter attributes of the call.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
A Module instance is used to store all the information related to an LLVM module. ...
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, unsigned Align, const char *Name)
Provided to resolve 'CreateAlignedLoad(Ptr, Align, "...")' correctly, instead of converting the strin...
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Implements a dense probed hash-table based set.
void push_back(const T &Elt)
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
This class represents a function call, abstracting a target machine's calling convention.
unsigned getSourceAlignment() const
const Value * getTrueValue() const
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
void setCallingConv(CallingConv::ID CC)
Set the calling convention of the call.
This instruction constructs a fixed permutation of two input vectors.
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", Instruction *InsertBefore=nullptr, Instruction *MDFrom=nullptr)
LLVMContext & getContext() const
All values hold a context through their type.
bool isTerminator() const
This class wraps the llvm.memset intrinsic.
BasicBlock * getSuccessor(unsigned i) const
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))
param_iterator param_end() const
An instruction for reading from memory.
FunTy * getCalledFunction() const
Return the function being called if this is a direct call, otherwise return null (if it's an indirect...
static IntegerType * getInt64Ty(LLVMContext &C)
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
void addAttribute(unsigned i, Attribute::AttrKind Kind)
adds the attribute to the list of attributes.
Value * getLength() const
INITIALIZE_PASS(DataFlowSanitizer, "dfsan", "DataFlowSanitizer: dynamic data flow analysis.", false, false) ModulePass *llvm
static PointerType * getInt64PtrTy(LLVMContext &C, unsigned AS=0)
static std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths)
Parses the special case list entries from files.
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
CallingConv::ID getCallingConv() const
Get the calling convention of the call.
block_iterator block_end()
Value * getDest() const
This is just like getRawDest, but it strips off any cast instructions (including addrspacecast) that ...
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align, bool isVolatile=false)
iterator begin()
Instruction iterator methods.
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Split the edge connecting specified block.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
Value * getArgOperand(unsigned i) const
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.
Type * getPointerElementType() const
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
This is the base class for all instructions that perform data casts.
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Class to represent struct types.
LLVMContext & getContext() const
Get the global data context.
ValTy * getCalledValue() const
Return the pointer to function that is being called.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
This file contains the simple types necessary to represent the attributes associated with functions a...
AttributeSet getRetAttributes() const
The attributes for the ret value are returned.
void setModuleInlineAsm(StringRef Asm)
Set the module-scope inline assembly blocks.
void setName(const Twine &Name)
Change the name of the value.
unsigned getDestAlignment() const
Type * getType() const
Return the type of the instruction that generated this call site.
block_iterator block_begin()
static StructType * get(LLVMContext &Context, ArrayRef< Type *> Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
InstrTy * getInstruction() const
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Class to represent function types.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Type * getType() const
All values are typed, get the type of this value.
LLVM_NODISCARD AttributeList removeAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &AttrsToRemove) const
Remove the specified attributes at the specified index from this attribute list.
TypeSize getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Class to represent array types.
AttributeSet getParamAttributes(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
BasicBlock * getBasicBlock() const
const GlobalObject * getBaseObject() const
An instruction for storing to memory.
LinkageTypes getLinkage() const
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...
Value * getOperand(unsigned i) const
Class to represent pointers.
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
iterator find(const_arg_type_t< KeyT > Val)
static Constant * getBitCast(Constant *C, Type *Ty, bool OnlyIfReduced=false)
bool isVoidTy() const
Return true if this is 'void'.
const BasicBlock & getEntryBlock() const
an instruction for type-safe pointer arithmetic to access elements of arrays and structs ...
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...
Same, but only replaced by something equivalent.
initializer< Ty > init(const Ty &Val)
This instruction inserts a single (scalar) element into a VectorType value.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void GetUnderlyingObjects(const Value *V, SmallVectorImpl< const 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...
void setCalledFunction(Value *V)
Set the callee to the specified value.
Value * getCalledValue() const
LLVM Basic Block Representation.
LLVM_NODISCARD AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const
Add an argument attribute to the list.
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.
static BlockAddress * get(Function *F, BasicBlock *BB)
Return a BlockAddress for the specified function and basic block.
This function has undefined behavior.
This is an important base class in LLVM.
void setAlignment(MaybeAlign Align)
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const Instruction & front() const
AttributeList getAttributes() const
Get the parameter attributes of the call.
FunctionType * getFunctionType() const
static const char *const kDFSanExternShadowPtrMask
ValTy * getArgument(unsigned ArgNo) const
unsigned getNumParams() const
Return the number of fixed parameters this function type requires.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
param_iterator param_begin() const
static Type * getVoidTy(LLVMContext &C)
void splice(iterator where, iplist_impl &L2)
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)
unsigned getAddressSpace() const
void setCallingConv(CallingConv::ID CC)
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Value * getPointerOperand()
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
self_iterator getIterator()
Class to represent integer types.
const Value * getCondition() const
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
const Constant * stripPointerCasts() const
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
const std::string & getModuleIdentifier() const
Get the module identifier which is, essentially, the name of the module.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="")
This struct is a compact representation of a valid (non-zero power of two) alignment.
Triple - Helper class for working with autoconf configuration names.
ConstantInt * getVolatileCst() const
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
Value * CreateGEP(Value *Ptr, ArrayRef< Value *> IdxList, const Twine &Name="")
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Iterator for intrusive lists based on ilist_node.
unsigned getNumOperands() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
This is the shared class of boolean and integer constants.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Value * CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name="")
unsigned arg_size() const
Type * getReturnType() const
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
std::string utostr(uint64_t X, bool isNeg=false)
User::op_iterator arg_iterator
The type of iterator to use when looping over actual arguments at this call site. ...
unsigned getNumIncomingValues() const
Return the number of incoming edges.
void setLinkage(LinkageTypes LT)
void setOperand(unsigned i, Value *Val)
The access may modify the value stored in memory.
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))
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Class to represent vector types.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
unsigned getNumAttrSets() const
LinkageTypes
An enumeration for the kinds of linkage for global values.
BBTy * getParent() const
Get the basic block containing the call site.
iterator_range< user_iterator > users()
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
const Value * getFalseValue() const
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
void removeAttributes(unsigned i, const AttrBuilder &Attrs)
removes the attributes from the list of attributes.
This class wraps the llvm.memcpy/memmove intrinsics.
LLVM_NODISCARD AttributeList addAttribute(LLVMContext &C, unsigned Index, Attribute::AttrKind Kind) const
Add an attribute to the attribute set at the given index.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
static IntegerType * getInt32Ty(LLVMContext &C)
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))
Value * CreateConstGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
static VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
StringRef getName() const
Return a constant reference to the value's name.
Tail - This calling convention attemps to make calls as fast as possible while guaranteeing that tail...
user_iterator_impl< User > user_iterator
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Type * getValueType() const
const BasicBlockListType & getBasicBlockList() const
Get the underlying elements of the Function...
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it...
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
static StringRef GetGlobalTypeString(const GlobalValue &G)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
const std::string & getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
iterator_range< df_iterator< T > > depth_first(const T &G)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
AttrBuilder typeIncompatible(Type *Ty)
Which attributes cannot be applied to a type.
AttributeSet getFnAttributes() const
The function attributes are returned.
ModulePass * createDataFlowSanitizerPass(const std::vector< std::string > &ABIListFiles=std::vector< std::string >(), void *(*getArgTLS)()=nullptr, void *(*getRetValTLS)()=nullptr)
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * getSource() const
This is just like getRawSource, but it strips off any cast instructions that feed it...
StringRef - Represent a constant reference to a string, i.e.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * getPointerOperand()
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Instruction * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
PointerType * getType() const
Global values are always pointers.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute >> Attrs)
Create an AttributeList with the specified parameters in it.
const BasicBlock * getParent() const
an instruction to allocate memory on the stack
This instruction inserts a struct field of array element value into an aggregate value.