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);
2195 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2196 Shadows.push_back(WideShadow);
2197 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2199 Shadows.push_back(WideShadowLo);
2200 Origins.push_back(Origin);
2202 Shadows.push_back(WideShadow);
2203 Origins.push_back(Origin);
2207 if (ShouldTrackOrigins)
2208 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2215 for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2216 ByteOfs += BytesPerWideShadow) {
2217 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2218 ConstantInt::get(DFS.IntptrTy, 1));
2219 Value *NextWideShadow =
2221 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2222 if (ShouldTrackOrigins) {
2223 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2224 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2227 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2230 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2232 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2234 ? combineOrigins(Shadows, Origins, Pos,
2239std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2241 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2245 const auto SI = AllocaShadowMap.
find(AI);
2246 if (SI != AllocaShadowMap.
end()) {
2249 const auto OI = AllocaOriginMap.
find(AI);
2250 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2251 return {ShadowLI, ShouldTrackOrigins
2258 SmallVector<const Value *, 2> Objs;
2260 bool AllConstants =
true;
2261 for (
const Value *Obj : Objs) {
2267 AllConstants =
false;
2271 return {DFS.ZeroPrimitiveShadow,
2272 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2275 return {DFS.ZeroPrimitiveShadow,
2276 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2280 if (ShouldTrackOrigins &&
2281 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2284 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2285 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2288 DFS.PrimitiveShadowTy),
2293 Value *ShadowAddr, *OriginAddr;
2294 std::tie(ShadowAddr, OriginAddr) =
2295 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2297 const Align ShadowAlign = getShadowAlign(InstAlignment);
2298 const Align OriginAlign = getOriginAlign(InstAlignment);
2299 Value *Origin =
nullptr;
2300 if (ShouldTrackOrigins) {
2309 LoadInst *LI =
new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr,
"", Pos);
2311 return {LI, Origin};
2315 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2316 ConstantInt::get(DFS.IntptrTy, 1));
2321 return {combineShadows(Load, Load1, Pos), Origin};
2324 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2326 if (HasSizeForFastPath)
2327 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2328 OriginAlign, Origin, Pos);
2332 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2334 return {FallbackCall, Origin};
2337std::pair<Value *, Value *>
2338DFSanFunction::loadShadowOrigin(
Value *Addr, uint64_t
Size, Align InstAlignment,
2340 Value *PrimitiveShadow, *Origin;
2341 std::tie(PrimitiveShadow, Origin) =
2342 loadShadowOriginSansLoadTracking(Addr,
Size, InstAlignment, Pos);
2343 if (DFS.shouldTrackOrigins()) {
2347 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2348 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2351 return {PrimitiveShadow, Origin};
2372 if (!V->getType()->isPointerTy())
2381 V =
GEP->getPointerOperand();
2384 if (!V->getType()->isPointerTy())
2389 }
while (Visited.
insert(V).second);
2394void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2398 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2399 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2414 Pos = std::next(Pos);
2416 std::vector<Value *> Shadows;
2417 std::vector<Value *> Origins;
2418 Value *PrimitiveShadow, *Origin;
2419 std::tie(PrimitiveShadow, Origin) =
2421 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2422 if (ShouldTrackOrigins) {
2423 Shadows.push_back(PrimitiveShadow);
2424 Origins.push_back(Origin);
2427 DFSF.isLookupTableConstant(
2430 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2431 if (ShouldTrackOrigins) {
2432 Shadows.push_back(PtrShadow);
2436 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2437 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2440 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2441 DFSF.setShadow(&LI, Shadow);
2443 if (ShouldTrackOrigins) {
2444 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2451 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2456 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2459Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2461 assert(DFS.shouldTrackOrigins());
2462 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2466 if (!DFS.shouldTrackOrigins())
2468 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2472 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2473 const DataLayout &
DL =
F->getDataLayout();
2474 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2475 if (IntptrSize == OriginSize)
2477 assert(IntptrSize == OriginSize * 2);
2483 Value *StoreOriginAddr,
2484 uint64_t StoreOriginSize, Align Alignment) {
2485 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2486 const DataLayout &
DL =
F->getDataLayout();
2487 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2488 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2490 assert(IntptrSize >= OriginSize);
2493 Align CurrentAlignment = Alignment;
2494 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2495 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2496 Value *IntptrStoreOriginPtr =
2498 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2501 : IntptrStoreOriginPtr;
2503 Ofs += IntptrSize / OriginSize;
2504 CurrentAlignment = IntptrAlignment;
2508 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2518 const Twine &Name) {
2519 Type *VTy =
V->getType();
2524 return IRB.
CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2529 Value *StoreOriginAddr, Align InstAlignment) {
2532 const Align OriginAlignment = getOriginAlign(InstAlignment);
2533 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2536 if (!ConstantShadow->isZeroValue())
2537 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2542 if (shouldInstrumentWithCall()) {
2544 DFS.DFSanMaybeStoreOriginFn,
2545 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2547 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2548 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2550 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2552 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2558void DFSanFunction::storeZeroPrimitiveShadow(
Value *Addr, uint64_t
Size,
2562 IntegerType *ShadowTy =
2564 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2565 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2571void DFSanFunction::storePrimitiveShadowOrigin(
Value *Addr, uint64_t
Size,
2572 Align InstAlignment,
2573 Value *PrimitiveShadow,
2576 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2579 const auto SI = AllocaShadowMap.
find(AI);
2580 if (SI != AllocaShadowMap.
end()) {
2586 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2587 const auto OI = AllocaOriginMap.
find(AI);
2588 assert(OI != AllocaOriginMap.
end() && Origin);
2595 const Align ShadowAlign = getShadowAlign(InstAlignment);
2596 if (DFS.isZeroShadow(PrimitiveShadow)) {
2597 storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign, Pos);
2602 Value *ShadowAddr, *OriginAddr;
2603 std::tie(ShadowAddr, OriginAddr) =
2604 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2606 const unsigned ShadowVecSize = 8;
2607 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2608 "Shadow vector is too large!");
2611 uint64_t LeftSize =
Size;
2612 if (LeftSize >= ShadowVecSize) {
2616 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2618 ShadowVec, PrimitiveShadow,
2619 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx),
I));
2622 Value *CurShadowVecAddr =
2625 LeftSize -= ShadowVecSize;
2627 }
while (LeftSize >= ShadowVecSize);
2630 while (LeftSize > 0) {
2631 Value *CurShadowAddr =
2638 if (ShouldTrackOrigins) {
2639 storeOrigin(Pos, Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2661void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2662 auto &
DL =
SI.getDataLayout();
2663 Value *Val =
SI.getValueOperand();
2676 const bool ShouldTrackOrigins =
2677 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2678 std::vector<Value *> Shadows;
2679 std::vector<Value *> Origins;
2682 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2684 if (ShouldTrackOrigins) {
2685 Shadows.push_back(Shadow);
2686 Origins.push_back(DFSF.getOrigin(Val));
2689 Value *PrimitiveShadow;
2691 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2692 if (ShouldTrackOrigins) {
2693 Shadows.push_back(PtrShadow);
2694 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2696 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2698 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2700 Value *Origin =
nullptr;
2701 if (ShouldTrackOrigins)
2702 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2703 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2704 PrimitiveShadow, Origin,
SI.getIterator());
2707 Value *Addr =
SI.getPointerOperand();
2709 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2714void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &
I) {
2717 Value *Val =
I.getOperand(1);
2718 const auto &
DL =
I.getDataLayout();
2726 Value *Addr =
I.getOperand(0);
2727 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2728 DFSF.storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign,
I.getIterator());
2729 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2730 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2733void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &
I) {
2734 visitCASOrRMW(
I.getAlign(),
I);
2740void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2741 visitCASOrRMW(
I.getAlign(),
I);
2747void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2748 visitInstOperands(UO);
2751void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2752 visitInstOperands(BO);
2755void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2762 visitInstOperands(BCI);
2765void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2767void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2768 visitInstOperands(CI);
2771 Value *CombinedShadow = DFSF.getShadow(&CI);
2773 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2778void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2790 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2791 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2794void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2796 DFSF.isLookupTableConstant(
2798 visitInstOperands(GEPI);
2805 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2806 if (DFSF.DFS.shouldTrackOrigins())
2807 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2810void DFSanVisitor::visitExtractElementInst(ExtractElementInst &
I) {
2811 visitInstOperands(
I);
2814void DFSanVisitor::visitInsertElementInst(InsertElementInst &
I) {
2815 visitInstOperands(
I);
2818void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &
I) {
2819 visitInstOperands(
I);
2822void DFSanVisitor::visitExtractValueInst(ExtractValueInst &
I) {
2824 Value *Agg =
I.getAggregateOperand();
2825 Value *AggShadow = DFSF.getShadow(Agg);
2827 DFSF.setShadow(&
I, ResShadow);
2828 visitInstOperandOrigins(
I);
2831void DFSanVisitor::visitInsertValueInst(InsertValueInst &
I) {
2833 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2834 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2836 DFSF.setShadow(&
I, Res);
2837 visitInstOperandOrigins(
I);
2840void DFSanVisitor::visitAllocaInst(AllocaInst &
I) {
2841 bool AllLoadsStores =
true;
2842 for (User *U :
I.users()) {
2847 if (
SI->getPointerOperand() == &
I)
2851 AllLoadsStores =
false;
2854 if (AllLoadsStores) {
2856 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2857 if (DFSF.DFS.shouldTrackOrigins()) {
2858 DFSF.AllocaOriginMap[&
I] =
2862 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2863 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2866void DFSanVisitor::visitSelectInst(SelectInst &
I) {
2867 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2868 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2869 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2870 Value *ShadowSel =
nullptr;
2871 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2872 std::vector<Value *> Shadows;
2873 std::vector<Value *> Origins;
2875 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2876 Value *FalseOrigin =
2877 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2879 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2882 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2883 FalseShadow,
I.getIterator());
2884 if (ShouldTrackOrigins) {
2885 Shadows.push_back(TrueShadow);
2886 Shadows.push_back(FalseShadow);
2887 Origins.push_back(TrueOrigin);
2888 Origins.push_back(FalseOrigin);
2891 if (TrueShadow == FalseShadow) {
2892 ShadowSel = TrueShadow;
2893 if (ShouldTrackOrigins) {
2894 Shadows.push_back(TrueShadow);
2895 Origins.push_back(TrueOrigin);
2899 "",
I.getIterator());
2900 if (ShouldTrackOrigins) {
2901 Shadows.push_back(ShadowSel);
2903 FalseOrigin,
"",
I.getIterator()));
2908 I.getType(), CondShadow,
2909 ShadowSel,
I.getIterator())
2911 if (ShouldTrackOrigins) {
2913 Shadows.push_back(CondShadow);
2914 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2916 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2920void DFSanVisitor::visitMemSetInst(MemSetInst &
I) {
2922 Value *ValShadow = DFSF.getShadow(
I.getValue());
2923 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2924 ? DFSF.getOrigin(
I.getValue())
2925 : DFSF.DFS.ZeroOrigin;
2927 {ValShadow, ValOrigin, I.getDest(),
2928 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2931void DFSanVisitor::visitMemTransferInst(MemTransferInst &
I) {
2936 if (DFSF.DFS.shouldTrackOrigins()) {
2938 DFSF.DFS.DFSanMemOriginTransferFn,
2939 {I.getArgOperand(0), I.getArgOperand(1),
2940 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2943 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2944 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2946 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2947 DFSF.DFS.ShadowWidthBytes));
2949 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2950 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2951 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2952 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2955 DFSF.DFS.DFSanMemTransferCallbackFn,
2956 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2960void DFSanVisitor::visitBranchInst(BranchInst &BR) {
2964 DFSF.addConditionalCallbacksIfEnabled(BR, BR.
getCondition());
2967void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
2968 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2974 RetVal =
I->getOperand(0);
2977 return I->isMustTailCall();
2982void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
2991 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2997 if (DFSF.DFS.shouldTrackOrigins()) {
3004void DFSanVisitor::addShadowArguments(Function &
F, CallBase &CB,
3005 std::vector<Value *> &Args,
3007 FunctionType *FT =
F.getFunctionType();
3012 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3014 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3017 if (FT->isVarArg()) {
3018 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3019 CB.
arg_size() - FT->getNumParams());
3020 auto *LabelVAAlloca =
3021 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3024 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3027 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3035 if (!FT->getReturnType()->isVoidTy()) {
3036 if (!DFSF.LabelReturnAlloca) {
3037 DFSF.LabelReturnAlloca =
new AllocaInst(
3038 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3041 Args.push_back(DFSF.LabelReturnAlloca);
3045void DFSanVisitor::addOriginArguments(Function &
F, CallBase &CB,
3046 std::vector<Value *> &Args,
3048 FunctionType *FT =
F.getFunctionType();
3053 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3054 Args.push_back(DFSF.getOrigin(*
I));
3057 if (FT->isVarArg()) {
3059 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3060 auto *OriginVAAlloca =
3061 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3064 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3073 if (!FT->getReturnType()->isVoidTy()) {
3074 if (!DFSF.OriginReturnAlloca) {
3075 DFSF.OriginReturnAlloca =
new AllocaInst(
3076 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3079 Args.push_back(DFSF.OriginReturnAlloca);
3083bool DFSanVisitor::visitWrappedCallBase(Function &
F, CallBase &CB) {
3085 switch (DFSF.DFS.getWrapperKind(&
F)) {
3086 case DataFlowSanitizer::WK_Warning:
3088 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3090 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3091 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3092 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3094 case DataFlowSanitizer::WK_Discard:
3096 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3097 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3098 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3100 case DataFlowSanitizer::WK_Functional:
3102 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3103 visitInstOperands(CB);
3105 case DataFlowSanitizer::WK_Custom:
3113 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3114 FunctionType *FT =
F.getFunctionType();
3115 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3116 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3117 CustomFName +=
F.getName();
3119 CustomFName, CustomFn.TransformedType);
3121 CustomFn->copyAttributesFrom(&
F);
3124 if (!FT->getReturnType()->isVoidTy()) {
3125 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3129 std::vector<Value *>
Args;
3133 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3138 const unsigned ShadowArgStart =
Args.size();
3139 addShadowArguments(
F, CB, Args, IRB);
3142 const unsigned OriginArgStart =
Args.size();
3143 if (ShouldTrackOrigins)
3144 addOriginArguments(
F, CB, Args, IRB);
3149 CallInst *CustomCI = IRB.
CreateCall(CustomF, Args);
3157 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3158 const unsigned ArgNo = ShadowArgStart +
N;
3160 DFSF.DFS.PrimitiveShadowTy)
3162 if (ShouldTrackOrigins) {
3163 const unsigned OriginArgNo = OriginArgStart +
N;
3171 if (!FT->getReturnType()->isVoidTy()) {
3172 LoadInst *LabelLoad =
3173 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3174 DFSF.setShadow(CustomCI,
3175 DFSF.expandFromPrimitiveShadow(
3176 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3177 if (ShouldTrackOrigins) {
3178 LoadInst *OriginLoad =
3179 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3180 DFSF.setOrigin(CustomCI, OriginLoad);
3192 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3193 uint32_t OrderingTable[NumOrderings] = {};
3195 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3196 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3197 OrderingTable[(int)AtomicOrderingCABI::consume] =
3198 (
int)AtomicOrderingCABI::acquire;
3199 OrderingTable[(int)AtomicOrderingCABI::release] =
3200 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3201 (int)AtomicOrderingCABI::acq_rel;
3202 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3203 (
int)AtomicOrderingCABI::seq_cst;
3208void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3219 Value *NewOrdering =
3224 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3230 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3231 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3235 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3236 uint32_t OrderingTable[NumOrderings] = {};
3238 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3239 OrderingTable[(
int)AtomicOrderingCABI::release] =
3240 (int)AtomicOrderingCABI::release;
3241 OrderingTable[(int)AtomicOrderingCABI::consume] =
3242 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3243 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3244 (
int)AtomicOrderingCABI::acq_rel;
3245 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3246 (
int)AtomicOrderingCABI::seq_cst;
3251void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3259 Value *NewOrdering =
3267 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3268 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3271void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3287 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3288 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3292 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3293 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3296void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3310 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3312 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3316 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3317 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3318 TargetPtr, ExpectedPtr, DesiredPtr,
3319 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3322void DFSanVisitor::visitCallBase(CallBase &CB) {
3325 visitInstOperands(CB);
3340 case LibFunc_atomic_load:
3342 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3346 visitLibAtomicLoad(CB);
3348 case LibFunc_atomic_store:
3349 visitLibAtomicStore(CB);
3357 if (
F &&
F->hasName() && !
F->isVarArg()) {
3358 if (
F->getName() ==
"__atomic_exchange") {
3359 visitLibAtomicExchange(CB);
3362 if (
F->getName() ==
"__atomic_compare_exchange") {
3363 visitLibAtomicCompareExchange(CB);
3368 DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
3370 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3371 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3376 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3378 const DataLayout &
DL = getDataLayout();
3381 unsigned ArgOffset = 0;
3382 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3383 if (ShouldTrackOrigins) {
3386 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3387 !DFSF.DFS.isZeroShadow(ArgShadow))
3389 DFSF.getArgOriginTLS(
I, IRB));
3393 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3399 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3407 if (
II->getNormalDest()->getSinglePredecessor()) {
3408 Next = &
II->getNormalDest()->front();
3425 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3428 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3430 LoadInst *LI = NextIRB.CreateAlignedLoad(
3431 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3433 DFSF.SkipInsts.insert(LI);
3434 DFSF.setShadow(&CB, LI);
3435 DFSF.NonZeroChecks.push_back(LI);
3438 if (ShouldTrackOrigins) {
3439 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3440 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3441 DFSF.SkipInsts.insert(LI);
3442 DFSF.setOrigin(&CB, LI);
3445 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3449void DFSanVisitor::visitPHINode(PHINode &PN) {
3450 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3456 for (BasicBlock *BB : PN.
blocks())
3459 DFSF.setShadow(&PN, ShadowPN);
3461 PHINode *OriginPN =
nullptr;
3462 if (DFSF.DFS.shouldTrackOrigins()) {
3466 for (BasicBlock *BB : PN.
blocks())
3468 DFSF.setOrigin(&PN, OriginPN);
3471 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3484 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.
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.