76 "dfsan-preserve-alignment",
89 cl::desc(
"File listing native ABI functions and how the pass treats them"),
96 cl::desc(
"Use the argument ABI rather than the TLS ABI"),
100 "dfsan-debug-nonzero-labels",
101 cl::desc(
"Insert calls to __dfsan_nonzero_label on observing a parameter, "
102 "load or return with a nonzero label"),
108 friend struct DFSanFunction;
109 friend class DFSanVisitor;
116 enum InstrumentedABI {
162 void *(*GetArgTLSPtr)();
163 void *(*GetRetvalTLSPtr)();
188 InstrumentedABI getInstrumentedABI();
198 void *(*getArgTLS)() = 0,
void *(*getRetValTLS)() = 0);
200 bool doInitialization(
Module &M);
201 bool runOnModule(
Module &M);
204 struct DFSanFunction {
205 DataFlowSanitizer &DFS;
207 DataFlowSanitizer::InstrumentedABI IA;
214 std::vector<std::pair<PHINode *, PHINode *> > PHIFixups;
218 DFSanFunction(DataFlowSanitizer &DFS,
Function *
F,
bool IsNativeABI)
219 : DFS(DFS), F(F), IA(DFS.getInstrumentedABI()),
220 IsNativeABI(IsNativeABI), ArgTLSPtr(0), RetvalTLSPtr(0),
221 LabelReturnAlloca(0) {}
222 Value *getArgTLSPtr();
224 Value *getRetvalTLS();
230 void storeShadow(
Value *Addr, uint64_t Size, uint64_t
Align,
Value *Shadow,
234 class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
237 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
243 void visitCmpInst(
CmpInst &CI);
249 void visitPHINode(
PHINode &PN);
265 "DataFlowSanitizer: dynamic data flow analysis.",
false,
false)
268 void *(*getArgTLS)(),
269 void *(*getRetValTLS)()) {
270 return new DataFlowSanitizer(ABIListFile, getArgTLS, getRetValTLS);
273 DataFlowSanitizer::DataFlowSanitizer(
StringRef ABIListFile,
274 void *(*getArgTLS)(),
275 void *(*getRetValTLS)())
276 :
ModulePass(
ID), GetArgTLSPtr(getArgTLS), GetRetvalTLSPtr(getRetValTLS),
284 for (
unsigned i = 0, e = T->
getNumParams(); i != e; ++i)
290 RetType = StructType::get(RetType, ShadowTy, (
Type *)0);
291 return FunctionType::get(RetType, ArgTypes, T->
isVarArg());
299 for (
unsigned i = 0, e = T->
getNumParams(); i != e; ++i)
300 ArgTypes.push_back(ShadowTy);
303 ArgTypes.push_back(ShadowPtrTy);
304 return FunctionType::get(T->
getReturnType(), ArgTypes,
false);
314 *i)->getElementType()))) {
315 ArgTypes.push_back(getTrampolineFunctionType(FT)->getPointerTo());
316 ArgTypes.push_back(Type::getInt8PtrTy(*Ctx));
318 ArgTypes.push_back(*i);
321 for (
unsigned i = 0, e = T->
getNumParams(); i != e; ++i)
322 ArgTypes.push_back(ShadowTy);
325 ArgTypes.push_back(ShadowPtrTy);
326 return FunctionType::get(T->
getReturnType(), ArgTypes,
false);
329 bool DataFlowSanitizer::doInitialization(
Module &M) {
330 DL = getAnalysisIfAvailable<DataLayout>();
336 ShadowTy = IntegerType::get(*Ctx, ShadowWidth);
337 ShadowPtrTy = PointerType::getUnqual(ShadowTy);
338 IntptrTy = DL->getIntPtrType(*Ctx);
339 ZeroShadow = ConstantInt::getSigned(ShadowTy, 0);
340 ShadowPtrMask = ConstantInt::getSigned(IntptrTy, ~0x700000000000LL);
341 ShadowPtrMul = ConstantInt::getSigned(IntptrTy, ShadowWidth / 8);
343 Type *DFSanUnionArgs[2] = { ShadowTy, ShadowTy };
345 FunctionType::get(ShadowTy, DFSanUnionArgs,
false);
346 Type *DFSanUnionLoadArgs[2] = { ShadowPtrTy, IntptrTy };
348 FunctionType::get(ShadowTy, DFSanUnionLoadArgs,
false);
349 DFSanUnimplementedFnTy = FunctionType::get(
350 Type::getVoidTy(*Ctx), Type::getInt8PtrTy(*Ctx),
false);
351 Type *DFSanSetLabelArgs[3] = { ShadowTy, Type::getInt8PtrTy(*Ctx), IntptrTy };
352 DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
353 DFSanSetLabelArgs,
false);
354 DFSanNonzeroLabelFnTy = FunctionType::get(
358 Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
360 GetArgTLS = ConstantExpr::getIntToPtr(
361 ConstantInt::get(IntptrTy, uintptr_t(GetArgTLSPtr)),
362 PointerType::getUnqual(
363 FunctionType::get(PointerType::getUnqual(ArgTLSTy), (
Type *)0)));
365 if (GetRetvalTLSPtr) {
367 GetRetvalTLS = ConstantExpr::getIntToPtr(
368 ConstantInt::get(IntptrTy, uintptr_t(GetRetvalTLSPtr)),
369 PointerType::getUnqual(
370 FunctionType::get(PointerType::getUnqual(ShadowTy), (
Type *)0)));
377 bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
378 return !ABIList->isIn(*F,
"uninstrumented");
381 bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
382 return !ABIList->isIn(*GA,
"uninstrumented");
385 DataFlowSanitizer::InstrumentedABI DataFlowSanitizer::getInstrumentedABI() {
389 DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *F) {
390 if (ABIList->isIn(*F,
"functional"))
391 return WK_Functional;
392 if (ABIList->isIn(*F,
"discard"))
394 if (ABIList->isIn(*F,
"custom"))
400 void DataFlowSanitizer::addGlobalNamePrefix(
GlobalValue *GV) {
410 std::string SearchStr =
".symver " + GVName +
",";
411 size_t Pos = Asm.find(SearchStr);
412 if (Pos != std::string::npos) {
413 Asm.replace(Pos, SearchStr.size(),
424 Function *NewF = Function::Create(NewFT, NewFLink, NewFName,
428 AttributeSet::ReturnIndex,
430 AttributeSet::ReturnIndex));
432 BasicBlock *BB = BasicBlock::Create(*Ctx,
"entry", NewF);
433 std::vector<Value *> Args;
436 Args.push_back(&*ai);
437 CallInst *CI = CallInst::Create(F, Args,
"", BB);
439 ReturnInst::Create(*Ctx, BB);
441 ReturnInst::Create(*Ctx, CI, BB);
449 Constant *
C = Mod->getOrInsertFunction(FName, FTT);
452 F->
setLinkage(GlobalValue::LinkOnceODRLinkage);
453 BasicBlock *BB = BasicBlock::Create(*Ctx,
"entry", F);
454 std::vector<Value *> Args;
457 Args.push_back(&*AI);
462 RI = ReturnInst::Create(*Ctx, BB);
464 RI = ReturnInst::Create(*Ctx, CI, BB);
466 DFSanFunction DFSF(*
this, F,
true);
468 for (
unsigned N = FT->
getNumParams();
N != 0; ++ValAI, ++ShadowAI, --
N)
469 DFSF.ValShadowMap[ValAI] = ShadowAI;
470 DFSanVisitor(DFSF).visitCallInst(*CI);
472 new StoreInst(DFSF.getShadow(RI->getReturnValue()),
479 bool DataFlowSanitizer::runOnModule(
Module &M) {
483 if (ABIList->isIn(M,
"skip"))
487 Type *ArgTLSTy = ArrayType::get(ShadowTy, 64);
488 ArgTLS = Mod->getOrInsertGlobal(
"__dfsan_arg_tls", ArgTLSTy);
490 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
492 if (!GetRetvalTLSPtr) {
493 RetvalTLS = Mod->getOrInsertGlobal(
"__dfsan_retval_tls", ShadowTy);
495 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
498 DFSanUnionFn = Mod->getOrInsertFunction(
"__dfsan_union", DFSanUnionFnTy);
499 if (
Function *F = dyn_cast<Function>(DFSanUnionFn)) {
500 F->
addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
501 F->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
506 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy);
507 if (
Function *F = dyn_cast<Function>(DFSanUnionLoadFn)) {
508 F->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
510 DFSanUnimplementedFn =
511 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
513 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy);
514 if (
Function *F = dyn_cast<Function>(DFSanSetLabelFn)) {
517 DFSanNonzeroLabelFn =
518 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
520 std::vector<Function *> FnsToInstrument;
523 if (!i->isIntrinsic() &&
525 i != DFSanUnionLoadFn &&
526 i != DFSanUnimplementedFn &&
527 i != DFSanSetLabelFn &&
528 i != DFSanNonzeroLabelFn)
529 FnsToInstrument.push_back(&*i);
539 if (
Function *F = dyn_cast<Function>(
541 bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
542 if (GAInst && FInst) {
543 addGlobalNamePrefix(GA);
544 }
else if (GAInst != FInst) {
553 FnsToInstrument.push_back(NewF);
560 ReadOnlyNoneAttrs = AttributeSet::get(*Ctx, AttributeSet::FunctionIndex, B);
564 for (std::vector<Function *>::iterator i = FnsToInstrument.begin(),
565 e = FnsToInstrument.end();
573 if (isInstrumented(&F)) {
576 if (getInstrumentedABI() == IA_Args && !IsZeroArgsVoidRet) {
581 AttributeSet::ReturnIndex,
583 AttributeSet::ReturnIndex));
587 FArg != FArgEnd; ++FArg, ++NewFArg) {
588 FArg->replaceAllUsesWith(NewFArg);
603 ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT)));
607 addGlobalNamePrefix(NewF);
609 addGlobalNamePrefix(&F);
614 UnwrappedFnMap[&
F] = &
F;
616 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
621 ? getArgsFunctionType(FT)
623 Function *NewF = buildWrapperFunction(
624 &F, std::string(
"dfsw$") + std::string(F.
getName()),
625 GlobalValue::LinkOnceODRLinkage, NewFT);
626 if (getInstrumentedABI() == IA_TLS)
629 Value *WrappedFnCst =
630 ConstantExpr::getBitCast(NewF, PointerType::getUnqual(FT));
632 UnwrappedFnMap[WrappedFnCst] = &
F;
640 FnsWithNativeABI.
insert(&F);
645 size_t N = i - FnsToInstrument.begin(),
646 Count = e - FnsToInstrument.begin();
647 FnsToInstrument.push_back(&F);
648 i = FnsToInstrument.begin() +
N;
649 e = FnsToInstrument.begin() + Count;
654 for (std::vector<Function *>::iterator i = FnsToInstrument.begin(),
655 e = FnsToInstrument.end();
657 if (!*i || (*i)->isDeclaration())
662 DFSanFunction DFSF(*
this, *i, FnsWithNativeABI.
count(*i));
667 std::copy(
df_begin(&(*i)->getEntryBlock()),
df_end(&(*i)->getEntryBlock()),
668 std::back_inserter(BBList));
681 bool IsTerminator = isa<TerminatorInst>(Inst);
682 if (!DFSF.SkipInsts.count(Inst))
683 DFSanVisitor(DFSF).visit(Inst);
694 for (std::vector<std::pair<PHINode *, PHINode *> >::iterator
695 i = DFSF.PHIFixups.begin(),
696 e = DFSF.PHIFixups.end();
698 for (
unsigned val = 0, n = i->first->getNumIncomingValues(); val != n;
700 i->second->setIncomingValue(
701 val, DFSF.getShadow(i->first->getIncomingValue(val)));
711 e = DFSF.NonZeroChecks.end();
715 Pos =
I->getNextNode();
717 Pos = DFSF.F->getEntryBlock().begin();
718 while (isa<PHINode>(Pos) || isa<AllocaInst>(Pos))
722 IRB.CreateICmpNE(*i, DFSF.DFS.ZeroShadow));
724 NeInst,
false, ColdCallWeights));
726 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn);
734 Value *DFSanFunction::getArgTLSPtr() {
738 return ArgTLSPtr = DFS.ArgTLS;
741 return ArgTLSPtr = IRB.
CreateCall(DFS.GetArgTLS);
744 Value *DFSanFunction::getRetvalTLS() {
748 return RetvalTLSPtr = DFS.RetvalTLS;
751 return RetvalTLSPtr = IRB.
CreateCall(DFS.GetRetvalTLS);
756 return IRB.CreateConstGEP2_64(getArgTLSPtr(), 0, Idx);
760 if (!isa<Argument>(V) && !isa<Instruction>(V))
761 return DFS.ZeroShadow;
762 Value *&Shadow = ValShadowMap[V];
764 if (
Argument *
A = dyn_cast<Argument>(V)) {
766 return DFS.ZeroShadow;
768 case DataFlowSanitizer::IA_TLS: {
769 Value *ArgTLSPtr = getArgTLSPtr();
772 : cast<Instruction>(ArgTLSPtr)->getNextNode();
774 Shadow = IRB.CreateLoad(getArgTLS(
A->getArgNo(), ArgTLSPos));
777 case DataFlowSanitizer::IA_Args: {
783 assert(Shadow->
getType() == DFS.ShadowTy);
787 NonZeroChecks.insert(Shadow);
789 Shadow = DFS.ZeroShadow;
796 assert(!ValShadowMap.count(I));
797 assert(Shadow->
getType() == DFS.ShadowTy);
798 ValShadowMap[
I] = Shadow;
802 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
804 return IRB.CreateIntToPtr(
806 IRB.CreateAnd(IRB.CreatePtrToInt(Addr, IntptrTy), ShadowPtrMask),
815 if (V1 == ZeroShadow)
817 if (V2 == ZeroShadow)
823 Value *Ne = IRB.CreateICmpNE(V1, V2);
827 NeInst,
false, ColdCallWeights));
829 CallInst *
Call = ThenIRB.CreateCall2(DFSanUnionFn, V1, V2);
830 Call->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
835 PHINode *Phi = PHINode::Create(ShadowTy, 2,
"", Tail->
begin());
851 return DFS.ZeroShadow;
855 Shadow = DFS.combineShadows(Shadow, getShadow(Inst->
getOperand(i)), Inst);
860 void DFSanVisitor::visitOperandShadowInst(
Instruction &I) {
861 Value *CombinedShadow = DFSF.combineOperandShadows(&I);
862 DFSF.setShadow(&I, CombinedShadow);
867 Value *DFSanFunction::loadShadow(
Value *Addr, uint64_t Size, uint64_t
Align,
869 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
871 AllocaShadowMap.find(AI);
872 if (i != AllocaShadowMap.end()) {
874 return IRB.CreateLoad(i->second);
878 uint64_t ShadowAlign = Align * DFS.ShadowWidth / 8;
881 bool AllConstants =
true;
884 if (isa<Function>(*i) || isa<BlockAddress>(*i))
886 if (isa<GlobalVariable>(*i) && cast<GlobalVariable>(*i)->isConstant())
889 AllConstants =
false;
893 return DFS.ZeroShadow;
895 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
898 return DFS.ZeroShadow;
907 IRB.CreateGEP(ShadowAddr, ConstantInt::get(DFS.IntptrTy, 1));
908 return DFS.combineShadows(IRB.CreateAlignedLoad(ShadowAddr, ShadowAlign),
909 IRB.CreateAlignedLoad(ShadowAddr1, ShadowAlign),
913 if (Size % (64 / DFS.ShadowWidth) == 0) {
917 BasicBlock *FallbackBB = BasicBlock::Create(*DFS.Ctx,
"", F);
919 CallInst *FallbackCall = FallbackIRB.CreateCall2(
920 DFS.DFSanUnionLoadFn, ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size));
921 FallbackCall->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
927 IRB.CreateBitCast(ShadowAddr, Type::getInt64PtrTy(*DFS.Ctx));
928 Value *WideShadow = IRB.CreateAlignedLoad(WideAddr, ShadowAlign);
929 Value *TruncShadow = IRB.CreateTrunc(WideShadow, DFS.ShadowTy);
930 Value *ShlShadow = IRB.CreateShl(WideShadow, DFS.ShadowWidth);
931 Value *ShrShadow = IRB.CreateLShr(WideShadow, 64 - DFS.ShadowWidth);
932 Value *RotShadow = IRB.CreateOr(ShlShadow, ShrShadow);
933 Value *ShadowsEq = IRB.CreateICmpEQ(WideShadow, RotShadow);
941 BranchInst *LastBr = BranchInst::Create(FallbackBB, FallbackBB, ShadowsEq);
944 for (uint64_t Ofs = 64 / DFS.ShadowWidth; Ofs != Size;
945 Ofs += 64 / DFS.ShadowWidth) {
946 BasicBlock *NextBB = BasicBlock::Create(*DFS.Ctx,
"", F);
948 WideAddr = NextIRB.CreateGEP(WideAddr, ConstantInt::get(DFS.IntptrTy, 1));
949 Value *NextWideShadow = NextIRB.CreateAlignedLoad(WideAddr, ShadowAlign);
950 ShadowsEq = NextIRB.CreateICmpEQ(WideShadow, NextWideShadow);
952 LastBr = NextIRB.CreateCondBr(ShadowsEq, FallbackBB, FallbackBB);
956 FallbackIRB.CreateBr(Tail);
957 PHINode *Shadow = PHINode::Create(DFS.ShadowTy, 2,
"", &Tail->
front());
964 CallInst *FallbackCall = IRB.CreateCall2(
965 DFS.DFSanUnionLoadFn, ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size));
966 FallbackCall->
addAttribute(AttributeSet::ReturnIndex, Attribute::ZExt);
970 void DFSanVisitor::visitLoadInst(
LoadInst &LI) {
971 uint64_t Size = DFSF.DFS.DL->getTypeStoreSize(LI.
getType());
976 Align = DFSF.DFS.DL->getABITypeAlignment(LI.
getType());
981 Value *LoadedShadow =
984 Value *CombinedShadow = DFSF.DFS.combineShadows(LoadedShadow, PtrShadow, &LI);
985 if (CombinedShadow != DFSF.DFS.ZeroShadow)
986 DFSF.NonZeroChecks.insert(CombinedShadow);
988 DFSF.setShadow(&LI, CombinedShadow);
991 void DFSanFunction::storeShadow(
Value *Addr, uint64_t Size, uint64_t Align,
993 if (
AllocaInst *AI = dyn_cast<AllocaInst>(Addr)) {
995 AllocaShadowMap.find(AI);
996 if (i != AllocaShadowMap.end()) {
998 IRB.CreateStore(Shadow, i->second);
1003 uint64_t ShadowAlign = Align * DFS.ShadowWidth / 8;
1005 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
1006 if (Shadow == DFS.ZeroShadow) {
1007 IntegerType *ShadowTy = IntegerType::get(*DFS.Ctx, Size * DFS.ShadowWidth);
1008 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
1009 Value *ExtShadowAddr =
1010 IRB.CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowTy));
1011 IRB.CreateAlignedStore(ExtZeroShadow, ExtShadowAddr, ShadowAlign);
1015 const unsigned ShadowVecSize = 128 / DFS.ShadowWidth;
1016 uint64_t Offset = 0;
1017 if (Size >= ShadowVecSize) {
1018 VectorType *ShadowVecTy = VectorType::get(DFS.ShadowTy, ShadowVecSize);
1019 Value *ShadowVec = UndefValue::get(ShadowVecTy);
1020 for (
unsigned i = 0; i != ShadowVecSize; ++i) {
1021 ShadowVec = IRB.CreateInsertElement(
1022 ShadowVec, Shadow, ConstantInt::get(Type::getInt32Ty(*DFS.Ctx), i));
1024 Value *ShadowVecAddr =
1025 IRB.CreateBitCast(ShadowAddr, PointerType::getUnqual(ShadowVecTy));
1027 Value *CurShadowVecAddr = IRB.CreateConstGEP1_32(ShadowVecAddr, Offset);
1028 IRB.CreateAlignedStore(ShadowVec, CurShadowVecAddr, ShadowAlign);
1029 Size -= ShadowVecSize;
1031 }
while (Size >= ShadowVecSize);
1032 Offset *= ShadowVecSize;
1035 Value *CurShadowAddr = IRB.CreateConstGEP1_32(ShadowAddr, Offset);
1036 IRB.CreateAlignedStore(Shadow, CurShadowAddr, ShadowAlign);
1042 void DFSanVisitor::visitStoreInst(
StoreInst &SI) {
1058 visitOperandShadowInst(BO);
1061 void DFSanVisitor::visitCastInst(
CastInst &CI) { visitOperandShadowInst(CI); }
1063 void DFSanVisitor::visitCmpInst(
CmpInst &CI) { visitOperandShadowInst(CI); }
1066 visitOperandShadowInst(GEPI);
1070 visitOperandShadowInst(I);
1074 visitOperandShadowInst(I);
1078 visitOperandShadowInst(I);
1082 visitOperandShadowInst(I);
1086 visitOperandShadowInst(I);
1089 void DFSanVisitor::visitAllocaInst(
AllocaInst &I) {
1090 bool AllLoadsStores =
true;
1093 if (isa<LoadInst>(*i))
1096 if (
StoreInst *SI = dyn_cast<StoreInst>(*i)) {
1101 AllLoadsStores =
false;
1104 if (AllLoadsStores) {
1106 DFSF.AllocaShadowMap[&
I] = IRB.CreateAlloca(DFSF.DFS.ShadowTy);
1108 DFSF.setShadow(&I, DFSF.DFS.ZeroShadow);
1111 void DFSanVisitor::visitSelectInst(
SelectInst &I) {
1118 &I, DFSF.DFS.combineShadows(
1120 DFSF.DFS.combineShadows(TrueShadow, FalseShadow, &I), &
I));
1123 if (TrueShadow == FalseShadow) {
1124 ShadowSel = TrueShadow;
1127 SelectInst::Create(I.
getCondition(), TrueShadow, FalseShadow,
"", &
I);
1129 DFSF.setShadow(&I, DFSF.DFS.combineShadows(CondShadow, ShadowSel, &I));
1133 void DFSanVisitor::visitMemSetInst(
MemSetInst &I) {
1137 DFSF.DFS.DFSanSetLabelFn, ValShadow,
1138 IRB.CreateBitCast(I.
getDest(), Type::getInt8PtrTy(*DFSF.DFS.Ctx)),
1139 IRB.CreateZExtOrTrunc(I.
getLength(), DFSF.DFS.IntptrTy));
1144 Value *DestShadow = DFSF.DFS.getShadowAddress(I.
getDest(), &
I);
1146 Value *LenShadow = IRB.CreateMul(
1153 DFSF.DFS.ShadowWidth / 8));
1156 DFSF.DFS.ShadowWidth / 8);
1158 Type *Int8Ptr = Type::getInt8PtrTy(*DFSF.DFS.Ctx);
1159 DestShadow = IRB.CreateBitCast(DestShadow, Int8Ptr);
1160 SrcShadow = IRB.CreateBitCast(SrcShadow, Int8Ptr);
1161 IRB.CreateCall5(I.
getCalledValue(), DestShadow, SrcShadow, LenShadow,
1165 void DFSanVisitor::visitReturnInst(
ReturnInst &RI) {
1168 case DataFlowSanitizer::IA_TLS: {
1171 IRB.CreateStore(S, DFSF.getRetvalTLS());
1174 case DataFlowSanitizer::IA_Args: {
1176 Type *RT = DFSF.F->getFunctionType()->getReturnType();
1178 IRB.CreateInsertValue(UndefValue::get(RT), RI.
getReturnValue(), 0);
1180 IRB.CreateInsertValue(InsVal, DFSF.getShadow(RI.
getReturnValue()), 1);
1188 void DFSanVisitor::visitCallSite(
CallSite CS) {
1199 if (i != DFSF.DFS.UnwrappedFnMap.end()) {
1201 switch (DFSF.DFS.getWrapperKind(F)) {
1202 case DataFlowSanitizer::WK_Warning: {
1204 IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
1205 IRB.CreateGlobalStringPtr(F->
getName()));
1209 case DataFlowSanitizer::WK_Discard: {
1214 case DataFlowSanitizer::WK_Functional: {
1219 case DataFlowSanitizer::WK_Custom: {
1225 FunctionType *CustomFT = DFSF.DFS.getCustomFunctionType(FT);
1226 std::string CustomFName =
"__dfsw_";
1229 DFSF.DFS.Mod->getOrInsertFunction(CustomFName, CustomFT);
1230 if (
Function *CustomFn = dyn_cast<Function>(CustomF)) {
1231 CustomFn->copyAttributesFrom(F);
1235 CustomFn->removeAttributes(AttributeSet::FunctionIndex,
1236 DFSF.DFS.ReadOnlyNoneAttrs);
1240 std::vector<Value *> Args;
1242 CallSite::arg_iterator i = CS.
arg_begin();
1243 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n) {
1244 Type *T = (*i)->getType();
1246 if (isa<PointerType>(T) &&
1247 (ParamFT = dyn_cast<FunctionType>(
1248 cast<PointerType>(T)->getElementType()))) {
1249 std::string TName =
"dfst";
1253 Constant *T = DFSF.DFS.getOrBuildTrampolineFunction(ParamFT, TName);
1256 IRB.CreateBitCast(*i, Type::getInt8PtrTy(*DFSF.DFS.Ctx)));
1263 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1264 Args.push_back(DFSF.getShadow(*i));
1267 if (!DFSF.LabelReturnAlloca) {
1268 DFSF.LabelReturnAlloca =
1269 new AllocaInst(DFSF.DFS.ShadowTy,
"labelreturn",
1270 DFSF.F->getEntryBlock().begin());
1272 Args.push_back(DFSF.LabelReturnAlloca);
1275 CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
1280 LoadInst *LabelLoad = IRB.CreateLoad(DFSF.LabelReturnAlloca);
1281 DFSF.setShadow(CustomCI, LabelLoad);
1295 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1296 for (
unsigned i = 0, n = FT->
getNumParams(); i != n; ++i) {
1297 IRB.CreateStore(DFSF.getShadow(CS.
getArgument(i)),
1305 if (II->getNormalDest()->getSinglePredecessor()) {
1306 Next = II->getNormalDest()->begin();
1309 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DFS);
1310 Next = NewBB->
begin();
1313 Next = CS->getNextNode();
1316 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_TLS) {
1318 LoadInst *LI = NextIRB.CreateLoad(DFSF.getRetvalTLS());
1319 DFSF.SkipInsts.insert(LI);
1321 DFSF.NonZeroChecks.insert(LI);
1327 if (DFSF.DFS.getInstrumentedABI() == DataFlowSanitizer::IA_Args) {
1328 FunctionType *NewFT = DFSF.DFS.getArgsFunctionType(FT);
1330 IRB.CreateBitCast(CS.
getCalledValue(), PointerType::getUnqual(NewFT));
1331 std::vector<Value *> Args;
1334 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1338 for (
unsigned n = FT->
getNumParams(); n != 0; ++i, --n)
1339 Args.push_back(DFSF.getShadow(*i));
1343 ArrayType *VarArgArrayTy = ArrayType::get(DFSF.DFS.ShadowTy, VarArgSize);
1345 new AllocaInst(VarArgArrayTy,
"", DFSF.F->getEntryBlock().begin());
1346 Args.push_back(IRB.CreateConstGEP2_32(VarArgShadow, 0, 0));
1347 for (
unsigned n = 0; i != e; ++i, ++n) {
1348 IRB.CreateStore(DFSF.getShadow(*i),
1349 IRB.CreateConstGEP2_32(VarArgShadow, 0, n));
1356 NewCS = IRB.CreateInvoke(Func, II->getNormalDest(), II->getUnwindDest(),
1359 NewCS = IRB.CreateCall(Func, Args);
1363 *DFSF.DFS.Ctx, AttributeSet::ReturnIndex,
1365 AttributeSet::ReturnIndex)));
1370 DFSF.SkipInsts.insert(ExVal);
1373 DFSF.SkipInsts.insert(ExShadow);
1374 DFSF.setShadow(ExVal, ExShadow);
1375 DFSF.NonZeroChecks.insert(ExShadow);
1384 void DFSanVisitor::visitPHINode(
PHINode &PN) {
1389 Value *UndefShadow = UndefValue::get(DFSF.DFS.ShadowTy);
1395 DFSF.PHIFixups.push_back(std::make_pair(&PN, ShadowPN));
1396 DFSF.setShadow(&PN, ShadowPN);
Value * getValueOperand()
const Value * getCalledValue() const
void push_back(const T &Elt)
LinkageTypes getLinkage() const
IntegerType * getType() const
void ReplaceInstWithInst(BasicBlock::InstListType &BIL, BasicBlock::iterator &BI, Instruction *I)
Abstract base class of comparison instructions.
BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P)
void addIncoming(Value *V, BasicBlock *BB)
const AttributeSet & getAttributes() const
LLVM Argument representation.
Base class for instruction visitors.
void GetUnderlyingObjects(Value *V, SmallVectorImpl< Value * > &Objects, const DataLayout *TD=0, unsigned MaxLookup=6)
The main container class for the LLVM Intermediate Representation.
unsigned getNumParams() const
ConstantInt * getAlignmentCst() const
unsigned arg_size() const
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getNumOperands() const
Type::subtype_iterator param_iterator
void setCalledFunction(Value *V)
const Instruction & front() const
MDNode - a tuple of other values.
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
LoopInfoBase< BlockT, LoopT > * LI
ValTy * getArgument(unsigned ArgNo) const
Type * getPointerElementType() const
virtual void eraseFromParent()
StringRef getName() const
block_iterator block_end()
void setCallingConv(CallingConv::ID CC)
static cl::opt< std::string > ClABIListFile("dfsan-abilist", cl::desc("File listing native ABI functions and how the pass treats them"), cl::Hidden)
static cl::opt< bool > ClArgsABI("dfsan-args-abi", cl::desc("Use the argument ABI rather than the TLS ABI"), cl::Hidden)
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
Base class of casting instructions.
NodeTy * getNextNode()
Get the next node, or 0 for the list tail.
param_iterator param_end() const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void setModuleInlineAsm(StringRef Asm)
Set the module-scope inline assembly blocks.
void setName(const Twine &Name)
void copyAttributesFrom(const GlobalValue *Src)
ID
LLVM Calling Convention Representation.
AttributeSet typeIncompatible(Type *Ty, uint64_t Index)
Which attributes cannot be applied to a type.
block_iterator block_begin()
bool count(PtrType Ptr) const
count - Return true if the specified pointer is in the set.
CallingConv::ID getCallingConv() const
BasicBlock * getSuccessor(unsigned i) const
static std::string utostr(uint64_t X, bool isNeg=false)
GlobalValue * resolveAliasedGlobal(bool stopOnWeak=true)
ValTy * getCalledValue() const
void replaceAllUsesWith(Value *V)
void removeAttributes(unsigned i, AttributeSet attr)
removes the attributes from the list of attributes.
void addAttribute(unsigned i, Attribute::AttrKind attr)
addAttribute - adds the attribute to the list of attributes.
unsigned getNumIncomingValues() const
initializer< Ty > init(const Ty &Val)
unsigned getAlignment() const
alias_iterator alias_end()
LLVM Basic Block Representation.
TerminatorInst * SplitBlockAndInsertIfThen(Instruction *Cmp, bool Unreachable, MDNode *BranchWeights=0)
InstrTy * getInstruction() const
df_iterator< T > df_end(const T &G)
size_type LLVM_ATTRIBUTE_UNUSED_RESULT size() const
LLVM Constant Representation.
const Value * getCondition() const
param_iterator param_begin() const
ConstantInt * getVolatileCst() const
Value * getOperand(unsigned i) const
Value * getPointerOperand()
Integer representation type.
void setAlignment(unsigned Align)
PointerType * getPointerTo(unsigned AddrSpace=0)
const Value * getTrueValue() const
ModulePass * createDataFlowSanitizerPass(StringRef ABIListFile=StringRef(), void *(*getArgTLS)()=0, void *(*getRetValTLS)()=0)
void setSuccessor(unsigned idx, BasicBlock *NewSucc)
const std::string & getModuleInlineAsm() const
const BasicBlockListType & getBasicBlockList() const
Class for constant integers.
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
alias_iterator alias_begin()
BasicBlock * getBasicBlock() const
const BasicBlock & getEntryBlock() const
void setLinkage(LinkageTypes LT)
void splice(iterator where, iplist &L2)
void setOperand(unsigned i, Value *Val)
df_iterator< T > df_begin(const T &G)
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. Since attribute list...
LinkageTypes
An enumeration for the kinds of linkage for global values.
INITIALIZE_PASS(DataFlowSanitizer,"dfsan","DataFlowSanitizer: dynamic data flow analysis.", false, false) ModulePass *llvm
void addAttribute(unsigned i, Attribute::AttrKind attr)
adds the attribute to the list of attributes.
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
const AttributeSet & getAttributes() const
void setCallingConv(CallingConv::ID CC)
Value * getSource() const
bool isDeclaration() const
unsigned getAlignment() const
void setAttributes(const AttributeSet &PAL)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
FunctionType * getFunctionType() const
virtual void eraseFromParent()
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
void setAttributes(const AttributeSet &Attrs)
Type * getReturnType() const
LLVM Value Representation.
const ArgumentListType & getArgumentList() const
CallInst * CreateCall(Value *Callee, const Twine &Name="")
const Value * getFalseValue() const
bool removeUnreachableBlocks(Function &F)
Remove all blocks that can not be reached from the function's entry.
CallingConv::ID getCallingConv() const
Value * getPointerOperand()
const BasicBlock * getParent() const
LLVMContext & getContext() const
bool isVoidTy() const
isVoidTy - Return true if this is 'void'.
FunTy * getCalledFunction() const