139 "dfsan-preserve-alignment",
161 cl::desc(
"File listing native ABI functions and how the pass treats them"),
167 "dfsan-combine-pointer-labels-on-load",
168 cl::desc(
"Combine the label of the pointer with the label of the data when "
169 "loading from memory."),
175 "dfsan-combine-pointer-labels-on-store",
176 cl::desc(
"Combine the label of the pointer with the label of the data when "
177 "storing in memory."),
182 "dfsan-combine-offset-labels-on-gep",
184 "Combine the label of the offset with the label of the pointer when "
185 "doing pointer arithmetic."),
189 "dfsan-combine-taint-lookup-table",
191 "When dfsan-combine-offset-labels-on-gep and/or "
192 "dfsan-combine-pointer-labels-on-load are false, this flag can "
193 "be used to re-enable combining offset and/or pointer taint when "
194 "loading specific constant global variables (i.e. lookup tables)."),
198 "dfsan-debug-nonzero-labels",
199 cl::desc(
"Insert calls to __dfsan_nonzero_label on observing a parameter, "
200 "load or return with a nonzero label"),
214 "dfsan-event-callbacks",
215 cl::desc(
"Insert calls to __dfsan_*_callback functions on data events."),
222 "dfsan-conditional-callbacks",
230 "dfsan-reaches-function-callbacks",
231 cl::desc(
"Insert calls to callback functions on data reaching a function."),
236 "dfsan-track-select-control-flow",
237 cl::desc(
"Propagate labels from condition values of select instructions "
243 "dfsan-instrument-with-call-threshold",
244 cl::desc(
"If the function being instrumented requires more than "
245 "this number of origin stores, use callbacks instead of "
246 "inline checks (-1 means never use callbacks)."),
255 cl::desc(
"Track origins of labels"),
259 "dfsan-ignore-personality-routine",
260 cl::desc(
"If a personality routine is marked uninstrumented from the ABI "
261 "list, do not create a wrapper for it."),
265 "dfsan-add-global-name-suffix",
271 Type *GType =
G.getValueType();
274 if (!SGType->isLiteral())
275 return SGType->getName();
277 return "<unknown type>";
286struct MemoryMapParams {
324 std::unique_ptr<SpecialCaseList> SCL;
327 DFSanABIList() =
default;
329 void set(std::unique_ptr<SpecialCaseList>
List) { SCL = std::move(
List); }
333 bool isIn(
const Function &
F, StringRef Category)
const {
334 return isIn(*
F.getParent(), Category) ||
335 SCL->inSection(
"dataflow",
"fun",
F.getName(), Category);
342 bool isIn(
const GlobalAlias &GA, StringRef Category)
const {
347 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
349 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
355 bool isIn(
const Module &M, StringRef Category)
const {
356 return SCL->inSection(
"dataflow",
"src",
M.getModuleIdentifier(), Category);
363struct TransformedFunction {
364 TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
365 const std::vector<unsigned> &ArgumentIndexMapping)
366 : OriginalType(OriginalType), TransformedType(TransformedType),
367 ArgumentIndexMapping(ArgumentIndexMapping) {}
370 TransformedFunction(
const TransformedFunction &) =
delete;
371 TransformedFunction &operator=(
const TransformedFunction &) =
delete;
374 TransformedFunction(TransformedFunction &&) =
default;
375 TransformedFunction &operator=(TransformedFunction &&) =
default;
378 FunctionType *OriginalType;
381 FunctionType *TransformedType;
388 std::vector<unsigned> ArgumentIndexMapping;
395transformFunctionAttributes(
const TransformedFunction &TransformedFunction,
399 std::vector<llvm::AttributeSet> ArgumentAttributes(
400 TransformedFunction.TransformedType->getNumParams());
405 for (
unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
407 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[
I];
408 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttrs(
I);
412 for (
unsigned I = TransformedFunction.OriginalType->getNumParams(),
413 IE = CallSiteAttrs.getNumAttrSets();
415 ArgumentAttributes.push_back(CallSiteAttrs.getParamAttrs(
I));
418 return AttributeList::get(Ctx, CallSiteAttrs.getFnAttrs(),
419 CallSiteAttrs.getRetAttrs(),
423class DataFlowSanitizer {
424 friend struct DFSanFunction;
425 friend class DFSanVisitor;
427 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
429 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
457 IntegerType *OriginTy;
459 ConstantInt *ZeroOrigin;
461 IntegerType *PrimitiveShadowTy;
463 IntegerType *IntptrTy;
464 ConstantInt *ZeroPrimitiveShadow;
470 FunctionType *DFSanUnionLoadFnTy;
471 FunctionType *DFSanLoadLabelAndOriginFnTy;
472 FunctionType *DFSanUnimplementedFnTy;
473 FunctionType *DFSanWrapperExternWeakNullFnTy;
474 FunctionType *DFSanSetLabelFnTy;
475 FunctionType *DFSanNonzeroLabelFnTy;
476 FunctionType *DFSanVarargWrapperFnTy;
477 FunctionType *DFSanConditionalCallbackFnTy;
478 FunctionType *DFSanConditionalCallbackOriginFnTy;
479 FunctionType *DFSanReachesFunctionCallbackFnTy;
480 FunctionType *DFSanReachesFunctionCallbackOriginFnTy;
481 FunctionType *DFSanCmpCallbackFnTy;
482 FunctionType *DFSanLoadStoreCallbackFnTy;
483 FunctionType *DFSanMemTransferCallbackFnTy;
484 FunctionType *DFSanChainOriginFnTy;
485 FunctionType *DFSanChainOriginIfTaintedFnTy;
486 FunctionType *DFSanMemOriginTransferFnTy;
487 FunctionType *DFSanMemShadowOriginTransferFnTy;
488 FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
489 FunctionType *DFSanMaybeStoreOriginFnTy;
490 FunctionCallee DFSanUnionLoadFn;
491 FunctionCallee DFSanLoadLabelAndOriginFn;
492 FunctionCallee DFSanUnimplementedFn;
493 FunctionCallee DFSanWrapperExternWeakNullFn;
494 FunctionCallee DFSanSetLabelFn;
495 FunctionCallee DFSanNonzeroLabelFn;
496 FunctionCallee DFSanVarargWrapperFn;
497 FunctionCallee DFSanLoadCallbackFn;
498 FunctionCallee DFSanStoreCallbackFn;
499 FunctionCallee DFSanMemTransferCallbackFn;
500 FunctionCallee DFSanConditionalCallbackFn;
501 FunctionCallee DFSanConditionalCallbackOriginFn;
502 FunctionCallee DFSanReachesFunctionCallbackFn;
503 FunctionCallee DFSanReachesFunctionCallbackOriginFn;
504 FunctionCallee DFSanCmpCallbackFn;
505 FunctionCallee DFSanChainOriginFn;
506 FunctionCallee DFSanChainOriginIfTaintedFn;
507 FunctionCallee DFSanMemOriginTransferFn;
508 FunctionCallee DFSanMemShadowOriginTransferFn;
509 FunctionCallee DFSanMemShadowOriginConditionalExchangeFn;
510 FunctionCallee DFSanMaybeStoreOriginFn;
511 SmallPtrSet<Value *, 16> DFSanRuntimeFunctions;
512 MDNode *ColdCallWeights;
513 MDNode *OriginStoreWeights;
514 DFSanABIList ABIList;
515 DenseMap<Value *, Function *> UnwrappedFnMap;
516 AttributeMask ReadOnlyNoneAttrs;
517 StringSet<> CombineTaintLookupTableNames;
521 const MemoryMapParams *MapParams;
526 Value *ShadowOffset);
527 std::pair<Value *, Value *> getShadowOriginAddress(
Value *Addr,
530 bool isInstrumented(
const Function *
F);
531 bool isInstrumented(
const GlobalAlias *GA);
532 bool isForceZeroLabels(
const Function *
F);
533 TransformedFunction getCustomFunctionType(FunctionType *
T);
534 WrapperKind getWrapperKind(Function *
F);
535 void addGlobalNameSuffix(GlobalValue *GV);
536 void buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB, Function *
F);
537 Function *buildWrapperFunction(Function *
F, StringRef NewFName,
539 FunctionType *NewFT);
540 void initializeCallbackFunctions(
Module &M);
541 void initializeRuntimeFunctions(
Module &M);
542 bool initializeModule(
Module &M);
551 bool hasLoadSizeForFastPath(uint64_t
Size);
554 bool shouldTrackOrigins();
566 bool isZeroShadow(
Value *V);
577 const uint64_t NumOfElementsInArgOrgTLS =
ArgTLSSize / OriginWidthBytes;
580 DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles,
581 IntrusiveRefCntPtr<vfs::FileSystem> FS);
584 llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI);
587struct DFSanFunction {
588 DataFlowSanitizer &DFS;
592 bool IsForceZeroLabels;
593 TargetLibraryInfo &TLI;
594 AllocaInst *LabelReturnAlloca =
nullptr;
595 AllocaInst *OriginReturnAlloca =
nullptr;
596 DenseMap<Value *, Value *> ValShadowMap;
597 DenseMap<Value *, Value *> ValOriginMap;
598 DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
599 DenseMap<AllocaInst *, AllocaInst *> AllocaOriginMap;
601 struct PHIFixupElement {
606 std::vector<PHIFixupElement> PHIFixups;
608 DenseSet<Instruction *> SkipInsts;
609 std::vector<Value *> NonZeroChecks;
611 struct CachedShadow {
616 DenseMap<std::pair<Value *, Value *>, CachedShadow> CachedShadows;
621 DenseMap<Value *, Value *> CachedCollapsedShadows;
622 DenseMap<Value *, std::set<Value *>> ShadowElements;
624 DFSanFunction(DataFlowSanitizer &DFS, Function *F,
bool IsNativeABI,
625 bool IsForceZeroLabels, TargetLibraryInfo &TLI)
626 : DFS(DFS), F(F), IsNativeABI(IsNativeABI),
627 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
645 Value *getRetvalOriginTLS();
648 void setOrigin(Instruction *
I,
Value *Origin);
650 Value *combineOperandOrigins(Instruction *Inst);
657 Value *combineOrigins(
const std::vector<Value *> &Shadows,
658 const std::vector<Value *> &Origins,
662 void setShadow(Instruction *
I,
Value *Shadow);
670 Value *combineOperandShadows(Instruction *Inst);
679 std::pair<Value *, Value *> loadShadowOrigin(
Value *Addr, uint64_t
Size,
683 void storePrimitiveShadowOrigin(
Value *Addr, uint64_t
Size,
684 Align InstAlignment,
Value *PrimitiveShadow,
703 void storeZeroPrimitiveShadow(
Value *Addr, uint64_t
Size, Align ShadowAlign,
706 Align getShadowAlign(Align InstAlignment);
710 void addConditionalCallbacksIfEnabled(Instruction &
I,
Value *Condition);
714 void addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB, Instruction &
I,
717 bool isLookupTableConstant(
Value *
P);
722 template <
class AggregateType>
723 Value *collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
729 Value *getShadowForTLSArgument(Argument *
A);
732 std::pair<Value *, Value *>
733 loadShadowFast(
Value *ShadowAddr,
Value *OriginAddr, uint64_t
Size,
734 Align ShadowAlign, Align OriginAlign,
Value *FirstOrigin,
737 Align getOriginAlign(Align InstAlignment);
748 bool useCallbackLoadLabelAndOrigin(uint64_t
Size, Align InstAlignment);
764 uint64_t StoreOriginSize, Align Alignment);
773 Align InstAlignment);
778 bool shouldInstrumentWithCall();
784 std::pair<Value *, Value *>
785 loadShadowOriginSansLoadTracking(
Value *Addr, uint64_t
Size,
788 int NumOriginStores = 0;
791class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
795 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
797 const DataLayout &getDataLayout()
const {
798 return DFSF.F->getDataLayout();
802 void visitInstOperands(Instruction &
I);
804 void visitUnaryOperator(UnaryOperator &UO);
805 void visitBinaryOperator(BinaryOperator &BO);
806 void visitBitCastInst(BitCastInst &BCI);
807 void visitCastInst(CastInst &CI);
808 void visitCmpInst(CmpInst &CI);
809 void visitLandingPadInst(LandingPadInst &LPI);
810 void visitGetElementPtrInst(GetElementPtrInst &GEPI);
811 void visitLoadInst(LoadInst &LI);
812 void visitStoreInst(StoreInst &SI);
813 void visitAtomicRMWInst(AtomicRMWInst &
I);
814 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I);
815 void visitReturnInst(ReturnInst &RI);
816 void visitLibAtomicLoad(CallBase &CB);
817 void visitLibAtomicStore(CallBase &CB);
818 void visitLibAtomicExchange(CallBase &CB);
819 void visitLibAtomicCompareExchange(CallBase &CB);
820 void visitCallBase(CallBase &CB);
821 void visitPHINode(PHINode &PN);
822 void visitExtractElementInst(ExtractElementInst &
I);
823 void visitInsertElementInst(InsertElementInst &
I);
824 void visitShuffleVectorInst(ShuffleVectorInst &
I);
825 void visitExtractValueInst(ExtractValueInst &
I);
826 void visitInsertValueInst(InsertValueInst &
I);
827 void visitAllocaInst(AllocaInst &
I);
828 void visitSelectInst(SelectInst &
I);
829 void visitMemSetInst(MemSetInst &
I);
830 void visitMemTransferInst(MemTransferInst &
I);
831 void visitBranchInst(BranchInst &BR);
832 void visitSwitchInst(SwitchInst &SW);
835 void visitCASOrRMW(Align InstAlignment, Instruction &
I);
838 bool visitWrappedCallBase(Function &
F, CallBase &CB);
841 void visitInstOperandOrigins(Instruction &
I);
843 void addShadowArguments(Function &
F, CallBase &CB, std::vector<Value *> &Args,
846 void addOriginArguments(Function &
F, CallBase &CB, std::vector<Value *> &Args,
853bool LibAtomicFunction(
const Function &
F) {
859 if (!
F.hasName() ||
F.isVarArg())
861 switch (
F.arg_size()) {
863 return F.getName() ==
"__atomic_load" ||
F.getName() ==
"__atomic_store";
865 return F.getName() ==
"__atomic_exchange";
867 return F.getName() ==
"__atomic_compare_exchange";
875DataFlowSanitizer::DataFlowSanitizer(
876 const std::vector<std::string> &ABIListFiles,
878 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
885TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *
T) {
892 std::vector<unsigned> ArgumentIndexMapping;
893 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
894 Type *ParamType =
T->getParamType(
I);
895 ArgumentIndexMapping.push_back(ArgTypes.
size());
898 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
901 ArgTypes.
push_back(PrimitiveShadowPtrTy);
902 Type *RetType =
T->getReturnType();
904 ArgTypes.
push_back(PrimitiveShadowPtrTy);
906 if (shouldTrackOrigins()) {
907 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
915 return TransformedFunction(
916 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
917 ArgumentIndexMapping);
920bool DataFlowSanitizer::isZeroShadow(
Value *V) {
931bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t
Size) {
932 uint64_t ShadowSize =
Size * ShadowWidthBytes;
933 return ShadowSize % 8 == 0 || ShadowSize == 4;
936bool DataFlowSanitizer::shouldTrackOrigins() {
938 return ShouldTrackOrigins;
941Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
943 return ZeroPrimitiveShadow;
944 Type *ShadowTy = getShadowTy(OrigTy);
949 return getZeroShadow(
V->getType());
959 for (
unsigned Idx = 0; Idx < AT->getNumElements(); Idx++) {
962 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
969 for (
unsigned Idx = 0; Idx < ST->getNumElements(); Idx++) {
972 Shadow, Indices, ST->getElementType(Idx), PrimitiveShadow, IRB);
980bool DFSanFunction::shouldInstrumentWithCall() {
985Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
987 Type *ShadowTy = DFS.getShadowTy(
T);
990 return PrimitiveShadow;
992 if (DFS.isZeroShadow(PrimitiveShadow))
993 return DFS.getZeroShadow(ShadowTy);
996 SmallVector<unsigned, 4> Indices;
999 PrimitiveShadow, IRB);
1002 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
1006template <
class AggregateType>
1007Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
1009 if (!AT->getNumElements())
1010 return DFS.ZeroPrimitiveShadow;
1013 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1015 for (
unsigned Idx = 1; Idx < AT->getNumElements(); Idx++) {
1017 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1018 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1023Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1029 return collapseAggregateShadow<>(AT, Shadow, IRB);
1031 return collapseAggregateShadow<>(ST, Shadow, IRB);
1035Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1042 Value *&CS = CachedCollapsedShadows[Shadow];
1047 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1049 CS = PrimitiveShadow;
1050 return PrimitiveShadow;
1053void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &
I,
1059 Value *CondShadow = getShadow(Condition);
1061 if (DFS.shouldTrackOrigins()) {
1062 Value *CondOrigin = getOrigin(Condition);
1063 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1064 {CondShadow, CondOrigin});
1066 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1071void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
1077 const DebugLoc &dbgloc =
I.getDebugLoc();
1078 Value *DataShadow = collapseToPrimitiveShadow(getShadow(
Data), IRB);
1079 ConstantInt *CILine;
1082 if (dbgloc.
get() ==
nullptr) {
1083 CILine = llvm::ConstantInt::get(
I.getContext(), llvm::APInt(32, 0));
1085 I.getFunction()->getParent()->getSourceFileName());
1087 CILine = llvm::ConstantInt::get(
I.getContext(),
1088 llvm::APInt(32, dbgloc.
getLine()));
1096 std::vector<Value *>
args;
1098 if (DFS.shouldTrackOrigins()) {
1100 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1101 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1103 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1110Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1112 return PrimitiveShadowTy;
1114 return PrimitiveShadowTy;
1116 return PrimitiveShadowTy;
1118 return ArrayType::get(getShadowTy(AT->getElementType()),
1119 AT->getNumElements());
1122 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1123 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1126 return PrimitiveShadowTy;
1129Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1130 return getShadowTy(
V->getType());
1133bool DataFlowSanitizer::initializeModule(
Module &M) {
1134 Triple TargetTriple(
M.getTargetTriple());
1135 const DataLayout &
DL =
M.getDataLayout();
1139 switch (TargetTriple.getArch()) {
1154 Ctx = &
M.getContext();
1155 Int8Ptr = PointerType::getUnqual(*Ctx);
1157 OriginPtrTy = PointerType::getUnqual(*Ctx);
1159 PrimitiveShadowPtrTy = PointerType::getUnqual(*Ctx);
1160 IntptrTy =
DL.getIntPtrType(*Ctx);
1164 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1165 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1167 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1168 DFSanLoadLabelAndOriginFnTy =
1171 DFSanUnimplementedFnTy = FunctionType::get(
1172 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx),
false);
1173 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1174 DFSanWrapperExternWeakNullFnTy =
1175 FunctionType::get(Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1177 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1178 PointerType::getUnqual(*Ctx), IntptrTy};
1179 DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
1180 DFSanSetLabelArgs,
false);
1181 DFSanNonzeroLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx), {},
1183 DFSanVarargWrapperFnTy = FunctionType::get(
1184 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx),
false);
1185 DFSanConditionalCallbackFnTy =
1186 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1188 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1189 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1190 Type::getVoidTy(*Ctx), DFSanConditionalCallbackOriginArgs,
1192 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1194 DFSanReachesFunctionCallbackFnTy =
1195 FunctionType::get(Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1197 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1198 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1199 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1200 Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackOriginArgs,
1202 DFSanCmpCallbackFnTy =
1203 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1205 DFSanChainOriginFnTy =
1206 FunctionType::get(OriginTy, OriginTy,
false);
1207 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1208 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1209 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1211 Int8Ptr, IntptrTy, OriginTy};
1212 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1213 Type::getVoidTy(*Ctx), DFSanMaybeStoreOriginArgs,
false);
1214 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1215 DFSanMemOriginTransferFnTy = FunctionType::get(
1216 Type::getVoidTy(*Ctx), DFSanMemOriginTransferArgs,
false);
1217 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1218 DFSanMemShadowOriginTransferFnTy =
1219 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1221 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1223 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1224 Type::getVoidTy(*Ctx), DFSanMemShadowOriginConditionalExchangeArgs,
1226 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1227 DFSanLoadStoreCallbackFnTy =
1228 FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs,
1230 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1231 DFSanMemTransferCallbackFnTy =
1232 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1235 ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1236 OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1240bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1241 return !ABIList.isIn(*
F,
"uninstrumented");
1244bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1245 return !ABIList.isIn(*GA,
"uninstrumented");
1248bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1249 return ABIList.isIn(*
F,
"force_zero_labels");
1252DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *
F) {
1253 if (ABIList.isIn(*
F,
"functional"))
1254 return WK_Functional;
1255 if (ABIList.isIn(*
F,
"discard"))
1257 if (ABIList.isIn(*
F,
"custom"))
1263void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) {
1267 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1276 std::string SearchStr =
".symver " + GVName +
",";
1277 size_t Pos =
Asm.find(SearchStr);
1278 if (Pos != std::string::npos) {
1279 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1280 Pos =
Asm.find(
'@');
1282 if (Pos == std::string::npos)
1285 Asm.replace(Pos, 1, Suffix +
"@");
1290void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1300 std::vector<Value *>
Args;
1303 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1308DataFlowSanitizer::buildWrapperFunction(Function *
F, StringRef NewFName,
1310 FunctionType *NewFT) {
1311 FunctionType *FT =
F->getFunctionType();
1313 NewFName,
F->getParent());
1316 NewFT->getReturnType(), NewF->
getAttributes().getRetAttrs()));
1319 if (
F->isVarArg()) {
1322 IRBuilder<>(BB).CreateGlobalString(
F->getName()),
"", BB);
1323 new UnreachableInst(*Ctx, BB);
1325 auto ArgIt = pointer_iterator<Argument *>(NewF->
arg_begin());
1326 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1329 if (FT->getReturnType()->isVoidTy())
1339void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1340 LLVMContext &
C =
M.getContext();
1343 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1344 AL =
AL.addFnAttribute(
1346 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1348 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1352 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1353 AL =
AL.addFnAttribute(
1355 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1356 DFSanLoadLabelAndOriginFn =
Mod->getOrInsertFunction(
1357 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1359 DFSanUnimplementedFn =
1360 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
1361 DFSanWrapperExternWeakNullFn =
Mod->getOrInsertFunction(
1362 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1365 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1366 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1368 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
1370 DFSanNonzeroLabelFn =
1371 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1372 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
1373 DFSanVarargWrapperFnTy);
1376 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1377 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1378 DFSanChainOriginFn =
Mod->getOrInsertFunction(
"__dfsan_chain_origin",
1379 DFSanChainOriginFnTy, AL);
1383 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1384 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1385 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1386 DFSanChainOriginIfTaintedFn =
Mod->getOrInsertFunction(
1387 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1389 DFSanMemOriginTransferFn =
Mod->getOrInsertFunction(
1390 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1392 DFSanMemShadowOriginTransferFn =
Mod->getOrInsertFunction(
1393 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1395 DFSanMemShadowOriginConditionalExchangeFn =
1396 Mod->getOrInsertFunction(
"__dfsan_mem_shadow_origin_conditional_exchange",
1397 DFSanMemShadowOriginConditionalExchangeFnTy);
1401 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1402 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1403 DFSanMaybeStoreOriginFn =
Mod->getOrInsertFunction(
1404 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1407 DFSanRuntimeFunctions.
insert(
1409 DFSanRuntimeFunctions.
insert(
1411 DFSanRuntimeFunctions.
insert(
1413 DFSanRuntimeFunctions.
insert(
1415 DFSanRuntimeFunctions.
insert(
1417 DFSanRuntimeFunctions.
insert(
1419 DFSanRuntimeFunctions.
insert(
1421 DFSanRuntimeFunctions.
insert(
1423 DFSanRuntimeFunctions.
insert(
1425 DFSanRuntimeFunctions.
insert(
1427 DFSanRuntimeFunctions.
insert(
1429 DFSanRuntimeFunctions.
insert(
1431 DFSanRuntimeFunctions.
insert(
1433 DFSanRuntimeFunctions.
insert(
1435 DFSanRuntimeFunctions.
insert(
1437 DFSanRuntimeFunctions.
insert(
1439 DFSanRuntimeFunctions.
insert(
1441 DFSanRuntimeFunctions.
insert(
1443 DFSanRuntimeFunctions.
insert(
1445 DFSanRuntimeFunctions.
insert(
1446 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1448 DFSanRuntimeFunctions.
insert(
1453void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1456 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1457 DFSanLoadCallbackFn =
Mod->getOrInsertFunction(
1458 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1462 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1463 DFSanStoreCallbackFn =
Mod->getOrInsertFunction(
1464 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1466 DFSanMemTransferCallbackFn =
Mod->getOrInsertFunction(
1467 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1470 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1471 DFSanCmpCallbackFn =
Mod->getOrInsertFunction(
"__dfsan_cmp_callback",
1472 DFSanCmpCallbackFnTy, AL);
1476 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1477 DFSanConditionalCallbackFn =
Mod->getOrInsertFunction(
1478 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1482 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1483 DFSanConditionalCallbackOriginFn =
1484 Mod->getOrInsertFunction(
"__dfsan_conditional_callback_origin",
1485 DFSanConditionalCallbackOriginFnTy, AL);
1489 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1490 DFSanReachesFunctionCallbackFn =
1491 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback",
1492 DFSanReachesFunctionCallbackFnTy, AL);
1496 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1497 DFSanReachesFunctionCallbackOriginFn =
1498 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback_origin",
1499 DFSanReachesFunctionCallbackOriginFnTy, AL);
1503bool DataFlowSanitizer::runImpl(
1504 Module &M, llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1505 initializeModule(M);
1507 if (ABIList.isIn(M,
"skip"))
1510 const unsigned InitialGlobalSize =
M.global_size();
1511 const unsigned InitialModuleSize =
M.size();
1515 auto GetOrInsertGlobal = [
this, &
Changed](StringRef
Name,
1516 Type *Ty) -> Constant * {
1517 GlobalVariable *
G =
Mod->getOrInsertGlobal(Name, Ty);
1518 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1519 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1525 GetOrInsertGlobal(
"__dfsan_arg_tls",
1526 ArrayType::get(Type::getInt64Ty(*Ctx),
ArgTLSSize / 8));
1527 RetvalTLS = GetOrInsertGlobal(
1528 "__dfsan_retval_tls",
1530 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1531 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1532 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1534 (void)
Mod->getOrInsertGlobal(
"__dfsan_track_origins", OriginTy, [&] {
1536 return new GlobalVariable(
1537 M, OriginTy, true, GlobalValue::WeakODRLinkage,
1538 ConstantInt::getSigned(OriginTy,
1539 shouldTrackOrigins() ? ClTrackOrigins : 0),
1540 "__dfsan_track_origins");
1543 initializeCallbackFunctions(M);
1544 initializeRuntimeFunctions(M);
1546 std::vector<Function *> FnsToInstrument;
1547 SmallPtrSet<Function *, 2> FnsWithNativeABI;
1548 SmallPtrSet<Function *, 2> FnsWithForceZeroLabel;
1549 SmallPtrSet<Constant *, 1> PersonalityFns;
1550 for (Function &
F : M)
1551 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1552 !LibAtomicFunction(
F) &&
1553 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1554 FnsToInstrument.push_back(&
F);
1555 if (
F.hasPersonalityFn())
1556 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1560 for (
auto *
C : PersonalityFns) {
1563 if (!isInstrumented(
F))
1577 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1578 if (GAInst && FInst) {
1579 addGlobalNameSuffix(&GA);
1580 }
else if (GAInst != FInst) {
1585 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1589 FnsToInstrument.push_back(NewF);
1598 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1599 FE = FnsToInstrument.end();
1602 FunctionType *FT =
F.getFunctionType();
1604 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1605 FT->getReturnType()->isVoidTy());
1607 if (isInstrumented(&
F)) {
1608 if (isForceZeroLabels(&
F))
1609 FnsWithForceZeroLabel.
insert(&
F);
1614 addGlobalNameSuffix(&
F);
1615 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1623 F.hasLocalLinkage() ?
F.getLinkage()
1626 Function *NewF = buildWrapperFunction(
1628 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1629 std::string(
F.getName()),
1630 WrapperLinkage, FT);
1650 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1651 User *Usr =
U.getUser();
1654 if (
CE->getOpcode() == Instruction::ICmp) {
1659 if (
I->getOpcode() == Instruction::ICmp) {
1665 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1667 UnwrappedFnMap[NewF] = &
F;
1670 if (!
F.isDeclaration()) {
1680 size_t N = FI - FnsToInstrument.begin(),
1681 Count = FE - FnsToInstrument.begin();
1682 FnsToInstrument.push_back(&
F);
1683 FI = FnsToInstrument.begin() +
N;
1684 FE = FnsToInstrument.begin() +
Count;
1688 }
else if (FT->isVarArg()) {
1689 UnwrappedFnMap[&
F] = &
F;
1694 for (Function *
F : FnsToInstrument) {
1695 if (!
F ||
F->isDeclaration())
1700 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1701 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1705 for (
auto &FArg :
F->args()) {
1707 Value *FArgShadow = DFSF.getShadow(&FArg);
1708 if (isZeroShadow(FArgShadow))
1711 Next = FArgShadowInst->getNextNode();
1713 if (shouldTrackOrigins()) {
1714 if (Instruction *Origin =
1718 if (
Next->comesBefore(OriginNext)) {
1724 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *
Next, &FArg);
1732 for (BasicBlock *BB : BBList) {
1742 if (!DFSF.SkipInsts.
count(Inst))
1743 DFSanVisitor(DFSF).visit(Inst);
1754 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1755 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1757 P.ShadowPhi->setIncomingValue(
1758 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1760 P.OriginPhi->setIncomingValue(
1761 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1770 for (
Value *V : DFSF.NonZeroChecks) {
1773 Pos = std::next(
I->getIterator());
1777 Pos = std::next(Pos->getIterator());
1779 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1781 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1783 Ne, Pos,
false, ColdCallWeights));
1785 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1790 return Changed || !FnsToInstrument.empty() ||
1791 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1795 return IRB.
CreatePtrAdd(DFS.ArgTLS, ConstantInt::get(DFS.IntptrTy, ArgOffset),
1804Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1808 ArgNo,
"_dfsarg_o");
1812 assert(DFS.shouldTrackOrigins());
1814 return DFS.ZeroOrigin;
1815 Value *&Origin = ValOriginMap[
V];
1819 return DFS.ZeroOrigin;
1820 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1821 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1823 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1824 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1827 Origin = DFS.ZeroOrigin;
1830 Origin = DFS.ZeroOrigin;
1836void DFSanFunction::setOrigin(Instruction *
I,
Value *Origin) {
1837 if (!DFS.shouldTrackOrigins())
1841 ValOriginMap[
I] = Origin;
1844Value *DFSanFunction::getShadowForTLSArgument(Argument *
A) {
1845 unsigned ArgOffset = 0;
1846 const DataLayout &
DL =
F->getDataLayout();
1847 for (
auto &FArg :
F->args()) {
1848 if (!FArg.getType()->isSized()) {
1854 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1867 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1872 return DFS.getZeroShadow(
A);
1877 return DFS.getZeroShadow(V);
1878 if (IsForceZeroLabels)
1879 return DFS.getZeroShadow(V);
1880 Value *&Shadow = ValShadowMap[
V];
1884 return DFS.getZeroShadow(V);
1885 Shadow = getShadowForTLSArgument(
A);
1886 NonZeroChecks.push_back(Shadow);
1888 Shadow = DFS.getZeroShadow(V);
1894void DFSanFunction::setShadow(Instruction *
I,
Value *Shadow) {
1896 ValShadowMap[
I] = Shadow;
1904 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
1907 uint64_t AndMask = MapParams->AndMask;
1910 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1912 uint64_t XorMask = MapParams->XorMask;
1914 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1918std::pair<Value *, Value *>
1919DataFlowSanitizer::getShadowOriginAddress(
Value *Addr, Align InstAlignment,
1923 Value *ShadowOffset = getShadowOffset(Addr, IRB);
1924 Value *ShadowLong = ShadowOffset;
1925 uint64_t ShadowBase = MapParams->ShadowBase;
1926 if (ShadowBase != 0) {
1928 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1931 Value *OriginPtr =
nullptr;
1932 if (shouldTrackOrigins()) {
1933 Value *OriginLong = ShadowOffset;
1934 uint64_t OriginBase = MapParams->OriginBase;
1935 if (OriginBase != 0)
1937 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1943 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1947 return std::make_pair(ShadowPtr, OriginPtr);
1950Value *DataFlowSanitizer::getShadowAddress(
Value *Addr,
1952 Value *ShadowOffset) {
1957Value *DataFlowSanitizer::getShadowAddress(
Value *Addr,
1960 Value *ShadowAddr = getShadowOffset(Addr, IRB);
1961 uint64_t ShadowBase = MapParams->ShadowBase;
1962 if (ShadowBase != 0)
1964 IRB.
CreateAdd(ShadowAddr, ConstantInt::get(IntptrTy, ShadowBase));
1965 return getShadowAddress(Addr, Pos, ShadowAddr);
1970 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1971 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1978 if (DFS.isZeroShadow(V1))
1979 return collapseToPrimitiveShadow(V2, Pos);
1980 if (DFS.isZeroShadow(V2))
1981 return collapseToPrimitiveShadow(V1, Pos);
1983 return collapseToPrimitiveShadow(V1, Pos);
1985 auto V1Elems = ShadowElements.
find(V1);
1986 auto V2Elems = ShadowElements.
find(V2);
1987 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1989 return collapseToPrimitiveShadow(V1, Pos);
1992 return collapseToPrimitiveShadow(V2, Pos);
1994 }
else if (V1Elems != ShadowElements.
end()) {
1995 if (V1Elems->second.count(V2))
1996 return collapseToPrimitiveShadow(V1, Pos);
1997 }
else if (V2Elems != ShadowElements.
end()) {
1998 if (V2Elems->second.count(V1))
1999 return collapseToPrimitiveShadow(V2, Pos);
2002 auto Key = std::make_pair(V1, V2);
2005 CachedShadow &CCS = CachedShadows[
Key];
2006 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2010 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2011 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2014 CCS.Block = Pos->getParent();
2015 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2017 std::set<Value *> UnionElems;
2018 if (V1Elems != ShadowElements.
end()) {
2019 UnionElems = V1Elems->second;
2021 UnionElems.insert(V1);
2023 if (V2Elems != ShadowElements.
end()) {
2024 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2026 UnionElems.insert(V2);
2028 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2036Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
2038 return DFS.getZeroShadow(Inst);
2042 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2045 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2049void DFSanVisitor::visitInstOperands(Instruction &
I) {
2050 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2051 DFSF.setShadow(&
I, CombinedShadow);
2052 visitInstOperandOrigins(
I);
2055Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2056 const std::vector<Value *> &Origins,
2058 ConstantInt *Zero) {
2059 assert(Shadows.size() == Origins.size());
2060 size_t Size = Origins.size();
2062 return DFS.ZeroOrigin;
2063 Value *Origin =
nullptr;
2065 Zero = DFS.ZeroPrimitiveShadow;
2066 for (
size_t I = 0;
I !=
Size; ++
I) {
2067 Value *OpOrigin = Origins[
I];
2069 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2075 Value *OpShadow = Shadows[
I];
2076 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2081 return Origin ? Origin : DFS.ZeroOrigin;
2084Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2086 std::vector<Value *> Shadows(
Size);
2087 std::vector<Value *> Origins(
Size);
2088 for (
unsigned I = 0;
I !=
Size; ++
I) {
2092 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2095void DFSanVisitor::visitInstOperandOrigins(Instruction &
I) {
2096 if (!DFSF.DFS.shouldTrackOrigins())
2098 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2099 DFSF.setOrigin(&
I, CombinedOrigin);
2102Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2104 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2107Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2112bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2114 if (GV->isConstant() && GV->
hasName())
2115 return DFS.CombineTaintLookupTableNames.
count(GV->
getName());
2120bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t
Size,
2121 Align InstAlignment) {
2145 Value **OriginAddr) {
2148 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2152std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2153 Value *ShadowAddr,
Value *OriginAddr, uint64_t
Size, Align ShadowAlign,
2155 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2156 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2158 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2161 std::vector<Value *> Shadows;
2162 std::vector<Value *> Origins;
2175 Type *WideShadowTy =
2176 ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) :
Type::getInt64Ty(*DFS.Ctx);
2179 Value *CombinedWideShadow =
2183 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2185 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2186 if (BytesPerWideShadow > 4) {
2187 assert(BytesPerWideShadow == 8);
2194 Value *WideShadowLo =
2195 F->getParent()->getDataLayout().isLittleEndian()
2198 ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2))
2201 ConstantInt::get(WideShadowTy,
2202 (1 - (1 << (WideShadowBitWidth / 2)))
2203 << (WideShadowBitWidth / 2)));
2204 Shadows.push_back(WideShadow);
2205 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2207 Shadows.push_back(WideShadowLo);
2208 Origins.push_back(Origin);
2210 Shadows.push_back(WideShadow);
2211 Origins.push_back(Origin);
2215 if (ShouldTrackOrigins)
2216 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2223 for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2224 ByteOfs += BytesPerWideShadow) {
2225 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2226 ConstantInt::get(DFS.IntptrTy, 1));
2227 Value *NextWideShadow =
2229 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2230 if (ShouldTrackOrigins) {
2231 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2232 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2235 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2238 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2240 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2242 ? combineOrigins(Shadows, Origins, Pos,
2247std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2249 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2253 const auto SI = AllocaShadowMap.
find(AI);
2254 if (SI != AllocaShadowMap.
end()) {
2257 const auto OI = AllocaOriginMap.
find(AI);
2258 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2259 return {ShadowLI, ShouldTrackOrigins
2266 SmallVector<const Value *, 2> Objs;
2268 bool AllConstants =
true;
2269 for (
const Value *Obj : Objs) {
2275 AllConstants =
false;
2279 return {DFS.ZeroPrimitiveShadow,
2280 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2283 return {DFS.ZeroPrimitiveShadow,
2284 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2288 if (ShouldTrackOrigins &&
2289 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2292 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2293 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2296 DFS.PrimitiveShadowTy),
2301 Value *ShadowAddr, *OriginAddr;
2302 std::tie(ShadowAddr, OriginAddr) =
2303 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2305 const Align ShadowAlign = getShadowAlign(InstAlignment);
2306 const Align OriginAlign = getOriginAlign(InstAlignment);
2307 Value *Origin =
nullptr;
2308 if (ShouldTrackOrigins) {
2317 LoadInst *LI =
new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr,
"", Pos);
2319 return {LI, Origin};
2323 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2324 ConstantInt::get(DFS.IntptrTy, 1));
2329 return {combineShadows(Load, Load1, Pos), Origin};
2332 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2334 if (HasSizeForFastPath)
2335 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2336 OriginAlign, Origin, Pos);
2340 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2342 return {FallbackCall, Origin};
2345std::pair<Value *, Value *>
2346DFSanFunction::loadShadowOrigin(
Value *Addr, uint64_t
Size, Align InstAlignment,
2348 Value *PrimitiveShadow, *Origin;
2349 std::tie(PrimitiveShadow, Origin) =
2350 loadShadowOriginSansLoadTracking(Addr,
Size, InstAlignment, Pos);
2351 if (DFS.shouldTrackOrigins()) {
2355 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2356 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2359 return {PrimitiveShadow, Origin};
2380 if (!V->getType()->isPointerTy())
2389 V =
GEP->getPointerOperand();
2392 if (!V->getType()->isPointerTy())
2397 }
while (Visited.
insert(V).second);
2402void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2406 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2407 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2422 Pos = std::next(Pos);
2424 std::vector<Value *> Shadows;
2425 std::vector<Value *> Origins;
2426 Value *PrimitiveShadow, *Origin;
2427 std::tie(PrimitiveShadow, Origin) =
2429 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2430 if (ShouldTrackOrigins) {
2431 Shadows.push_back(PrimitiveShadow);
2432 Origins.push_back(Origin);
2435 DFSF.isLookupTableConstant(
2438 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2439 if (ShouldTrackOrigins) {
2440 Shadows.push_back(PtrShadow);
2444 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2445 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2448 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2449 DFSF.setShadow(&LI, Shadow);
2451 if (ShouldTrackOrigins) {
2452 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2459 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2464 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2467Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2469 assert(DFS.shouldTrackOrigins());
2470 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2474 if (!DFS.shouldTrackOrigins())
2476 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2480 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2481 const DataLayout &
DL =
F->getDataLayout();
2482 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2483 if (IntptrSize == OriginSize)
2485 assert(IntptrSize == OriginSize * 2);
2491 Value *StoreOriginAddr,
2492 uint64_t StoreOriginSize, Align Alignment) {
2493 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2494 const DataLayout &
DL =
F->getDataLayout();
2495 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2496 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2498 assert(IntptrSize >= OriginSize);
2501 Align CurrentAlignment = Alignment;
2502 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2503 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2504 Value *IntptrStoreOriginPtr =
2506 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2509 : IntptrStoreOriginPtr;
2511 Ofs += IntptrSize / OriginSize;
2512 CurrentAlignment = IntptrAlignment;
2516 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2526 const Twine &Name) {
2527 Type *VTy =
V->getType();
2532 return IRB.
CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2537 Value *StoreOriginAddr, Align InstAlignment) {
2540 const Align OriginAlignment = getOriginAlign(InstAlignment);
2541 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2544 if (!ConstantShadow->isZeroValue())
2545 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2550 if (shouldInstrumentWithCall()) {
2552 DFS.DFSanMaybeStoreOriginFn,
2553 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2555 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2556 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2558 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2560 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2566void DFSanFunction::storeZeroPrimitiveShadow(
Value *Addr, uint64_t
Size,
2570 IntegerType *ShadowTy =
2572 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2573 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2579void DFSanFunction::storePrimitiveShadowOrigin(
Value *Addr, uint64_t
Size,
2580 Align InstAlignment,
2581 Value *PrimitiveShadow,
2584 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2587 const auto SI = AllocaShadowMap.
find(AI);
2588 if (SI != AllocaShadowMap.
end()) {
2594 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2595 const auto OI = AllocaOriginMap.
find(AI);
2596 assert(OI != AllocaOriginMap.
end() && Origin);
2603 const Align ShadowAlign = getShadowAlign(InstAlignment);
2604 if (DFS.isZeroShadow(PrimitiveShadow)) {
2605 storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign, Pos);
2610 Value *ShadowAddr, *OriginAddr;
2611 std::tie(ShadowAddr, OriginAddr) =
2612 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2614 const unsigned ShadowVecSize = 8;
2615 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2616 "Shadow vector is too large!");
2619 uint64_t LeftSize =
Size;
2620 if (LeftSize >= ShadowVecSize) {
2624 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2626 ShadowVec, PrimitiveShadow,
2627 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx),
I));
2630 Value *CurShadowVecAddr =
2633 LeftSize -= ShadowVecSize;
2635 }
while (LeftSize >= ShadowVecSize);
2638 while (LeftSize > 0) {
2639 Value *CurShadowAddr =
2646 if (ShouldTrackOrigins) {
2647 storeOrigin(Pos, Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2669void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2670 auto &
DL =
SI.getDataLayout();
2671 Value *Val =
SI.getValueOperand();
2684 const bool ShouldTrackOrigins =
2685 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2686 std::vector<Value *> Shadows;
2687 std::vector<Value *> Origins;
2690 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2692 if (ShouldTrackOrigins) {
2693 Shadows.push_back(Shadow);
2694 Origins.push_back(DFSF.getOrigin(Val));
2697 Value *PrimitiveShadow;
2699 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2700 if (ShouldTrackOrigins) {
2701 Shadows.push_back(PtrShadow);
2702 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2704 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2706 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2708 Value *Origin =
nullptr;
2709 if (ShouldTrackOrigins)
2710 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2711 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2712 PrimitiveShadow, Origin,
SI.getIterator());
2715 Value *Addr =
SI.getPointerOperand();
2717 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2722void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &
I) {
2725 Value *Val =
I.getOperand(1);
2726 const auto &
DL =
I.getDataLayout();
2734 Value *Addr =
I.getOperand(0);
2735 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2736 DFSF.storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign,
I.getIterator());
2737 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2738 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2741void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &
I) {
2742 visitCASOrRMW(
I.getAlign(),
I);
2748void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2749 visitCASOrRMW(
I.getAlign(),
I);
2755void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2756 visitInstOperands(UO);
2759void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2760 visitInstOperands(BO);
2763void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2770 visitInstOperands(BCI);
2773void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2775void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2776 visitInstOperands(CI);
2779 Value *CombinedShadow = DFSF.getShadow(&CI);
2781 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2786void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2798 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2799 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2802void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2804 DFSF.isLookupTableConstant(
2806 visitInstOperands(GEPI);
2813 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2814 if (DFSF.DFS.shouldTrackOrigins())
2815 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2818void DFSanVisitor::visitExtractElementInst(ExtractElementInst &
I) {
2819 visitInstOperands(
I);
2822void DFSanVisitor::visitInsertElementInst(InsertElementInst &
I) {
2823 visitInstOperands(
I);
2826void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &
I) {
2827 visitInstOperands(
I);
2830void DFSanVisitor::visitExtractValueInst(ExtractValueInst &
I) {
2832 Value *Agg =
I.getAggregateOperand();
2833 Value *AggShadow = DFSF.getShadow(Agg);
2835 DFSF.setShadow(&
I, ResShadow);
2836 visitInstOperandOrigins(
I);
2839void DFSanVisitor::visitInsertValueInst(InsertValueInst &
I) {
2841 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2842 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2844 DFSF.setShadow(&
I, Res);
2845 visitInstOperandOrigins(
I);
2848void DFSanVisitor::visitAllocaInst(AllocaInst &
I) {
2849 bool AllLoadsStores =
true;
2850 for (User *U :
I.users()) {
2855 if (
SI->getPointerOperand() == &
I)
2859 AllLoadsStores =
false;
2862 if (AllLoadsStores) {
2864 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2865 if (DFSF.DFS.shouldTrackOrigins()) {
2866 DFSF.AllocaOriginMap[&
I] =
2870 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2871 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2874void DFSanVisitor::visitSelectInst(SelectInst &
I) {
2875 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2876 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2877 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2878 Value *ShadowSel =
nullptr;
2879 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2880 std::vector<Value *> Shadows;
2881 std::vector<Value *> Origins;
2883 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2884 Value *FalseOrigin =
2885 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2887 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2890 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2891 FalseShadow,
I.getIterator());
2892 if (ShouldTrackOrigins) {
2893 Shadows.push_back(TrueShadow);
2894 Shadows.push_back(FalseShadow);
2895 Origins.push_back(TrueOrigin);
2896 Origins.push_back(FalseOrigin);
2899 if (TrueShadow == FalseShadow) {
2900 ShadowSel = TrueShadow;
2901 if (ShouldTrackOrigins) {
2902 Shadows.push_back(TrueShadow);
2903 Origins.push_back(TrueOrigin);
2907 "",
I.getIterator());
2908 if (ShouldTrackOrigins) {
2909 Shadows.push_back(ShadowSel);
2911 FalseOrigin,
"",
I.getIterator()));
2916 I.getType(), CondShadow,
2917 ShadowSel,
I.getIterator())
2919 if (ShouldTrackOrigins) {
2921 Shadows.push_back(CondShadow);
2922 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2924 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2928void DFSanVisitor::visitMemSetInst(MemSetInst &
I) {
2930 Value *ValShadow = DFSF.getShadow(
I.getValue());
2931 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2932 ? DFSF.getOrigin(
I.getValue())
2933 : DFSF.DFS.ZeroOrigin;
2935 {ValShadow, ValOrigin, I.getDest(),
2936 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2939void DFSanVisitor::visitMemTransferInst(MemTransferInst &
I) {
2944 if (DFSF.DFS.shouldTrackOrigins()) {
2946 DFSF.DFS.DFSanMemOriginTransferFn,
2947 {I.getArgOperand(0), I.getArgOperand(1),
2948 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2951 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2952 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2954 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2955 DFSF.DFS.ShadowWidthBytes));
2957 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2958 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2959 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2960 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2963 DFSF.DFS.DFSanMemTransferCallbackFn,
2964 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2968void DFSanVisitor::visitBranchInst(BranchInst &BR) {
2972 DFSF.addConditionalCallbacksIfEnabled(BR, BR.
getCondition());
2975void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
2976 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2982 RetVal =
I->getOperand(0);
2985 return I->isMustTailCall();
2990void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
2999 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
3005 if (DFSF.DFS.shouldTrackOrigins()) {
3012void DFSanVisitor::addShadowArguments(Function &
F, CallBase &CB,
3013 std::vector<Value *> &Args,
3015 FunctionType *FT =
F.getFunctionType();
3020 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3022 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3025 if (FT->isVarArg()) {
3026 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3027 CB.
arg_size() - FT->getNumParams());
3028 auto *LabelVAAlloca =
3029 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3032 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3035 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3043 if (!FT->getReturnType()->isVoidTy()) {
3044 if (!DFSF.LabelReturnAlloca) {
3045 DFSF.LabelReturnAlloca =
new AllocaInst(
3046 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3049 Args.push_back(DFSF.LabelReturnAlloca);
3053void DFSanVisitor::addOriginArguments(Function &
F, CallBase &CB,
3054 std::vector<Value *> &Args,
3056 FunctionType *FT =
F.getFunctionType();
3061 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3062 Args.push_back(DFSF.getOrigin(*
I));
3065 if (FT->isVarArg()) {
3067 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3068 auto *OriginVAAlloca =
3069 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3072 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3081 if (!FT->getReturnType()->isVoidTy()) {
3082 if (!DFSF.OriginReturnAlloca) {
3083 DFSF.OriginReturnAlloca =
new AllocaInst(
3084 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3087 Args.push_back(DFSF.OriginReturnAlloca);
3091bool DFSanVisitor::visitWrappedCallBase(Function &
F, CallBase &CB) {
3093 switch (DFSF.DFS.getWrapperKind(&
F)) {
3094 case DataFlowSanitizer::WK_Warning:
3096 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3098 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3099 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3100 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3102 case DataFlowSanitizer::WK_Discard:
3104 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3105 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3106 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3108 case DataFlowSanitizer::WK_Functional:
3110 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3111 visitInstOperands(CB);
3113 case DataFlowSanitizer::WK_Custom:
3121 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3122 FunctionType *FT =
F.getFunctionType();
3123 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3124 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3125 CustomFName +=
F.getName();
3127 CustomFName, CustomFn.TransformedType);
3129 CustomFn->copyAttributesFrom(&
F);
3132 if (!FT->getReturnType()->isVoidTy()) {
3133 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3137 std::vector<Value *>
Args;
3141 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3146 const unsigned ShadowArgStart =
Args.size();
3147 addShadowArguments(
F, CB, Args, IRB);
3150 const unsigned OriginArgStart =
Args.size();
3151 if (ShouldTrackOrigins)
3152 addOriginArguments(
F, CB, Args, IRB);
3157 CallInst *CustomCI = IRB.
CreateCall(CustomF, Args);
3165 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3166 const unsigned ArgNo = ShadowArgStart +
N;
3168 DFSF.DFS.PrimitiveShadowTy)
3170 if (ShouldTrackOrigins) {
3171 const unsigned OriginArgNo = OriginArgStart +
N;
3179 if (!FT->getReturnType()->isVoidTy()) {
3180 LoadInst *LabelLoad =
3181 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3182 DFSF.setShadow(CustomCI,
3183 DFSF.expandFromPrimitiveShadow(
3184 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3185 if (ShouldTrackOrigins) {
3186 LoadInst *OriginLoad =
3187 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3188 DFSF.setOrigin(CustomCI, OriginLoad);
3200 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3201 uint32_t OrderingTable[NumOrderings] = {};
3203 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3204 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3205 OrderingTable[(int)AtomicOrderingCABI::consume] =
3206 (
int)AtomicOrderingCABI::acquire;
3207 OrderingTable[(int)AtomicOrderingCABI::release] =
3208 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3209 (int)AtomicOrderingCABI::acq_rel;
3210 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3211 (
int)AtomicOrderingCABI::seq_cst;
3216void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3227 Value *NewOrdering =
3232 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3238 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3239 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3243 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3244 uint32_t OrderingTable[NumOrderings] = {};
3246 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3247 OrderingTable[(
int)AtomicOrderingCABI::release] =
3248 (int)AtomicOrderingCABI::release;
3249 OrderingTable[(int)AtomicOrderingCABI::consume] =
3250 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3251 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3252 (
int)AtomicOrderingCABI::acq_rel;
3253 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3254 (
int)AtomicOrderingCABI::seq_cst;
3259void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3267 Value *NewOrdering =
3275 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3276 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3279void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3295 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3296 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3300 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3301 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3304void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3318 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3320 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3324 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3325 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3326 TargetPtr, ExpectedPtr, DesiredPtr,
3327 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3330void DFSanVisitor::visitCallBase(CallBase &CB) {
3333 visitInstOperands(CB);
3348 case LibFunc_atomic_load:
3350 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3354 visitLibAtomicLoad(CB);
3356 case LibFunc_atomic_store:
3357 visitLibAtomicStore(CB);
3365 if (
F &&
F->hasName() && !
F->isVarArg()) {
3366 if (
F->getName() ==
"__atomic_exchange") {
3367 visitLibAtomicExchange(CB);
3370 if (
F->getName() ==
"__atomic_compare_exchange") {
3371 visitLibAtomicCompareExchange(CB);
3376 DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
3378 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3379 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3384 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3386 const DataLayout &
DL = getDataLayout();
3389 unsigned ArgOffset = 0;
3390 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3391 if (ShouldTrackOrigins) {
3394 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3395 !DFSF.DFS.isZeroShadow(ArgShadow))
3397 DFSF.getArgOriginTLS(
I, IRB));
3401 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3407 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3415 if (
II->getNormalDest()->getSinglePredecessor()) {
3416 Next = &
II->getNormalDest()->front();
3433 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3436 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3438 LoadInst *LI = NextIRB.CreateAlignedLoad(
3439 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3441 DFSF.SkipInsts.
insert(LI);
3442 DFSF.setShadow(&CB, LI);
3443 DFSF.NonZeroChecks.push_back(LI);
3446 if (ShouldTrackOrigins) {
3447 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3448 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3449 DFSF.SkipInsts.
insert(LI);
3450 DFSF.setOrigin(&CB, LI);
3453 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3457void DFSanVisitor::visitPHINode(PHINode &PN) {
3458 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3464 for (BasicBlock *BB : PN.
blocks())
3467 DFSF.setShadow(&PN, ShadowPN);
3469 PHINode *OriginPN =
nullptr;
3470 if (DFSF.DFS.shouldTrackOrigins()) {
3474 for (BasicBlock *BB : PN.
blocks())
3476 DFSF.setOrigin(&PN, OriginPN);
3479 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3492 if (!DataFlowSanitizer(ABIListFiles, FS).
runImpl(M, GetTLI))
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< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 cl::opt< bool > ClAddGlobalNameSuffix("dfsan-add-global-name-suffix", cl::desc("Whether to add .dfsan suffix to global names"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClTrackSelectControlFlow("dfsan-track-select-control-flow", cl::desc("Propagate labels from condition values of select instructions " "to results."), cl::Hidden, cl::init(true))
static cl::list< std::string > ClCombineTaintLookupTables("dfsan-combine-taint-lookup-table", cl::desc("When dfsan-combine-offset-labels-on-gep and/or " "dfsan-combine-pointer-labels-on-load are false, this flag can " "be used to re-enable combining offset and/or pointer taint when " "loading specific constant global variables (i.e. lookup tables)."), cl::Hidden)
static const Align MinOriginAlignment
static cl::opt< int > ClTrackOrigins("dfsan-track-origins", cl::desc("Track origins of labels"), cl::Hidden, cl::init(0))
static cl::list< std::string > ClABIListFiles("dfsan-abilist", cl::desc("File listing native ABI functions and how the pass treats them"), cl::Hidden)
static cl::opt< bool > ClReachesFunctionCallbacks("dfsan-reaches-function-callbacks", cl::desc("Insert calls to callback functions on data reaching a function."), cl::Hidden, cl::init(false))
static Value * expandFromPrimitiveShadowRecursive(Value *Shadow, SmallVector< unsigned, 4 > &Indices, Type *SubShadowTy, Value *PrimitiveShadow, IRBuilder<> &IRB)
static cl::opt< int > ClInstrumentWithCallThreshold("dfsan-instrument-with-call-threshold", cl::desc("If the function being instrumented requires more than " "this number of origin stores, use callbacks instead of " "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(3500))
static cl::opt< bool > ClPreserveAlignment("dfsan-preserve-alignment", cl::desc("respect alignment requirements provided by input IR"), cl::Hidden, cl::init(false))
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)
static cl::opt< bool > ClCombineOffsetLabelsOnGEP("dfsan-combine-offset-labels-on-gep", cl::desc("Combine the label of the offset with the label of the pointer when " "doing pointer arithmetic."), cl::Hidden, cl::init(true))
static cl::opt< bool > ClIgnorePersonalityRoutine("dfsan-ignore-personality-routine", cl::desc("If a personality routine is marked uninstrumented from the ABI " "list, do not create a wrapper for it."), cl::Hidden, cl::init(false))
static const Align ShadowTLSAlignment
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
Value * StripPointerGEPsAndCasts(Value *V)
const MemoryMapParams Linux_AArch64_MemoryMapParams
static cl::opt< bool > ClConditionalCallbacks("dfsan-conditional-callbacks", cl::desc("Insert calls to callback functions on conditionals."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClCombinePointerLabelsOnLoad("dfsan-combine-pointer-labels-on-load", cl::desc("Combine the label of the pointer with the label of the data when " "loading from memory."), cl::Hidden, cl::init(true))
static StringRef getGlobalTypeString(const GlobalValue &G)
static cl::opt< bool > ClCombinePointerLabelsOnStore("dfsan-combine-pointer-labels-on-store", cl::desc("Combine the label of the pointer with the label of the data when " "storing in memory."), cl::Hidden, cl::init(false))
static const unsigned ArgTLSSize
static const unsigned RetvalTLSSize
static bool isAMustTailRetVal(Value *RetVal)
static cl::opt< bool > ClEventCallbacks("dfsan-event-callbacks", cl::desc("Insert calls to __dfsan_*_callback functions on data events."), cl::Hidden, cl::init(false))
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.
static bool runImpl(Function &F, const TargetLowering &TLI, AssumptionCache *AC)
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
const SmallVectorImpl< MachineOperand > & 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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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 isConditional() const
Value * getCondition() const
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.
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
AttributeList getAttributes() const
Return the attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
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)
Return a ConstantInt with the specified value for the specified type.
LLVM_ABI 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
LLVM_ABI DILocation * get() const
Get the underlying DILocation.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
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 * 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)
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
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 bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
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.
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.
const std::string & getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
void setModuleInlineAsm(StringRef Asm)
Set the module-scope inline assembly blocks.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
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.
StringRef - 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.
bool getLibFunc(StringRef funcName, LibFunc &F) 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(SmallPtrSetImpl< Type * > *Visited=nullptr) 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.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
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.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
@ 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.
FunctionAddr VTableAddr Value
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.
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.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
FunctionAddr VTableAddr Next
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.
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 removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.
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.