105 using namespace llvm;
119 "dfsan-preserve-alignment",
132 cl::desc(
"File listing native ABI functions and how the pass treats them"),
139 cl::desc(
"Use the argument ABI rather than the TLS ABI"),
145 "dfsan-combine-pointer-labels-on-load",
146 cl::desc(
"Combine the label of the pointer with the label of the data when " 147 "loading from memory."),
153 "dfsan-combine-pointer-labels-on-store",
154 cl::desc(
"Combine the label of the pointer with the label of the data when " 155 "storing in memory."),
159 "dfsan-debug-nonzero-labels",
160 cl::desc(
"Insert calls to __dfsan_nonzero_label on observing a parameter, " 161 "load or return with a nonzero label"),
168 if (
StructType *SGType = dyn_cast<StructType>(GType)) {
169 if (!SGType->isLiteral())
170 return SGType->getName();
172 return "<unknown type>";
178 std::unique_ptr<SpecialCaseList> SCL;
181 DFSanABIList() =
default;
183 void set(std::unique_ptr<SpecialCaseList>
List) { SCL = std::move(
List); }
189 SCL->inSection(
"dataflow",
"fun", F.
getName(), Category);
201 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
203 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
217 struct TransformedFunction {
220 std::vector<unsigned> ArgumentIndexMapping)
221 : OriginalType(OriginalType),
222 TransformedType(TransformedType),
223 ArgumentIndexMapping(ArgumentIndexMapping) {}
226 TransformedFunction(
const TransformedFunction&) =
delete;
227 TransformedFunction& operator=(
const TransformedFunction&) =
delete;
230 TransformedFunction(TransformedFunction&&) =
default;
231 TransformedFunction& operator=(TransformedFunction&&) =
default;
244 std::vector<unsigned> ArgumentIndexMapping;
251 const TransformedFunction& TransformedFunction,
255 std::vector<llvm::AttributeSet> ArgumentAttributes(
256 TransformedFunction.TransformedType->getNumParams());
261 for (
unsigned i=0, ie = TransformedFunction.ArgumentIndexMapping.size();
263 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[i];
268 for (
unsigned i = TransformedFunction.OriginalType->getNumParams(),
281 friend struct DFSanFunction;
282 friend class DFSanVisitor;
289 enum InstrumentedABI {
334 void *(*GetArgTLSPtr)();
335 void *(*GetRetvalTLSPtr)();
353 DFSanABIList ABIList;
356 bool DFSanRuntimeShadowMask =
false;
363 TransformedFunction getCustomFunctionType(
FunctionType *T);
364 InstrumentedABI getInstrumentedABI();
365 WrapperKind getWrapperKind(
Function *F);
376 const std::vector<std::string> &ABIListFiles = std::vector<std::string>(),
377 void *(*getArgTLS)() =
nullptr,
void *(*getRetValTLS)() =
nullptr);
379 bool doInitialization(
Module &M)
override;
380 bool runOnModule(
Module &M)
override;
383 struct DFSanFunction {
384 DataFlowSanitizer &
DFS;
387 DataFlowSanitizer::InstrumentedABI IA;
389 Value *ArgTLSPtr =
nullptr;
390 Value *RetvalTLSPtr =
nullptr;
394 std::vector<std::pair<PHINode *, PHINode *>> PHIFixups;
396 std::vector<Value *> NonZeroChecks;
399 struct CachedCombinedShadow {
404 CachedCombinedShadows;
407 DFSanFunction(DataFlowSanitizer &DFS,
Function *F,
bool IsNativeABI)
408 :
DFS(DFS),
F(F), IA(DFS.getInstrumentedABI()), IsNativeABI(IsNativeABI) {
412 AvoidNewBlocks = F->
size() > 1000;
415 Value *getArgTLSPtr();
417 Value *getRetvalTLS();
424 void storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
Value *Shadow,
428 class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
432 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
435 return DFSF.F->getParent()->getDataLayout();
441 void visitCmpInst(
CmpInst &CI);
447 void visitPHINode(
PHINode &PN);
464 "DataFlowSanitizer: dynamic data flow analysis.",
false,
false)
468 void *(*getArgTLS)(),
469 void *(*getRetValTLS)()) {
470 return new DataFlowSanitizer(ABIListFiles, getArgTLS, getRetValTLS);
473 DataFlowSanitizer::DataFlowSanitizer(
474 const std::vector<std::string> &ABIListFiles,
void *(*getArgTLS)(),
475 void *(*getRetValTLS)())
476 :
ModulePass(
ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS) {
477 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
478 AllABIListFiles.insert(AllABIListFiles.end(),
ClABIListFiles.begin(),
487 ArgTypes.push_back(ShadowPtrTy);
502 ArgTypes.push_back(ShadowPtrTy);
506 TransformedFunction DataFlowSanitizer::getCustomFunctionType(
FunctionType *T) {
513 std::vector<unsigned> ArgumentIndexMapping;
514 for (
unsigned i = 0, ie = T->
getNumParams(); i != ie; ++i) {
517 if (isa<PointerType>(param_type) && (FT = dyn_cast<FunctionType>(
518 cast<PointerType>(param_type)->getElementType()))) {
519 ArgumentIndexMapping.push_back(ArgTypes.
size());
520 ArgTypes.
push_back(getTrampolineFunctionType(FT)->getPointerTo());
523 ArgumentIndexMapping.push_back(ArgTypes.
size());
527 for (
unsigned i = 0, e = T->
getNumParams(); i != e; ++i)
534 return TransformedFunction(
536 ArgumentIndexMapping);
539 bool DataFlowSanitizer::doInitialization(
Module &M) {
542 bool IsMIPS64 = TargetTriple.isMIPS64();
561 DFSanRuntimeShadowMask =
true;
565 Type *DFSanUnionArgs[2] = { ShadowTy, ShadowTy };
568 Type *DFSanUnionLoadArgs[2] = { ShadowPtrTy, IntptrTy };
575 DFSanSetLabelArgs,
false);
589 if (GetRetvalTLSPtr) {
601 bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
602 return !ABIList.isIn(*F,
"uninstrumented");
605 bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
606 return !ABIList.isIn(*GA,
"uninstrumented");
609 DataFlowSanitizer::InstrumentedABI DataFlowSanitizer::getInstrumentedABI() {
613 DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *F) {
614 if (ABIList.isIn(*F,
"functional"))
615 return WK_Functional;
616 if (ABIList.isIn(*F,
"discard"))
618 if (ABIList.isIn(*F,
"custom"))
624 void DataFlowSanitizer::addGlobalNamePrefix(
GlobalValue *GV) {
634 std::string SearchStr =
".symver " + GVName +
",";
635 size_t Pos = Asm.find(SearchStr);
636 if (Pos != std::string::npos) {
637 Asm.replace(Pos, SearchStr.size(),
664 std::vector<Value *>
Args;
667 Args.push_back(&*ai);
686 std::vector<Value *>
Args;
689 Args.push_back(&*AI);
697 DFSanFunction DFSF(*
this, F,
true);
699 for (
unsigned N = FT->
getNumParams();
N != 0; ++ValAI, ++ShadowAI, --
N)
700 DFSF.ValShadowMap[&*ValAI] = &*ShadowAI;
701 DFSanVisitor(DFSF).visitCallInst(*CI);
703 new StoreInst(DFSF.getShadow(RI->getReturnValue()),
704 &*std::prev(F->
arg_end()), RI);
710 bool DataFlowSanitizer::runOnModule(
Module &M) {
711 if (ABIList.isIn(M,
"skip"))
716 ArgTLS =
Mod->getOrInsertGlobal(
"__dfsan_arg_tls", ArgTLSTy);
720 if (!GetRetvalTLSPtr) {
721 RetvalTLS =
Mod->getOrInsertGlobal(
"__dfsan_retval_tls", ShadowTy);
727 Mod->getOrInsertGlobal(kDFSanExternShadowPtrMask, IntptrTy);
729 DFSanUnionFn =
Mod->getOrInsertFunction(
"__dfsan_union", DFSanUnionFnTy);
730 if (
Function *F = dyn_cast<Function>(DFSanUnionFn)) {
737 DFSanCheckedUnionFn =
Mod->getOrInsertFunction(
"dfsan_union", DFSanUnionFnTy);
738 if (
Function *F = dyn_cast<Function>(DFSanCheckedUnionFn)) {
746 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy);
747 if (
Function *F = dyn_cast<Function>(DFSanUnionLoadFn)) {
752 DFSanUnimplementedFn =
753 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
755 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy);
756 if (
Function *F = dyn_cast<Function>(DFSanSetLabelFn)) {
759 DFSanNonzeroLabelFn =
760 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
761 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
762 DFSanVarargWrapperFnTy);
764 std::vector<Function *> FnsToInstrument;
767 if (!i.isIntrinsic() &&
768 &i != DFSanUnionFn &&
769 &i != DFSanCheckedUnionFn &&
770 &i != DFSanUnionLoadFn &&
771 &i != DFSanUnimplementedFn &&
772 &i != DFSanSetLabelFn &&
773 &i != DFSanNonzeroLabelFn &&
774 &i != DFSanVarargWrapperFn)
775 FnsToInstrument.push_back(&i);
786 bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
787 if (GAInst && FInst) {
788 addGlobalNamePrefix(GA);
789 }
else if (GAInst != FInst) {
798 FnsToInstrument.push_back(NewF);
808 for (std::vector<Function *>::iterator i = FnsToInstrument.begin(),
809 e = FnsToInstrument.end();
817 if (isInstrumented(&F)) {
820 if (getInstrumentedABI() == IA_Args && !IsZeroArgsVoidRet) {
831 FArg != FArgEnd; ++FArg, ++NewFArg) {
832 FArg->replaceAllUsesWith(&*NewFArg);
851 addGlobalNamePrefix(NewF);
853 addGlobalNamePrefix(&F);
855 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
860 ? getArgsFunctionType(FT)
870 Function *NewF = buildWrapperFunction(
871 &F, std::string(
"dfsw$") + std::string(F.
getName()),
872 wrapperLinkage, NewFT);
873 if (getInstrumentedABI() == IA_TLS)
876 Value *WrappedFnCst =
880 UnwrappedFnMap[WrappedFnCst] = &
F;
888 FnsWithNativeABI.
insert(&F);
893 size_t N = i - FnsToInstrument.begin(),
894 Count = e - FnsToInstrument.begin();
895 FnsToInstrument.push_back(&F);
896 i = FnsToInstrument.begin() +
N;
897 e = FnsToInstrument.begin() + Count;
902 UnwrappedFnMap[&
F] = &
F;
907 for (
Function *i : FnsToInstrument) {
908 if (!i || i->isDeclaration())
913 DFSanFunction DFSF(*
this, i, FnsWithNativeABI.
count(i));
929 if (!DFSF.SkipInsts.count(Inst))
930 DFSanVisitor(DFSF).visit(Inst);
941 for (std::vector<std::pair<PHINode *, PHINode *>>::iterator
942 i = DFSF.PHIFixups.begin(),
943 e = DFSF.PHIFixups.end();
945 for (
unsigned val = 0, n = i->first->getNumIncomingValues(); val != n;
947 i->second->setIncomingValue(
948 val, DFSF.getShadow(i->first->getIncomingValue(val)));
957 for (
Value *V : DFSF.NonZeroChecks) {
960 Pos =
I->getNextNode();
962 Pos = &DFSF.F->getEntryBlock().front();
963 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
968 Ne, Pos,
false, ColdCallWeights));
970 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
978 Value *DFSanFunction::getArgTLSPtr() {
982 return ArgTLSPtr =
DFS.ArgTLS;
988 Value *DFSanFunction::getRetvalTLS() {
992 return RetvalTLSPtr =
DFS.RetvalTLS;
1004 if (!isa<Argument>(V) && !isa<Instruction>(V))
1005 return DFS.ZeroShadow;
1006 Value *&Shadow = ValShadowMap[V];
1008 if (
Argument *A = dyn_cast<Argument>(V)) {
1010 return DFS.ZeroShadow;
1012 case DataFlowSanitizer::IA_TLS: {
1013 Value *ArgTLSPtr = getArgTLSPtr();
1016 : cast<Instruction>(ArgTLSPtr)->getNextNode();
1018 Shadow = IRB.
CreateLoad(getArgTLS(A->getArgNo(), ArgTLSPos));
1021 case DataFlowSanitizer::IA_Args: {
1022 unsigned ArgIdx = A->getArgNo() + F->
arg_size() / 2;
1031 NonZeroChecks.push_back(Shadow);
1033 Shadow =
DFS.ZeroShadow;
1040 assert(!ValShadowMap.count(I));
1042 ValShadowMap[
I] = Shadow;
1046 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
1048 Value *ShadowPtrMaskValue;
1049 if (DFSanRuntimeShadowMask)
1050 ShadowPtrMaskValue = IRB.
CreateLoad(IntptrTy, ExternalShadowMask);
1052 ShadowPtrMaskValue = ShadowPtrMask;
1064 if (V1 ==
DFS.ZeroShadow)
1066 if (V2 ==
DFS.ZeroShadow)
1071 auto V1Elems = ShadowElements.find(V1);
1072 auto V2Elems = ShadowElements.find(V2);
1073 if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) {
1074 if (std::includes(V1Elems->second.begin(), V1Elems->second.end(),
1075 V2Elems->second.begin(), V2Elems->second.end())) {
1077 }
else if (std::includes(V2Elems->second.begin(), V2Elems->second.end(),
1078 V1Elems->second.begin(), V1Elems->second.end())) {
1081 }
else if (V1Elems != ShadowElements.end()) {
1082 if (V1Elems->second.count(V2))
1084 }
else if (V2Elems != ShadowElements.end()) {
1085 if (V2Elems->second.count(V1))
1089 auto Key = std::make_pair(V1, V2);
1092 CachedCombinedShadow &CCS = CachedCombinedShadows[
Key];
1093 if (CCS.Block && DT.dominates(CCS.Block, Pos->
getParent()))
1097 if (AvoidNewBlocks) {
1109 Ne, Pos,
false,
DFS.ColdCallWeights, &DT));
1111 CallInst *Call = ThenIRB.CreateCall(
DFS.DFSanUnionFn, {V1, V2});
1125 std::set<Value *> UnionElems;
1126 if (V1Elems != ShadowElements.end()) {
1127 UnionElems = V1Elems->second;
1129 UnionElems.insert(V1);
1131 if (V2Elems != ShadowElements.end()) {
1132 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
1134 UnionElems.insert(V2);
1136 ShadowElements[CCS.Shadow] = std::move(UnionElems);
1146 return DFS.ZeroShadow;
1150 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(i)), Inst);
1155 void DFSanVisitor::visitOperandShadowInst(
Instruction &I) {
1156 Value *CombinedShadow = DFSF.combineOperandShadows(&I);
1157 DFSF.setShadow(&I, CombinedShadow);
1164 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
1165 const auto i = AllocaShadowMap.find(AI);
1166 if (i != AllocaShadowMap.end()) {
1172 uint64_t ShadowAlign = Align *
DFS.ShadowWidth / 8;
1175 bool AllConstants =
true;
1176 for (
Value *Obj : Objs) {
1177 if (isa<Function>(Obj) || isa<BlockAddress>(Obj))
1179 if (isa<GlobalVariable>(Obj) && cast<GlobalVariable>(Obj)->
isConstant())
1182 AllConstants =
false;
1186 return DFS.ZeroShadow;
1188 Value *ShadowAddr =
DFS.getShadowAddress(Addr, Pos);
1191 return DFS.ZeroShadow;
1205 if (!AvoidNewBlocks && Size % (64 /
DFS.ShadowWidth) == 0) {
1212 DFS.DFSanUnionLoadFn,
1213 {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
1232 std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end());
1234 DomTreeNode *NewNode = DT.addNewBlock(Tail, Head);
1235 for (
auto Child : Children)
1236 DT.changeImmediateDominator(Child, NewNode);
1245 DT.addNewBlock(FallbackBB, Head);
1247 for (uint64_t Ofs = 64 /
DFS.ShadowWidth; Ofs != Size;
1248 Ofs += 64 /
DFS.ShadowWidth) {
1250 DT.addNewBlock(NextBB, LastBr->
getParent());
1255 ShadowsEq = NextIRB.
CreateICmpEQ(WideShadow, NextWideShadow);
1257 LastBr = NextIRB.
CreateCondBr(ShadowsEq, FallbackBB, FallbackBB);
1270 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
1272 return FallbackCall;
1275 void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
1279 DFSF.setShadow(&LI, DFSF.DFS.ZeroShadow);
1287 Align = DL.getABITypeAlignment(LI.
getType());
1295 Shadow = DFSF.combineShadows(Shadow, PtrShadow, &LI);
1297 if (Shadow != DFSF.DFS.ZeroShadow)
1298 DFSF.NonZeroChecks.push_back(Shadow);
1300 DFSF.setShadow(&LI, Shadow);
1303 void DFSanFunction::storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
1305 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
1306 const auto i = AllocaShadowMap.find(AI);
1307 if (i != AllocaShadowMap.end()) {
1314 uint64_t ShadowAlign = Align *
DFS.ShadowWidth / 8;
1316 Value *ShadowAddr =
DFS.getShadowAddress(Addr, Pos);
1317 if (Shadow ==
DFS.ZeroShadow) {
1320 Value *ExtShadowAddr =
1326 const unsigned ShadowVecSize = 128 /
DFS.ShadowWidth;
1328 if (Size >= ShadowVecSize) {
1331 for (
unsigned i = 0; i != ShadowVecSize; ++i) {
1335 Value *ShadowVecAddr =
1338 Value *CurShadowVecAddr =
1341 Size -= ShadowVecSize;
1343 }
while (Size >= ShadowVecSize);
1344 Offset *= ShadowVecSize;
1347 Value *CurShadowAddr =
1355 void DFSanVisitor::visitStoreInst(
StoreInst &
SI) {
1373 Shadow = DFSF.combineShadows(Shadow, PtrShadow, &SI);
1379 visitOperandShadowInst(BO);
1382 void DFSanVisitor::visitCastInst(
CastInst &CI) { visitOperandShadowInst(CI); }
1384 void DFSanVisitor::visitCmpInst(
CmpInst &CI) { visitOperandShadowInst(CI); }
1387 visitOperandShadowInst(GEPI);
1391 visitOperandShadowInst(I);
1395 visitOperandShadowInst(I);
1399 visitOperandShadowInst(I);
1403 visitOperandShadowInst(I);
1407 visitOperandShadowInst(I);
1410 void DFSanVisitor::visitAllocaInst(
AllocaInst &I) {
1411 bool AllLoadsStores =
true;
1413 if (isa<LoadInst>(U))
1416 if (
StoreInst *SI = dyn_cast<StoreInst>(U)) {
1421 AllLoadsStores =
false;
1424 if (AllLoadsStores) {
1426 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.ShadowTy);
1428 DFSF.setShadow(&I, DFSF.DFS.ZeroShadow);
1431 void DFSanVisitor::visitSelectInst(
SelectInst &I) {
1439 DFSF.combineShadows(
1440 CondShadow, DFSF.combineShadows(TrueShadow, FalseShadow, &I), &
I));
1443 if (TrueShadow == FalseShadow) {
1444 ShadowSel = TrueShadow;
1449 DFSF.setShadow(&I, DFSF.combineShadows(CondShadow, ShadowSel, &I));
1453 void DFSanVisitor::visitMemSetInst(
MemSetInst &I) {
1457 {ValShadow, IRB.CreateBitCast(I.getDest(), Type::getInt8PtrTy(
1459 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
1464 Value *DestShadow = DFSF.DFS.getShadowAddress(I.
getDest(), &
I);
1472 auto *MTI = cast<MemTransferInst>(
1479 MTI->setDestAlignment(DFSF.DFS.ShadowWidth / 8);
1480 MTI->setSourceAlignment(DFSF.DFS.ShadowWidth / 8);
1484 void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
1487 case DataFlowSanitizer::IA_TLS: {
1493 case DataFlowSanitizer::IA_Args: {
1495 Type *RT = DFSF.F->getFunctionType()->getReturnType();
1507 void DFSanVisitor::visitCallSite(
CallSite CS) {
1516 if (F == DFSF.DFS.DFSanVarargWrapperFn)
1523 if (i != DFSF.DFS.UnwrappedFnMap.end()) {
1525 switch (DFSF.DFS.getWrapperKind(F)) {
1526 case DataFlowSanitizer::WK_Warning:
1528 IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
1529 IRB.CreateGlobalStringPtr(F->
getName()));
1532 case DataFlowSanitizer::WK_Discard:
1536 case DataFlowSanitizer::WK_Functional:
1540 case DataFlowSanitizer::WK_Custom:
1546 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
1547 std::string CustomFName =
"__dfsw_";
1549 Constant *CustomF = DFSF.DFS.Mod->getOrInsertFunction(
1550 CustomFName, CustomFn.TransformedType);
1551 if (
Function *CustomFn = dyn_cast<Function>(CustomF)) {
1552 CustomFn->copyAttributesFrom(F);
1557 DFSF.DFS.ReadOnlyNoneAttrs);
1561 std::vector<Value *>
Args;
1564 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n) {
1565 Type *T = (*i)->getType();
1567 if (isa<PointerType>(T) &&
1568 (ParamFT = dyn_cast<FunctionType>(
1569 cast<PointerType>(T)->getElementType()))) {
1570 std::string TName =
"dfst";
1574 Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
1584 const unsigned ShadowArgStart = Args.size();
1585 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1586 Args.push_back(DFSF.getShadow(*i));
1592 LabelVATy, getDataLayout().getAllocaAddrSpace(),
1593 "labelva", &DFSF.F->getEntryBlock().front());
1595 for (
unsigned n = 0; i != CS.
arg_end(); ++i, ++n) {
1596 auto LabelVAPtr = IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, n);
1597 IRB.CreateStore(DFSF.getShadow(*i), LabelVAPtr);
1600 Args.push_back(IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, 0));
1604 if (!DFSF.LabelReturnAlloca) {
1605 DFSF.LabelReturnAlloca =
1607 getDataLayout().getAllocaAddrSpace(),
1608 "labelreturn", &DFSF.F->getEntryBlock().front());
1610 Args.push_back(DFSF.LabelReturnAlloca);
1616 CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
1618 CustomCI->
setAttributes(TransformFunctionAttributes(CustomFn,
1625 const unsigned ArgNo = ShadowArgStart + n;
1631 LoadInst *LabelLoad = IRB.CreateLoad(DFSF.LabelReturnAlloca);
1632 DFSF.setShadow(CustomCI, LabelLoad);
1645 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1646 for (
unsigned i = 0, n = FT->
getNumParams(); i != n; ++i) {
1647 IRB.CreateStore(DFSF.getShadow(CS.
getArgument(i)),
1655 if (II->getNormalDest()->getSinglePredecessor()) {
1656 Next = &II->getNormalDest()->front();
1659 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
1660 Next = &NewBB->
front();
1664 Next = CS->getNextNode();
1667 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1670 DFSF.SkipInsts.insert(LI);
1672 DFSF.NonZeroChecks.push_back(LI);
1678 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_Args) {
1679 FunctionType *NewFT = DFSF.DFS.getArgsFunctionType(FT);
1682 std::vector<Value *>
Args;
1685 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1689 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1690 Args.push_back(DFSF.getShadow(*i));
1696 new AllocaInst(VarArgArrayTy, getDataLayout().getAllocaAddrSpace(),
1697 "", &DFSF.F->getEntryBlock().front());
1698 Args.push_back(IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, 0));
1699 for (
unsigned n = 0; i != e; ++i, ++n) {
1702 IRB.CreateConstGEP2_32(VarArgArrayTy, VarArgShadow, 0, n));
1709 NewCS = IRB.CreateInvoke(Func, II->getNormalDest(), II->getUnwindDest(),
1712 NewCS = IRB.CreateCall(Func, Args);
1722 DFSF.SkipInsts.insert(ExVal);
1725 DFSF.SkipInsts.insert(ExShadow);
1726 DFSF.setShadow(ExVal, ExShadow);
1727 DFSF.NonZeroChecks.push_back(ExShadow);
1736 void DFSanVisitor::visitPHINode(
PHINode &PN) {
1747 DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
1748 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()
User::op_iterator arg_iterator
The type of iterator to use when looping over actual arguments at this call site. ...
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.
const GlobalObject * getBaseObject() const
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.
unsigned arg_size() const
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
CallingConv::ID getCallingConv() const
Get the calling convention of the call.
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 addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
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)
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
bool removeUnreachableBlocks(Function &F, LazyValueInfo *LVI=nullptr, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
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)
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.
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...
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.
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.
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.
InstrTy * getInstruction() const
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
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)
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
ValTy * getCalledValue() const
Return the pointer to function that is being called.
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.
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
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...
void setAttributes(AttributeList PAL)
Set the parameter attributes of the call.
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)
Value * getCalledValue() const
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.
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 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
static const char *const kDFSanExternShadowPtrMask
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
void addAttribute(unsigned i, Attribute::AttrKind Kind)
adds the attribute to the list of attributes.
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)
void setCallingConv(CallingConv::ID CC)
Set the calling convention of the call.
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.
void setAlignment(unsigned Align)
const Value * getCondition() const
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
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="")
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.
ValTy * getArgument(unsigned ArgNo) const
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="")
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)
unsigned getNumIncomingValues() const
Return the number of incoming edges.
BBTy * getParent() const
Get the basic block containing the call site.
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.
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.
Instruction * 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 ...
void removeAttributes(unsigned i, const AttrBuilder &Attrs)
removes the attributes from the list of attributes.
This class wraps the llvm.memcpy/memmove intrinsics.
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="")
StringRef getName() const
Return a constant reference to the value's name.
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.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
static StringRef GetGlobalTypeString(const GlobalValue &G)
Type * getType() const
Return the type of the instruction that generated this call site.
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...
FunTy * getCalledFunction() const
Return the function being called if this is a direct call, otherwise return null (if it's an indirect...
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...
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.
uint64_t getTypeStoreSize(Type *Ty) const
Returns the maximum number of bytes that may be overwritten by storing the specified type...
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
static VectorType * get(Type *ElementType, unsigned NumElements)
This static method is the primary way to construct an VectorType.
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.
AttributeList getAttributes() const
Get the parameter attributes of the call.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * getPointerOperand()
void setCalledFunction(Value *V)
Set the callee to the specified value.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
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.