151 Type *GType =
G.getValueType();
154 if (!SGType->isLiteral())
155 return SGType->getName();
157 return "<unknown type>";
166struct MemoryMapParams {
212 std::unique_ptr<SpecialCaseList> SCL;
215 DFSanABIList() =
default;
217 void set(std::unique_ptr<SpecialCaseList>
List) { SCL = std::move(
List); }
221 bool isIn(
const Function &
F, StringRef Category)
const {
222 return isIn(*
F.getParent(), Category) ||
223 SCL->inSection(
"dataflow",
"fun",
F.getName(), Category);
230 bool isIn(
const GlobalAlias &GA, StringRef Category)
const {
235 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
237 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
243 bool isIn(
const Module &M, StringRef Category)
const {
244 return SCL->inSection(
"dataflow",
"src",
M.getModuleIdentifier(), Category);
251struct TransformedFunction {
252 TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
253 const std::vector<unsigned> &ArgumentIndexMapping,
254 AttributeList &NewParamAttrs)
255 : OriginalType(OriginalType), TransformedType(TransformedType),
256 ArgumentIndexMapping(ArgumentIndexMapping),
257 NewParamAttrs(NewParamAttrs) {}
260 TransformedFunction(
const TransformedFunction &) =
delete;
261 TransformedFunction &operator=(
const TransformedFunction &) =
delete;
264 TransformedFunction(TransformedFunction &&) =
default;
265 TransformedFunction &operator=(TransformedFunction &&) =
default;
268 FunctionType *OriginalType;
271 FunctionType *TransformedType;
278 std::vector<unsigned> ArgumentIndexMapping;
282 AttributeList NewParamAttrs;
289transformFunctionAttributes(
const TransformedFunction &TransformedFunction,
293 std::vector<llvm::AttributeSet> ArgumentAttributes(
294 TransformedFunction.TransformedType->getNumParams());
299 for (
unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
301 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[
I];
302 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttrs(
I);
306 for (
unsigned I = TransformedFunction.OriginalType->getNumParams(),
307 IE = CallSiteAttrs.getNumAttrSets();
309 ArgumentAttributes.push_back(CallSiteAttrs.getParamAttrs(
I));
312 return AttributeList::get(Ctx, CallSiteAttrs.getFnAttrs(),
313 CallSiteAttrs.getRetAttrs(),
317class DataFlowSanitizer {
318 friend struct DFSanFunction;
319 friend class DFSanVisitor;
321 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
323 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
348 const InstrumentationOptions &Opts;
352 IntegerType *OriginTy;
354 ConstantInt *ZeroOrigin;
356 IntegerType *PrimitiveShadowTy;
358 IntegerType *IntptrTy;
359 ConstantInt *ZeroPrimitiveShadow;
365 FunctionType *DFSanUnionLoadFnTy;
366 FunctionType *DFSanLoadLabelAndOriginFnTy;
367 FunctionType *DFSanUnimplementedFnTy;
368 FunctionType *DFSanWrapperExternWeakNullFnTy;
369 FunctionType *DFSanSetLabelFnTy;
370 FunctionType *DFSanNonzeroLabelFnTy;
371 FunctionType *DFSanVarargWrapperFnTy;
372 FunctionType *DFSanConditionalCallbackFnTy;
373 FunctionType *DFSanConditionalCallbackOriginFnTy;
374 FunctionType *DFSanReachesFunctionCallbackFnTy;
375 FunctionType *DFSanReachesFunctionCallbackOriginFnTy;
376 FunctionType *DFSanCmpCallbackFnTy;
377 FunctionType *DFSanLoadStoreCallbackFnTy;
378 FunctionType *DFSanMemTransferCallbackFnTy;
379 FunctionType *DFSanChainOriginFnTy;
380 FunctionType *DFSanChainOriginIfTaintedFnTy;
381 FunctionType *DFSanMemOriginTransferFnTy;
382 FunctionType *DFSanMemShadowOriginTransferFnTy;
383 FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
384 FunctionType *DFSanMaybeStoreOriginFnTy;
385 FunctionCallee DFSanUnionLoadFn;
386 FunctionCallee DFSanLoadLabelAndOriginFn;
387 FunctionCallee DFSanUnimplementedFn;
388 FunctionCallee DFSanWrapperExternWeakNullFn;
389 FunctionCallee DFSanSetLabelFn;
390 FunctionCallee DFSanNonzeroLabelFn;
391 FunctionCallee DFSanVarargWrapperFn;
392 FunctionCallee DFSanLoadCallbackFn;
393 FunctionCallee DFSanStoreCallbackFn;
394 FunctionCallee DFSanMemTransferCallbackFn;
395 FunctionCallee DFSanConditionalCallbackFn;
396 FunctionCallee DFSanConditionalCallbackOriginFn;
397 FunctionCallee DFSanReachesFunctionCallbackFn;
398 FunctionCallee DFSanReachesFunctionCallbackOriginFn;
399 FunctionCallee DFSanCmpCallbackFn;
400 FunctionCallee DFSanChainOriginFn;
401 FunctionCallee DFSanChainOriginIfTaintedFn;
402 FunctionCallee DFSanMemOriginTransferFn;
403 FunctionCallee DFSanMemShadowOriginTransferFn;
404 FunctionCallee DFSanMemShadowOriginConditionalExchangeFn;
405 FunctionCallee DFSanMaybeStoreOriginFn;
406 SmallPtrSet<Value *, 16> DFSanRuntimeFunctions;
407 MDNode *ColdCallWeights;
408 MDNode *OriginStoreWeights;
409 DFSanABIList ABIList;
410 DenseMap<Value *, Function *> UnwrappedFnMap;
411 AttributeMask ReadOnlyNoneAttrs;
412 StringSet<> CombineTaintLookupTableNames;
416 const MemoryMapParams *MapParams;
421 Value *ShadowOffset);
422 std::pair<Value *, Value *> getShadowOriginAddress(
Value *Addr,
426 bool isInstrumented(
const GlobalAlias *GA);
427 bool isForceZeroLabels(
const Function *
F);
428 TransformedFunction getCustomFunctionType(FunctionType *
T,
429 TargetLibraryInfo &
TLI);
431 void addGlobalNameSuffix(GlobalValue *GV);
435 FunctionType *NewFT);
436 void initializeCallbackFunctions(
Module &M);
437 void initializeRuntimeFunctions(
Module &M);
438 bool initializeModule(
Module &M);
450 bool shouldTrackOrigins();
462 bool isZeroShadow(
Value *
V);
476 DataFlowSanitizer(
const InstrumentationOptions &Opts,
477 const std::vector<std::string> &ABIListFiles,
478 IntrusiveRefCntPtr<vfs::FileSystem> FS);
481 llvm::function_ref<TargetLibraryInfo &(
Function &)> GetTLI);
484struct DFSanFunction {
485 const InstrumentationOptions &Opts;
486 DataFlowSanitizer &DFS;
490 bool IsForceZeroLabels;
491 TargetLibraryInfo &TLI;
492 AllocaInst *LabelReturnAlloca =
nullptr;
493 AllocaInst *OriginReturnAlloca =
nullptr;
494 DenseMap<Value *, Value *> ValShadowMap;
495 DenseMap<Value *, Value *> ValOriginMap;
496 DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
497 DenseMap<AllocaInst *, AllocaInst *> AllocaOriginMap;
499 struct PHIFixupElement {
504 std::vector<PHIFixupElement> PHIFixups;
506 DenseSet<Instruction *> SkipInsts;
507 std::vector<Value *> NonZeroChecks;
509 struct CachedShadow {
514 DenseMap<std::pair<Value *, Value *>, CachedShadow> CachedShadows;
519 DenseMap<Value *, Value *> CachedCollapsedShadows;
520 DenseMap<Value *, std::set<Value *>> ShadowElements;
522 DFSanFunction(DataFlowSanitizer &DFS,
Function *F,
bool IsNativeABI,
523 bool IsForceZeroLabels, TargetLibraryInfo &TLI)
524 : Opts(DFS.Opts), DFS(DFS), F(F), IsNativeABI(IsNativeABI),
525 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
543 Value *getRetvalOriginTLS();
546 void setOrigin(Instruction *
I,
Value *Origin);
548 Value *combineOperandOrigins(Instruction *Inst);
555 Value *combineOrigins(
const std::vector<Value *> &Shadows,
556 const std::vector<Value *> &Origins,
560 void setShadow(Instruction *
I,
Value *Shadow);
568 Value *combineOperandShadows(Instruction *Inst);
582 Align InstAlignment,
Value *PrimitiveShadow,
604 Align getShadowAlign(Align InstAlignment);
608 void addConditionalCallbacksIfEnabled(Instruction &
I,
Value *Condition);
612 void addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB, Instruction &
I,
615 bool isLookupTableConstant(
Value *
P);
620 template <
class AggregateType>
621 Value *collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
627 Value *getShadowForTLSArgument(Argument *
A);
630 std::pair<Value *, Value *>
632 Align ShadowAlign, Align OriginAlign,
Value *FirstOrigin,
635 Align getOriginAlign(Align InstAlignment);
646 bool useCallbackLoadLabelAndOrigin(
uint64_t Size, Align InstAlignment);
662 uint64_t StoreOriginSize, Align Alignment);
671 Align InstAlignment);
676 bool shouldInstrumentWithCall();
682 std::pair<Value *, Value *>
686 int NumOriginStores = 0;
689class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
693 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
695 const DataLayout &getDataLayout()
const {
696 return DFSF.F->getDataLayout();
700 void visitInstOperands(Instruction &
I);
702 void visitUnaryOperator(UnaryOperator &UO);
703 void visitBinaryOperator(BinaryOperator &BO);
704 void visitBitCastInst(BitCastInst &BCI);
705 void visitCastInst(CastInst &CI);
706 void visitCmpInst(CmpInst &CI);
707 void visitLandingPadInst(LandingPadInst &LPI);
708 void visitGetElementPtrInst(GetElementPtrInst &GEPI);
709 void visitLoadInst(LoadInst &LI);
710 void visitStoreInst(StoreInst &SI);
711 void visitAtomicRMWInst(AtomicRMWInst &
I);
712 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I);
713 void visitReturnInst(ReturnInst &RI);
714 void visitLibAtomicLoad(CallBase &CB);
715 void visitLibAtomicStore(CallBase &CB);
716 void visitLibAtomicExchange(CallBase &CB);
717 void visitLibAtomicCompareExchange(CallBase &CB);
718 void visitCallBase(CallBase &CB);
719 void visitPHINode(PHINode &PN);
720 void visitExtractElementInst(ExtractElementInst &
I);
721 void visitInsertElementInst(InsertElementInst &
I);
722 void visitShuffleVectorInst(ShuffleVectorInst &
I);
723 void visitExtractValueInst(ExtractValueInst &
I);
724 void visitInsertValueInst(InsertValueInst &
I);
725 void visitAllocaInst(AllocaInst &
I);
726 void visitSelectInst(SelectInst &
I);
727 void visitMemSetInst(MemSetInst &
I);
728 void visitMemTransferInst(MemTransferInst &
I);
729 void visitCondBrInst(CondBrInst &BR);
730 void visitSwitchInst(SwitchInst &SW);
733 void visitCASOrRMW(Align InstAlignment, Instruction &
I);
736 bool visitWrappedCallBase(
Function &
F, CallBase &CB);
739 void visitInstOperandOrigins(Instruction &
I);
741 void addShadowArguments(
Function &
F, CallBase &CB, std::vector<Value *> &Args,
744 void addOriginArguments(
Function &
F, CallBase &CB, std::vector<Value *> &Args,
751bool LibAtomicFunction(
const Function &
F) {
757 if (!
F.hasName() ||
F.isVarArg())
759 switch (
F.arg_size()) {
761 return F.getName() ==
"__atomic_load" ||
F.getName() ==
"__atomic_store";
763 return F.getName() ==
"__atomic_exchange";
765 return F.getName() ==
"__atomic_compare_exchange";
773DataFlowSanitizer::DataFlowSanitizer(
774 const InstrumentationOptions &Opts,
775 const std::vector<std::string> &ABIListFiles,
778 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
783 Opts.dfsan_combine_taint_lookup_table);
790 AttributeList NewParamAttrs;
791 Attribute::AttrKind ShadowParamExtAttr =
792 TLI.getExtAttrForI8Param(
false);
793 Attribute::AttrKind OriginParamExtAttr =
794 TLI.getExtAttrForI32Param(
false);
800 std::vector<unsigned> ArgumentIndexMapping;
801 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
802 Type *ParamType =
T->getParamType(
I);
803 ArgumentIndexMapping.push_back(ArgTypes.
size());
806 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
807 NewParamAttrs = NewParamAttrs.maybeAddParamAttribute(*Ctx, ArgTypes.
size(),
812 ArgTypes.
push_back(PrimitiveShadowPtrTy);
813 Type *RetType =
T->getReturnType();
815 ArgTypes.
push_back(PrimitiveShadowPtrTy);
817 if (shouldTrackOrigins()) {
818 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
819 NewParamAttrs = NewParamAttrs.maybeAddParamAttribute(
820 *Ctx, ArgTypes.
size(), OriginParamExtAttr);
829 return TransformedFunction(
830 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
831 ArgumentIndexMapping, NewParamAttrs);
834bool DataFlowSanitizer::isZeroShadow(
Value *
V) {
845bool DataFlowSanitizer::hasLoadSizeForFastPath(
uint64_t Size) {
847 return ShadowSize % 8 == 0 || ShadowSize == 4;
850bool DataFlowSanitizer::shouldTrackOrigins() {
851 return Opts.dfsan_track_origins;
854Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
856 return ZeroPrimitiveShadow;
857 Type *ShadowTy = getShadowTy(OrigTy);
862 return getZeroShadow(
V->getType());
872 for (
unsigned Idx = 0; Idx < AT->getNumElements(); Idx++) {
875 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
882 for (
unsigned Idx = 0; Idx < ST->getNumElements(); Idx++) {
885 Shadow, Indices, ST->getElementType(Idx), PrimitiveShadow, IRB);
893bool DFSanFunction::shouldInstrumentWithCall() {
894 return Opts.dfsan_instrument_with_call_threshold >= 0 &&
895 NumOriginStores >= Opts.dfsan_instrument_with_call_threshold;
898Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
900 Type *ShadowTy = DFS.getShadowTy(
T);
903 return PrimitiveShadow;
905 if (DFS.isZeroShadow(PrimitiveShadow))
906 return DFS.getZeroShadow(ShadowTy);
909 SmallVector<unsigned, 4> Indices;
912 PrimitiveShadow, IRB);
915 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
919template <
class AggregateType>
920Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
922 if (!AT->getNumElements())
923 return DFS.ZeroPrimitiveShadow;
926 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
928 for (
unsigned Idx = 1;
Idx < AT->getNumElements();
Idx++) {
930 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
931 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
936Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
942 return collapseAggregateShadow<>(AT, Shadow, IRB);
944 return collapseAggregateShadow<>(ST, Shadow, IRB);
948Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
955 Value *&CS = CachedCollapsedShadows[Shadow];
960 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
962 CS = PrimitiveShadow;
963 return PrimitiveShadow;
966void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &
I,
968 if (!Opts.dfsan_conditional_callbacks) {
972 Value *CondShadow = getShadow(Condition);
974 if (DFS.shouldTrackOrigins()) {
975 Value *CondOrigin = getOrigin(Condition);
976 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
977 {CondShadow, CondOrigin});
980 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
985void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
988 if (!Opts.dfsan_reaches_function_callbacks) {
991 const DebugLoc &dbgloc =
I.getDebugLoc();
992 Value *DataShadow = collapseToPrimitiveShadow(getShadow(
Data), IRB);
996 if (dbgloc.
get() ==
nullptr) {
997 CILine = llvm::ConstantInt::get(
I.getContext(), llvm::APInt(32, 0));
999 I.getFunction()->getParent()->getSourceFileName());
1001 CILine = llvm::ConstantInt::get(
I.getContext(),
1002 llvm::APInt(32, dbgloc.
getLine()));
1010 std::vector<Value *>
args;
1012 Attribute::AttrKind I32ParamExtAttr =
1013 TLI.getExtAttrForI32Param(
false);
1014 if (DFS.shouldTrackOrigins()) {
1016 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1017 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1021 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1029Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1031 return PrimitiveShadowTy;
1033 return PrimitiveShadowTy;
1035 return PrimitiveShadowTy;
1037 return ArrayType::get(getShadowTy(AT->getElementType()),
1038 AT->getNumElements());
1041 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1042 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1045 return PrimitiveShadowTy;
1048Type *DataFlowSanitizer::getShadowTy(
Value *
V) {
1049 return getShadowTy(
V->getType());
1052bool DataFlowSanitizer::initializeModule(
Module &M) {
1053 Triple TargetTriple(
M.getTargetTriple());
1054 const DataLayout &
DL =
M.getDataLayout();
1058 switch (TargetTriple.getArch()) {
1076 Ctx = &
M.getContext();
1077 Int8Ptr = PointerType::getUnqual(*Ctx);
1079 OriginPtrTy = PointerType::getUnqual(*Ctx);
1081 PrimitiveShadowPtrTy = PointerType::getUnqual(*Ctx);
1082 IntptrTy =
DL.getIntPtrType(*Ctx);
1086 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1087 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1089 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1090 DFSanLoadLabelAndOriginFnTy =
1093 DFSanUnimplementedFnTy = FunctionType::get(
1094 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx),
false);
1095 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1096 DFSanWrapperExternWeakNullFnTy =
1097 FunctionType::get(Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1099 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1100 PointerType::getUnqual(*Ctx), IntptrTy};
1101 DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
1102 DFSanSetLabelArgs,
false);
1103 DFSanNonzeroLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx), {},
1105 DFSanVarargWrapperFnTy = FunctionType::get(
1106 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx),
false);
1107 DFSanConditionalCallbackFnTy =
1108 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1110 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1111 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1112 Type::getVoidTy(*Ctx), DFSanConditionalCallbackOriginArgs,
1114 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1116 DFSanReachesFunctionCallbackFnTy =
1117 FunctionType::get(Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1119 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1120 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1121 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1122 Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackOriginArgs,
1124 DFSanCmpCallbackFnTy =
1125 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1127 DFSanChainOriginFnTy =
1128 FunctionType::get(OriginTy, OriginTy,
false);
1129 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1130 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1131 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1133 Int8Ptr, IntptrTy, OriginTy};
1134 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1135 Type::getVoidTy(*Ctx), DFSanMaybeStoreOriginArgs,
false);
1136 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1137 DFSanMemOriginTransferFnTy = FunctionType::get(
1138 Type::getVoidTy(*Ctx), DFSanMemOriginTransferArgs,
false);
1139 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1140 DFSanMemShadowOriginTransferFnTy =
1141 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1143 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1145 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1146 Type::getVoidTy(*Ctx), DFSanMemShadowOriginConditionalExchangeArgs,
1148 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1149 DFSanLoadStoreCallbackFnTy =
1150 FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs,
1152 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1153 DFSanMemTransferCallbackFnTy =
1154 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1157 ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1158 OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1162bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1163 return !ABIList.isIn(*
F,
"uninstrumented");
1166bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1167 return !ABIList.isIn(*GA,
"uninstrumented");
1170bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1171 return ABIList.isIn(*
F,
"force_zero_labels");
1174DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(
Function *
F) {
1175 if (ABIList.isIn(*
F,
"functional"))
1176 return WK_Functional;
1177 if (ABIList.isIn(*
F,
"discard"))
1179 if (ABIList.isIn(*
F,
"custom"))
1185void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) {
1186 if (!Opts.dfsan_add_global_name_suffix)
1189 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1197 for (Module::GlobalAsmFragment &Frag :
1199 std::string SearchStr =
".symver " + GVName +
",";
1200 size_t Pos = Frag.Asm.find(SearchStr);
1201 if (Pos != std::string::npos) {
1202 Frag.Asm.replace(Pos, SearchStr.size(),
1203 ".symver " + GVName + Suffix +
",");
1204 Pos = Frag.Asm.find(
'@');
1206 if (Pos == std::string::npos)
1209 Frag.Asm.replace(Pos, 1, Suffix +
"@");
1214void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1224 std::vector<Value *>
Args;
1227 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1232DataFlowSanitizer::buildWrapperFunction(
Function *
F, StringRef NewFName,
1234 FunctionType *NewFT) {
1235 FunctionType *FT =
F->getFunctionType();
1237 NewFName,
F->getParent());
1240 NewFT->getReturnType(), NewF->
getAttributes().getRetAttrs()));
1243 if (
F->isVarArg()) {
1246 IRBuilder<>(BB).CreateGlobalString(
F->getName()),
"", BB);
1247 new UnreachableInst(*Ctx, BB);
1249 auto ArgIt = pointer_iterator<Argument *>(NewF->
arg_begin());
1250 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1253 if (FT->getReturnType()->isVoidTy())
1263void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1264 LLVMContext &
C =
M.getContext();
1265 Attribute::AttrKind I8ParamExtAttr =
1267 Attribute::AttrKind I32ParamExtAttr =
1268 TargetLibraryInfo::getExtAttrForI32Param(
M.getTargetTriple(),
1272 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1273 AL =
AL.addFnAttribute(
1275 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1277 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1281 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1282 AL =
AL.addFnAttribute(
1284 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1285 DFSanLoadLabelAndOriginFn =
Mod->getOrInsertFunction(
1286 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1288 DFSanUnimplementedFn =
1289 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
1290 DFSanWrapperExternWeakNullFn =
Mod->getOrInsertFunction(
1291 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1294 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1295 AL =
AL.maybeAddParamAttribute(
M.getContext(), 1, I32ParamExtAttr);
1297 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
1299 DFSanNonzeroLabelFn =
1300 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1301 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
1302 DFSanVarargWrapperFnTy);
1305 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I32ParamExtAttr);
1306 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1307 DFSanChainOriginFn =
Mod->getOrInsertFunction(
"__dfsan_chain_origin",
1308 DFSanChainOriginFnTy, AL);
1312 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1313 AL =
AL.maybeAddParamAttribute(
M.getContext(), 1, I32ParamExtAttr);
1314 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1315 DFSanChainOriginIfTaintedFn =
Mod->getOrInsertFunction(
1316 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1318 DFSanMemOriginTransferFn =
Mod->getOrInsertFunction(
1319 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1321 DFSanMemShadowOriginTransferFn =
Mod->getOrInsertFunction(
1322 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1326 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1327 DFSanMemShadowOriginConditionalExchangeFn =
Mod->getOrInsertFunction(
1328 "__dfsan_mem_shadow_origin_conditional_exchange",
1329 DFSanMemShadowOriginConditionalExchangeFnTy, AL);
1334 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1335 AL =
AL.maybeAddParamAttribute(
M.getContext(), 3, I32ParamExtAttr);
1336 DFSanMaybeStoreOriginFn =
Mod->getOrInsertFunction(
1337 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1340 DFSanRuntimeFunctions.
insert(
1342 DFSanRuntimeFunctions.
insert(
1344 DFSanRuntimeFunctions.
insert(
1346 DFSanRuntimeFunctions.
insert(
1348 DFSanRuntimeFunctions.
insert(
1350 DFSanRuntimeFunctions.
insert(
1352 DFSanRuntimeFunctions.
insert(
1354 DFSanRuntimeFunctions.
insert(
1356 DFSanRuntimeFunctions.
insert(
1358 DFSanRuntimeFunctions.
insert(
1360 DFSanRuntimeFunctions.
insert(
1362 DFSanRuntimeFunctions.
insert(
1364 DFSanRuntimeFunctions.
insert(
1366 DFSanRuntimeFunctions.
insert(
1368 DFSanRuntimeFunctions.
insert(
1370 DFSanRuntimeFunctions.
insert(
1372 DFSanRuntimeFunctions.
insert(
1374 DFSanRuntimeFunctions.
insert(
1376 DFSanRuntimeFunctions.
insert(
1378 DFSanRuntimeFunctions.
insert(
1379 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1381 DFSanRuntimeFunctions.
insert(
1386void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1387 Attribute::AttrKind I8ParamExtAttr =
1389 Attribute::AttrKind I32ParamExtAttr =
1390 TargetLibraryInfo::getExtAttrForI32Param(
M.getTargetTriple(),
1394 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1395 DFSanLoadCallbackFn =
Mod->getOrInsertFunction(
1396 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1400 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1401 DFSanStoreCallbackFn =
Mod->getOrInsertFunction(
1402 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1404 DFSanMemTransferCallbackFn =
Mod->getOrInsertFunction(
1405 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1408 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1409 DFSanCmpCallbackFn =
Mod->getOrInsertFunction(
"__dfsan_cmp_callback",
1410 DFSanCmpCallbackFnTy, AL);
1414 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1415 DFSanConditionalCallbackFn =
Mod->getOrInsertFunction(
1416 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1420 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1421 AL =
AL.maybeAddParamAttribute(
M.getContext(), 1, I32ParamExtAttr);
1422 DFSanConditionalCallbackOriginFn =
1423 Mod->getOrInsertFunction(
"__dfsan_conditional_callback_origin",
1424 DFSanConditionalCallbackOriginFnTy, AL);
1428 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1429 AL =
AL.maybeAddParamAttribute(
M.getContext(), 2, I32ParamExtAttr);
1430 DFSanReachesFunctionCallbackFn =
1431 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback",
1432 DFSanReachesFunctionCallbackFnTy, AL);
1436 AL =
AL.maybeAddParamAttribute(
M.getContext(), 0, I8ParamExtAttr);
1437 AL =
AL.maybeAddParamAttribute(
M.getContext(), 1, I32ParamExtAttr);
1438 AL =
AL.maybeAddParamAttribute(
M.getContext(), 3, I32ParamExtAttr);
1439 DFSanReachesFunctionCallbackOriginFn =
1440 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback_origin",
1441 DFSanReachesFunctionCallbackOriginFnTy, AL);
1445bool DataFlowSanitizer::runImpl(
1446 Module &M, llvm::function_ref<TargetLibraryInfo &(
Function &)> GetTLI) {
1447 initializeModule(M);
1449 if (ABIList.isIn(M,
"skip"))
1452 const unsigned InitialGlobalSize =
M.global_size();
1453 const unsigned InitialModuleSize =
M.size();
1457 auto GetOrInsertGlobal = [
this, &
Changed](StringRef
Name,
1458 Type *Ty) -> Constant * {
1459 GlobalVariable *
G =
Mod->getOrInsertGlobal(Name, Ty);
1460 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1461 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1467 GetOrInsertGlobal(
"__dfsan_arg_tls",
1468 ArrayType::get(Type::getInt64Ty(*Ctx),
ArgTLSSize / 8));
1469 RetvalTLS = GetOrInsertGlobal(
1470 "__dfsan_retval_tls",
1472 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1473 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1474 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1476 (void)
Mod->getOrInsertGlobal(
"__dfsan_track_origins", OriginTy, [&] {
1478 return new GlobalVariable(
1479 M, OriginTy, true, GlobalValue::WeakODRLinkage,
1480 ConstantInt::getSigned(OriginTy, Opts.dfsan_track_origins),
1481 "__dfsan_track_origins");
1484 initializeCallbackFunctions(M);
1485 initializeRuntimeFunctions(M);
1487 std::vector<Function *> FnsToInstrument;
1488 SmallPtrSet<Function *, 2> FnsWithNativeABI;
1489 SmallPtrSet<Function *, 2> FnsWithForceZeroLabel;
1490 SmallPtrSet<Constant *, 1> PersonalityFns;
1492 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1493 !LibAtomicFunction(
F) &&
1494 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1495 FnsToInstrument.push_back(&
F);
1496 if (
F.hasPersonalityFn())
1497 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1500 if (Opts.dfsan_ignore_personality_routine) {
1501 for (
auto *
C : PersonalityFns) {
1504 if (!isInstrumented(
F))
1518 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1519 if (GAInst && FInst) {
1520 addGlobalNameSuffix(&GA);
1521 }
else if (GAInst != FInst) {
1526 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1530 FnsToInstrument.push_back(NewF);
1539 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1540 FE = FnsToInstrument.end();
1543 FunctionType *FT =
F.getFunctionType();
1545 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1546 FT->getReturnType()->isVoidTy());
1548 if (isInstrumented(&
F)) {
1549 if (isForceZeroLabels(&
F))
1550 FnsWithForceZeroLabel.
insert(&
F);
1555 addGlobalNameSuffix(&
F);
1556 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1564 F.hasLocalLinkage() ?
F.getLinkage()
1567 Function *NewF = buildWrapperFunction(
1569 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1570 std::string(
F.getName()),
1571 WrapperLinkage, FT);
1591 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1592 User *Usr =
U.getUser();
1594 if (
I->getOpcode() == Instruction::ICmp) {
1600 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1602 UnwrappedFnMap[NewF] = &
F;
1605 if (!
F.isDeclaration()) {
1615 size_t N = FI - FnsToInstrument.begin(),
1616 Count = FE - FnsToInstrument.begin();
1617 FnsToInstrument.push_back(&
F);
1618 FI = FnsToInstrument.begin() +
N;
1619 FE = FnsToInstrument.begin() +
Count;
1623 }
else if (FT->isVarArg()) {
1624 UnwrappedFnMap[&
F] = &
F;
1630 if (!
F ||
F->isDeclaration())
1635 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1636 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1641 if (Opts.dfsan_reaches_function_callbacks && !UnwrappedFnMap.
count(
F)) {
1643 Instruction *FirstOrigInst = &
F->getEntryBlock().front();
1646 for (
auto &FArg :
F->args()) {
1648 Value *FArgShadow = DFSF.getShadow(&FArg);
1649 if (isZeroShadow(FArgShadow))
1652 Next = FArgShadowInst->getNextNode();
1654 if (shouldTrackOrigins()) {
1655 if (Instruction *Origin =
1659 if (
Next->comesBefore(OriginNext)) {
1665 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *
Next, &FArg);
1670 for (Instruction &
I :
F->getEntryBlock()) {
1671 if (&
I == FirstOrigInst)
1681 for (BasicBlock *BB : BBList) {
1691 if (!DFSF.SkipInsts.
count(Inst))
1692 DFSanVisitor(DFSF).visit(Inst);
1703 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1704 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1706 P.ShadowPhi->setIncomingValue(
1707 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1709 P.OriginPhi->setIncomingValue(
1710 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1718 if (Opts.dfsan_debug_nonzero_labels) {
1719 for (
Value *
V : DFSF.NonZeroChecks) {
1722 Pos = std::next(
I->getIterator());
1726 Pos = std::next(Pos->getIterator());
1728 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(
V, Pos);
1730 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1732 Ne, Pos,
false, ColdCallWeights));
1734 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1740 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1752Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1756 ArgNo,
"_dfsarg_o");
1760 assert(DFS.shouldTrackOrigins());
1762 return DFS.ZeroOrigin;
1763 Value *&Origin = ValOriginMap[
V];
1767 return DFS.ZeroOrigin;
1768 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1769 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1771 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1772 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1775 Origin = DFS.ZeroOrigin;
1778 Origin = DFS.ZeroOrigin;
1784void DFSanFunction::setOrigin(Instruction *
I,
Value *Origin) {
1785 if (!DFS.shouldTrackOrigins())
1789 ValOriginMap[
I] = Origin;
1792Value *DFSanFunction::getShadowForTLSArgument(Argument *
A) {
1793 unsigned ArgOffset = 0;
1794 const DataLayout &
DL =
F->getDataLayout();
1795 for (
auto &FArg :
F->args()) {
1796 if (!FArg.getType()->isSized()) {
1802 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1815 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1820 return DFS.getZeroShadow(
A);
1825 return DFS.getZeroShadow(
V);
1826 if (IsForceZeroLabels)
1827 return DFS.getZeroShadow(
V);
1828 Value *&Shadow = ValShadowMap[
V];
1832 return DFS.getZeroShadow(
V);
1833 Shadow = getShadowForTLSArgument(
A);
1834 NonZeroChecks.push_back(Shadow);
1836 Shadow = DFS.getZeroShadow(
V);
1842void DFSanFunction::setShadow(Instruction *
I,
Value *Shadow) {
1844 ValShadowMap[
I] = Shadow;
1852 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
1855 uint64_t AndMask = MapParams->AndMask;
1858 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1860 uint64_t XorMask = MapParams->XorMask;
1862 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1866std::pair<Value *, Value *>
1867DataFlowSanitizer::getShadowOriginAddress(
Value *Addr, Align InstAlignment,
1871 Value *ShadowOffset = getShadowOffset(Addr, IRB);
1872 Value *ShadowLong = ShadowOffset;
1873 uint64_t ShadowBase = MapParams->ShadowBase;
1874 if (ShadowBase != 0) {
1876 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1879 Value *OriginPtr =
nullptr;
1880 if (shouldTrackOrigins()) {
1881 Value *OriginLong = ShadowOffset;
1882 uint64_t OriginBase = MapParams->OriginBase;
1883 if (OriginBase != 0)
1885 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1891 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1895 return std::make_pair(ShadowPtr, OriginPtr);
1898Value *DataFlowSanitizer::getShadowAddress(
Value *Addr,
1900 Value *ShadowOffset) {
1905Value *DataFlowSanitizer::getShadowAddress(
Value *Addr,
1908 Value *ShadowAddr = getShadowOffset(Addr, IRB);
1909 uint64_t ShadowBase = MapParams->ShadowBase;
1910 if (ShadowBase != 0)
1912 IRB.
CreateAdd(ShadowAddr, ConstantInt::get(IntptrTy, ShadowBase));
1913 return getShadowAddress(Addr, Pos, ShadowAddr);
1918 Value *PrimitiveValue = combineShadows(
V1, V2, Pos);
1919 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1926 if (DFS.isZeroShadow(
V1))
1927 return collapseToPrimitiveShadow(V2, Pos);
1928 if (DFS.isZeroShadow(V2))
1929 return collapseToPrimitiveShadow(
V1, Pos);
1931 return collapseToPrimitiveShadow(
V1, Pos);
1933 auto V1Elems = ShadowElements.
find(
V1);
1934 auto V2Elems = ShadowElements.
find(V2);
1935 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1937 return collapseToPrimitiveShadow(
V1, Pos);
1940 return collapseToPrimitiveShadow(V2, Pos);
1942 }
else if (V1Elems != ShadowElements.
end()) {
1943 if (V1Elems->second.count(V2))
1944 return collapseToPrimitiveShadow(
V1, Pos);
1945 }
else if (V2Elems != ShadowElements.
end()) {
1946 if (V2Elems->second.count(
V1))
1947 return collapseToPrimitiveShadow(V2, Pos);
1950 auto Key = std::make_pair(
V1, V2);
1953 CachedShadow &CCS = CachedShadows[
Key];
1954 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
1958 Value *PV1 = collapseToPrimitiveShadow(
V1, Pos);
1959 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
1962 CCS.Block = Pos->getParent();
1963 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
1965 std::set<Value *> UnionElems;
1966 if (V1Elems != ShadowElements.
end()) {
1967 UnionElems = V1Elems->second;
1969 UnionElems.insert(
V1);
1971 if (V2Elems != ShadowElements.
end()) {
1972 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
1974 UnionElems.insert(V2);
1976 ShadowElements[CCS.Shadow] = std::move(UnionElems);
1984Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
1986 return DFS.getZeroShadow(Inst);
1990 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
1993 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
1997void DFSanVisitor::visitInstOperands(Instruction &
I) {
1998 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
1999 DFSF.setShadow(&
I, CombinedShadow);
2000 visitInstOperandOrigins(
I);
2003Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2004 const std::vector<Value *> &Origins,
2006 ConstantInt *
Zero) {
2007 assert(Shadows.size() == Origins.size());
2008 size_t Size = Origins.size();
2010 return DFS.ZeroOrigin;
2011 Value *Origin =
nullptr;
2013 Zero = DFS.ZeroPrimitiveShadow;
2014 for (
size_t I = 0;
I !=
Size; ++
I) {
2015 Value *OpOrigin = Origins[
I];
2017 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2023 Value *OpShadow = Shadows[
I];
2024 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2029 return Origin ? Origin : DFS.ZeroOrigin;
2032Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2034 std::vector<Value *> Shadows(
Size);
2035 std::vector<Value *> Origins(
Size);
2036 for (
unsigned I = 0;
I !=
Size; ++
I) {
2040 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2043void DFSanVisitor::visitInstOperandOrigins(Instruction &
I) {
2044 if (!DFSF.DFS.shouldTrackOrigins())
2046 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2047 DFSF.setOrigin(&
I, CombinedOrigin);
2050Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2052 Opts.dfsan_preserve_alignment ? InstAlignment :
Align(1);
2056Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2061bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2063 if (GV->isConstant() && GV->
hasName())
2064 return DFS.CombineTaintLookupTableNames.
count(GV->
getName());
2069bool DFSanFunction::useCallbackLoadLabelAndOrigin(
uint64_t Size,
2070 Align InstAlignment) {
2073 if (Opts.dfsan_track_origins == 2)
2094 Value **OriginAddr) {
2098 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2102std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2105 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2106 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2108 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2111 std::vector<Value *> Shadows;
2112 std::vector<Value *> Origins;
2125 Type *WideShadowTy =
2126 ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) :
Type::getInt64Ty(*DFS.Ctx);
2130 Value *CombinedWideShadow =
2134 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2136 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2137 if (BytesPerWideShadow > 4) {
2138 assert(BytesPerWideShadow == 8);
2145 Value *WideShadowLo =
2146 F->getDataLayout().isLittleEndian()
2149 ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2))
2152 ConstantInt::get(WideShadowTy,
2153 ((1ULL << (WideShadowBitWidth / 2)) - 1)
2154 << (WideShadowBitWidth / 2)));
2155 Shadows.push_back(WideShadow);
2156 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2158 Shadows.push_back(WideShadowLo);
2159 Origins.push_back(Origin);
2161 Shadows.push_back(WideShadow);
2162 Origins.push_back(Origin);
2166 if (ShouldTrackOrigins)
2167 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2174 for (
uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2175 ByteOfs += BytesPerWideShadow) {
2176 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2177 ConstantInt::get(DFS.IntptrTy, 1));
2178 Value *NextWideShadow =
2180 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2181 if (ShouldTrackOrigins) {
2182 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2183 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2186 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2189 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2191 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2193 ? combineOrigins(Shadows, Origins, Pos,
2198std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2200 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2204 const auto SI = AllocaShadowMap.
find(AI);
2205 if (SI != AllocaShadowMap.
end()) {
2208 const auto OI = AllocaOriginMap.
find(AI);
2209 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2210 return {ShadowLI, ShouldTrackOrigins
2217 SmallVector<const Value *, 2> Objs;
2219 bool AllConstants =
true;
2220 for (
const Value *Obj : Objs) {
2226 AllConstants =
false;
2230 return {DFS.ZeroPrimitiveShadow,
2231 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2234 return {DFS.ZeroPrimitiveShadow,
2235 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2239 if (ShouldTrackOrigins &&
2240 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2243 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2244 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2247 DFS.PrimitiveShadowTy),
2252 Value *ShadowAddr, *OriginAddr;
2253 std::tie(ShadowAddr, OriginAddr) =
2254 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2256 const Align ShadowAlign = getShadowAlign(InstAlignment);
2257 const Align OriginAlign = getOriginAlign(InstAlignment);
2258 Value *Origin =
nullptr;
2259 if (ShouldTrackOrigins) {
2268 LoadInst *LI =
new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr,
"", Pos);
2270 return {LI, Origin};
2275 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2276 ConstantInt::get(DFS.IntptrTy, 1));
2281 return {combineShadows(
Load, Load1, Pos), Origin};
2284 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2286 if (HasSizeForFastPath)
2287 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2288 OriginAlign, Origin, Pos);
2292 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2294 return {FallbackCall, Origin};
2297std::pair<Value *, Value *>
2300 Value *PrimitiveShadow, *Origin;
2301 std::tie(PrimitiveShadow, Origin) =
2302 loadShadowOriginSansLoadTracking(Addr,
Size, InstAlignment, Pos);
2303 if (DFS.shouldTrackOrigins()) {
2304 if (Opts.dfsan_track_origins == 2) {
2307 if (!ConstantShadow || !ConstantShadow->isNullValue())
2308 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2311 return {PrimitiveShadow, Origin};
2332 if (!
V->getType()->isPointerTy())
2341 V =
GEP->getPointerOperand();
2344 if (!
V->getType()->isPointerTy())
2349 }
while (Visited.
insert(
V).second);
2354void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2358 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2359 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2374 Pos = std::next(Pos);
2376 std::vector<Value *> Shadows;
2377 std::vector<Value *> Origins;
2378 Value *PrimitiveShadow, *Origin;
2379 std::tie(PrimitiveShadow, Origin) =
2381 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2382 if (ShouldTrackOrigins) {
2383 Shadows.push_back(PrimitiveShadow);
2384 Origins.push_back(Origin);
2386 if (DFSF.Opts.dfsan_combine_pointer_labels_on_load ||
2387 DFSF.isLookupTableConstant(
2390 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2391 if (ShouldTrackOrigins) {
2392 Shadows.push_back(PtrShadow);
2396 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2397 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2400 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2401 DFSF.setShadow(&LI, Shadow);
2403 if (ShouldTrackOrigins) {
2404 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2407 if (DFSF.Opts.dfsan_event_callbacks) {
2411 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2416 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2419Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2421 assert(DFS.shouldTrackOrigins());
2422 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2426 if (!DFS.shouldTrackOrigins())
2432 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2433 const DataLayout &
DL =
F->getDataLayout();
2434 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2435 if (IntptrSize == OriginSize)
2437 assert(IntptrSize == OriginSize * 2);
2443 Value *StoreOriginAddr,
2444 uint64_t StoreOriginSize, Align Alignment) {
2445 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2446 const DataLayout &
DL =
F->getDataLayout();
2447 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2448 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2450 assert(IntptrSize >= OriginSize);
2454 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2455 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2456 Value *IntptrStoreOriginPtr =
2458 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2461 : IntptrStoreOriginPtr;
2463 Ofs += IntptrSize / OriginSize;
2464 CurrentAlignment = IntptrAlignment;
2468 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2478 const Twine &Name) {
2479 Type *VTy =
V->getType();
2489 Value *StoreOriginAddr, Align InstAlignment) {
2492 const Align OriginAlignment = getOriginAlign(InstAlignment);
2493 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2497 if (!ConstantShadow->isNullValue())
2498 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2503 if (shouldInstrumentWithCall()) {
2505 DFS.DFSanMaybeStoreOriginFn,
2506 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2508 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2509 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2511 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2513 IRBNew.disableGEPCanonicalization();
2514 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2524 IntegerType *ShadowTy =
2526 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2527 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2534 Align InstAlignment,
2535 Value *PrimitiveShadow,
2538 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2541 const auto SI = AllocaShadowMap.
find(AI);
2542 if (SI != AllocaShadowMap.
end()) {
2548 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2549 const auto OI = AllocaOriginMap.
find(AI);
2550 assert(OI != AllocaOriginMap.
end() && Origin);
2557 const Align ShadowAlign = getShadowAlign(InstAlignment);
2558 if (DFS.isZeroShadow(PrimitiveShadow)) {
2559 storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign, Pos);
2565 Value *ShadowAddr, *OriginAddr;
2566 std::tie(ShadowAddr, OriginAddr) =
2567 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2569 const unsigned ShadowVecSize = 8;
2570 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2571 "Shadow vector is too large!");
2575 if (LeftSize >= ShadowVecSize) {
2579 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2581 ShadowVec, PrimitiveShadow,
2582 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx),
I));
2585 Value *CurShadowVecAddr =
2588 LeftSize -= ShadowVecSize;
2590 }
while (LeftSize >= ShadowVecSize);
2593 while (LeftSize > 0) {
2594 Value *CurShadowAddr =
2601 if (ShouldTrackOrigins) {
2602 storeOrigin(Pos, Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2624void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2625 auto &
DL =
SI.getDataLayout();
2626 Value *Val =
SI.getValueOperand();
2639 const bool ShouldTrackOrigins =
2640 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2641 std::vector<Value *> Shadows;
2642 std::vector<Value *> Origins;
2645 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2647 if (ShouldTrackOrigins) {
2648 Shadows.push_back(Shadow);
2649 Origins.push_back(DFSF.getOrigin(Val));
2652 Value *PrimitiveShadow;
2653 if (DFSF.Opts.dfsan_combine_pointer_labels_on_store) {
2654 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2655 if (ShouldTrackOrigins) {
2656 Shadows.push_back(PtrShadow);
2657 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2659 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2661 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2663 Value *Origin =
nullptr;
2664 if (ShouldTrackOrigins)
2665 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2666 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2667 PrimitiveShadow, Origin,
SI.getIterator());
2668 if (DFSF.Opts.dfsan_event_callbacks) {
2670 Value *Addr =
SI.getPointerOperand();
2672 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2677void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &
I) {
2680 Value *Val =
I.getOperand(1);
2681 const auto &
DL =
I.getDataLayout();
2688 Value *Addr =
I.getOperand(0);
2689 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2690 DFSF.storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign,
I.getIterator());
2691 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2692 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2695void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &
I) {
2696 visitCASOrRMW(
I.getAlign(),
I);
2702void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2703 visitCASOrRMW(
I.getAlign(),
I);
2709void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2710 visitInstOperands(UO);
2713void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2714 visitInstOperands(BO);
2717void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2724 visitInstOperands(BCI);
2727void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2729void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2730 visitInstOperands(CI);
2731 if (DFSF.Opts.dfsan_event_callbacks) {
2733 Value *CombinedShadow = DFSF.getShadow(&CI);
2735 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2741void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2753 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2754 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2757void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2758 if (DFSF.Opts.dfsan_combine_offset_labels_on_gep ||
2759 DFSF.isLookupTableConstant(
2761 visitInstOperands(GEPI);
2768 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2769 if (DFSF.DFS.shouldTrackOrigins())
2770 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2773void DFSanVisitor::visitExtractElementInst(ExtractElementInst &
I) {
2774 visitInstOperands(
I);
2777void DFSanVisitor::visitInsertElementInst(InsertElementInst &
I) {
2778 visitInstOperands(
I);
2781void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &
I) {
2782 visitInstOperands(
I);
2785void DFSanVisitor::visitExtractValueInst(ExtractValueInst &
I) {
2787 Value *Agg =
I.getAggregateOperand();
2788 Value *AggShadow = DFSF.getShadow(Agg);
2790 DFSF.setShadow(&
I, ResShadow);
2791 visitInstOperandOrigins(
I);
2794void DFSanVisitor::visitInsertValueInst(InsertValueInst &
I) {
2796 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2797 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2799 DFSF.setShadow(&
I, Res);
2800 visitInstOperandOrigins(
I);
2803void DFSanVisitor::visitAllocaInst(AllocaInst &
I) {
2804 bool AllLoadsStores =
true;
2805 for (User *U :
I.users()) {
2810 if (
SI->getPointerOperand() == &
I)
2814 AllLoadsStores =
false;
2817 if (AllLoadsStores) {
2819 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2820 if (DFSF.DFS.shouldTrackOrigins()) {
2821 DFSF.AllocaOriginMap[&
I] =
2825 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2826 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2829void DFSanVisitor::visitSelectInst(SelectInst &
I) {
2830 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2831 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2832 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2833 Value *ShadowSel =
nullptr;
2834 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2835 std::vector<Value *> Shadows;
2836 std::vector<Value *> Origins;
2838 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2839 Value *FalseOrigin =
2840 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2842 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2845 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2846 FalseShadow,
I.getIterator());
2847 if (ShouldTrackOrigins) {
2848 Shadows.push_back(TrueShadow);
2849 Shadows.push_back(FalseShadow);
2850 Origins.push_back(TrueOrigin);
2851 Origins.push_back(FalseOrigin);
2854 if (TrueShadow == FalseShadow) {
2855 ShadowSel = TrueShadow;
2856 if (ShouldTrackOrigins) {
2857 Shadows.push_back(TrueShadow);
2858 Origins.push_back(TrueOrigin);
2862 "",
I.getIterator());
2863 if (ShouldTrackOrigins) {
2864 Shadows.push_back(ShadowSel);
2866 FalseOrigin,
"",
I.getIterator()));
2870 DFSF.setShadow(&
I, DFSF.Opts.dfsan_track_select_control_flow
2871 ? DFSF.combineShadowsThenConvert(
I.getType(),
2872 CondShadow, ShadowSel,
2875 if (ShouldTrackOrigins) {
2876 if (DFSF.Opts.dfsan_track_select_control_flow) {
2877 Shadows.push_back(CondShadow);
2878 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2880 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2884void DFSanVisitor::visitMemSetInst(MemSetInst &
I) {
2886 Value *ValShadow = DFSF.getShadow(
I.getValue());
2887 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2888 ? DFSF.getOrigin(
I.getValue())
2889 : DFSF.DFS.ZeroOrigin;
2891 {ValShadow, ValOrigin, I.getDest(),
2892 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2895void DFSanVisitor::visitMemTransferInst(MemTransferInst &
I) {
2900 if (DFSF.DFS.shouldTrackOrigins()) {
2902 DFSF.DFS.DFSanMemOriginTransferFn,
2903 {I.getArgOperand(0), I.getArgOperand(1),
2904 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2907 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2908 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2910 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2911 DFSF.DFS.ShadowWidthBytes));
2913 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2914 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2915 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2916 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2917 if (DFSF.Opts.dfsan_event_callbacks) {
2919 DFSF.DFS.DFSanMemTransferCallbackFn,
2920 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2924void DFSanVisitor::visitCondBrInst(CondBrInst &BR) {
2925 DFSF.addConditionalCallbacksIfEnabled(BR,
BR.getCondition());
2928void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
2929 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2935 RetVal =
I->getOperand(0);
2938 return I->isMustTailCall();
2943void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
2952 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2958 if (DFSF.DFS.shouldTrackOrigins()) {
2965void DFSanVisitor::addShadowArguments(
Function &
F, CallBase &CB,
2966 std::vector<Value *> &Args,
2968 FunctionType *FT =
F.getFunctionType();
2973 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
2975 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
2978 if (FT->isVarArg()) {
2979 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
2980 CB.
arg_size() - FT->getNumParams());
2981 auto *LabelVAAlloca =
2982 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
2985 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
2988 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
2996 if (!FT->getReturnType()->isVoidTy()) {
2997 if (!DFSF.LabelReturnAlloca) {
2998 DFSF.LabelReturnAlloca =
new AllocaInst(
2999 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3002 Args.push_back(DFSF.LabelReturnAlloca);
3006void DFSanVisitor::addOriginArguments(
Function &
F, CallBase &CB,
3007 std::vector<Value *> &Args,
3009 FunctionType *FT =
F.getFunctionType();
3014 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3015 Args.push_back(DFSF.getOrigin(*
I));
3018 if (FT->isVarArg()) {
3020 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3021 auto *OriginVAAlloca =
3022 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3025 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3034 if (!FT->getReturnType()->isVoidTy()) {
3035 if (!DFSF.OriginReturnAlloca) {
3036 DFSF.OriginReturnAlloca =
new AllocaInst(
3037 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3040 Args.push_back(DFSF.OriginReturnAlloca);
3044bool DFSanVisitor::visitWrappedCallBase(
Function &
F, CallBase &CB) {
3047 switch (DFSF.DFS.getWrapperKind(&
F)) {
3048 case DataFlowSanitizer::WK_Warning:
3050 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3052 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3053 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3054 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3056 case DataFlowSanitizer::WK_Discard:
3058 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3059 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3060 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3062 case DataFlowSanitizer::WK_Functional:
3064 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3065 visitInstOperands(CB);
3067 case DataFlowSanitizer::WK_Custom:
3075 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3076 FunctionType *FT =
F.getFunctionType();
3077 TransformedFunction CustomFnTy =
3078 DFSF.DFS.getCustomFunctionType(FT, DFSF.TLI);
3079 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3080 CustomFName +=
F.getName();
3082 CustomFName, CustomFnTy.TransformedType);
3089 AttributeList CustomAL = CustomFun->getAttributes();
3090 CustomFun->copyAttributesFrom(&
F);
3091 CustomFun->setAttributes(AttributeList::get(
3093 {CustomFun->getAttributes(), CustomAL, CustomFnTy.NewParamAttrs}));
3096 if (!FT->getReturnType()->isVoidTy()) {
3097 CustomFun->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3101 std::vector<Value *>
Args;
3105 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3110 addShadowArguments(
F, CB, Args, IRB);
3113 if (ShouldTrackOrigins)
3114 addOriginArguments(
F, CB, Args, IRB);
3119 CallInst *CustomCI = IRB.
CreateCall(CustomFunCallee, Args);
3125 {transformFunctionAttributes(CustomFnTy, CI->getContext(),
3126 CI->getAttributes()),
3127 F.getAttributes(), CustomFnTy.NewParamAttrs}));
3130 if (!FT->getReturnType()->isVoidTy()) {
3131 LoadInst *LabelLoad =
3132 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3133 DFSF.setShadow(CustomCI,
3134 DFSF.expandFromPrimitiveShadow(
3135 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3136 if (ShouldTrackOrigins) {
3137 LoadInst *OriginLoad =
3138 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3139 DFSF.setOrigin(CustomCI, OriginLoad);
3151 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3152 uint32_t OrderingTable[NumOrderings] = {};
3154 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3155 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3156 OrderingTable[(int)AtomicOrderingCABI::consume] =
3157 (
int)AtomicOrderingCABI::acquire;
3158 OrderingTable[(int)AtomicOrderingCABI::release] =
3159 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3160 (int)AtomicOrderingCABI::acq_rel;
3161 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3162 (
int)AtomicOrderingCABI::seq_cst;
3167void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3178 Value *NewOrdering =
3183 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3189 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3190 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3194 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3195 uint32_t OrderingTable[NumOrderings] = {};
3197 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3198 OrderingTable[(
int)AtomicOrderingCABI::release] =
3199 (int)AtomicOrderingCABI::release;
3200 OrderingTable[(int)AtomicOrderingCABI::consume] =
3201 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3202 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3203 (
int)AtomicOrderingCABI::acq_rel;
3204 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3205 (
int)AtomicOrderingCABI::seq_cst;
3210void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3218 Value *NewOrdering =
3226 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3227 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3230void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3246 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3247 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3251 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3252 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3255void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3269 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3271 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3275 CallInst *CI = NextIRB.CreateCall(
3276 DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3277 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false), TargetPtr,
3278 ExpectedPtr, DesiredPtr,
3279 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3283void DFSanVisitor::visitCallBase(CallBase &CB) {
3286 visitInstOperands(CB);
3296 if (LF != NotLibFunc) {
3301 case LibFunc_atomic_load:
3303 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3307 visitLibAtomicLoad(CB);
3309 case LibFunc_atomic_store:
3310 visitLibAtomicStore(CB);
3318 if (
F &&
F->hasName() && !
F->isVarArg()) {
3319 if (
F->getName() ==
"__atomic_exchange") {
3320 visitLibAtomicExchange(CB);
3323 if (
F->getName() ==
"__atomic_compare_exchange") {
3324 visitLibAtomicCompareExchange(CB);
3330 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3331 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3336 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3338 const DataLayout &
DL = getDataLayout();
3341 unsigned ArgOffset = 0;
3342 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3343 if (ShouldTrackOrigins) {
3346 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3347 !DFSF.DFS.isZeroShadow(ArgShadow))
3349 DFSF.getArgOriginTLS(
I, IRB));
3353 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3359 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3367 if (
II->getNormalDest()->getSinglePredecessor()) {
3368 Next = &
II->getNormalDest()->front();
3385 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3388 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3390 LoadInst *LI = NextIRB.CreateAlignedLoad(
3391 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3393 DFSF.SkipInsts.
insert(LI);
3394 DFSF.setShadow(&CB, LI);
3395 DFSF.NonZeroChecks.push_back(LI);
3398 if (ShouldTrackOrigins) {
3399 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3400 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3401 DFSF.SkipInsts.
insert(LI);
3402 DFSF.setOrigin(&CB, LI);
3405 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3409void DFSanVisitor::visitPHINode(PHINode &PN) {
3410 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3416 for (BasicBlock *BB : PN.
blocks())
3419 DFSF.setShadow(&PN, ShadowPN);
3421 PHINode *OriginPN =
nullptr;
3422 if (DFSF.DFS.shouldTrackOrigins()) {
3426 for (BasicBlock *BB : PN.
blocks())
3428 DFSF.setOrigin(&PN, OriginPN);
3431 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3445 if (!DataFlowSanitizer(Opts, ABIListFiles, FS).
runImpl(M, GetTLI))
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isConstant(const MachineInstr &MI)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static bool runImpl(MachineFunction &MF)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MemoryMapParams Linux_LoongArch64_MemoryMapParams
const MemoryMapParams Linux_X86_64_MemoryMapParams
static const Align MinOriginAlignment
static Value * expandFromPrimitiveShadowRecursive(Value *Shadow, SmallVector< unsigned, 4 > &Indices, Type *SubShadowTy, Value *PrimitiveShadow, IRBuilder<> &IRB)
static const Align ShadowTLSAlignment
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
const MemoryMapParams Linux_S390X_MemoryMapParams
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
Value * StripPointerGEPsAndCasts(Value *V)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static StringRef getGlobalTypeString(const GlobalValue &G)
static const unsigned ArgTLSSize
static const unsigned RetvalTLSSize
static bool isAMustTailRetVal(Value *RetVal)
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
Machine Check Debug Module
uint64_t IntrinsicInst * II
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
SmallVector< MachineOperand, 4 > Cond
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
StringSet - A set-like wrapper for the StringMap.
Defines the virtual file system interface vfs::FileSystem.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Return true if the mask contains no attributes.
AttributeMask & addAttribute(Attribute::AttrKind Val)
Add an attribute to the mask.
iterator begin()
Instruction iterator methods.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Instruction & front() const
InstListType::iterator iterator
Instruction iterators...
bool isInlineAsm() const
Check if this call is an inline asm statement.
void setCallingConv(CallingConv::ID CC)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
User::op_iterator arg_begin()
Return the iterator pointing to the beginning of the argument list.
void maybeAddParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Value * getCalledOperand() const
void setAttributes(AttributeList A)
Set the attributes for this call.
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
User::op_iterator arg_end()
Return the iterator pointing to the end of the argument list.
FunctionType * getFunctionType() const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
bool isMustTailCall() const
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI unsigned getLine() const
DILocation * get() const
Get the underlying DILocation.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
iterator find(const_arg_type_t< KeyT > Val)
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Type * getReturnType() const
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
void removeFnAttrs(const AttributeMask &Attrs)
AttributeList getAttributes() const
Return the attribute list for this Function.
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
void removeRetAttrs(const AttributeMask &Attrs)
removes the attributes from the return value list of attributes.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Value * getPointerOperand()
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
LLVM_ABI const GlobalObject * getAliaseeObject() const
static bool isExternalWeakLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
Analysis pass providing a never-invalidated alias analysis result.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreatePtrAddWithUnsignedOffset(Value *Ptr, uint64_t Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Create a ptradd with an unsigned constant offset.
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
LLVM_ABI Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
void disableGEPCanonicalization()
Disable canonicalization of getelementptr instructions to ptradd form.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI GlobalVariable * CreateGlobalString(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr, bool AddNull=true)
Make a new global variable with initializer type i8*.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
bool isTerminator() const
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is an important class for using LLVM in a threaded context.
void setAlignment(Align Align)
Value * getPointerOperand()
void setOrdering(AtomicOrdering Ordering)
Sets the ordering constraint of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
bool isAtomic() const
Return true if this load has an atomic ordering.
Align getAlign() const
Return the alignment of the access that is being performed.
static MemoryEffectsBase readOnly()
A Module instance is used to store all the information related to an LLVM module.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
ArrayRef< GlobalAsmFragment > getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Represent a constant reference to a string, i.e.
void insert_range(Range &&R)
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Value * getCondition() const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
static Attribute::AttrKind getExtAttrForI8Param(bool Signed=true)
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isSized() const
Return true if it makes sense to take the size of this type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BR
Control flow instructions. These all have token chains.
@ BasicBlock
Various leaf nodes.
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
bool includes(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::includes which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
AtomicOrdering
Atomic ordering for LLVM's memory model.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
iterator_range< df_iterator< T > > depth_first(const T &G)
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI BasicBlock * SplitEdge(BasicBlock *From, BasicBlock *To, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the edge connecting the specified blocks, and return the newly created basic block between From...
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.