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 *ShadowOffset = getShadowOffset(Addr, IRB);
1961 return getShadowAddress(Addr, Pos, ShadowOffset);
1966 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1967 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1974 if (DFS.isZeroShadow(V1))
1975 return collapseToPrimitiveShadow(V2, Pos);
1976 if (DFS.isZeroShadow(V2))
1977 return collapseToPrimitiveShadow(V1, Pos);
1979 return collapseToPrimitiveShadow(V1, Pos);
1981 auto V1Elems = ShadowElements.
find(V1);
1982 auto V2Elems = ShadowElements.
find(V2);
1983 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1985 return collapseToPrimitiveShadow(V1, Pos);
1988 return collapseToPrimitiveShadow(V2, Pos);
1990 }
else if (V1Elems != ShadowElements.
end()) {
1991 if (V1Elems->second.count(V2))
1992 return collapseToPrimitiveShadow(V1, Pos);
1993 }
else if (V2Elems != ShadowElements.
end()) {
1994 if (V2Elems->second.count(V1))
1995 return collapseToPrimitiveShadow(V2, Pos);
1998 auto Key = std::make_pair(V1, V2);
2001 CachedShadow &CCS = CachedShadows[
Key];
2002 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2006 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2007 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2010 CCS.Block = Pos->getParent();
2011 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2013 std::set<Value *> UnionElems;
2014 if (V1Elems != ShadowElements.
end()) {
2015 UnionElems = V1Elems->second;
2017 UnionElems.insert(V1);
2019 if (V2Elems != ShadowElements.
end()) {
2020 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2022 UnionElems.insert(V2);
2024 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2032Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
2034 return DFS.getZeroShadow(Inst);
2038 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2041 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2045void DFSanVisitor::visitInstOperands(Instruction &
I) {
2046 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2047 DFSF.setShadow(&
I, CombinedShadow);
2048 visitInstOperandOrigins(
I);
2051Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2052 const std::vector<Value *> &Origins,
2054 ConstantInt *Zero) {
2055 assert(Shadows.size() == Origins.size());
2056 size_t Size = Origins.size();
2058 return DFS.ZeroOrigin;
2059 Value *Origin =
nullptr;
2061 Zero = DFS.ZeroPrimitiveShadow;
2062 for (
size_t I = 0;
I !=
Size; ++
I) {
2063 Value *OpOrigin = Origins[
I];
2065 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2071 Value *OpShadow = Shadows[
I];
2072 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2077 return Origin ? Origin : DFS.ZeroOrigin;
2080Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2082 std::vector<Value *> Shadows(
Size);
2083 std::vector<Value *> Origins(
Size);
2084 for (
unsigned I = 0;
I !=
Size; ++
I) {
2088 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2091void DFSanVisitor::visitInstOperandOrigins(Instruction &
I) {
2092 if (!DFSF.DFS.shouldTrackOrigins())
2094 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2095 DFSF.setOrigin(&
I, CombinedOrigin);
2098Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2100 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2103Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2108bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2110 if (GV->isConstant() && GV->
hasName())
2111 return DFS.CombineTaintLookupTableNames.
count(GV->
getName());
2116bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t
Size,
2117 Align InstAlignment) {
2141 Value **OriginAddr) {
2144 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2148std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2149 Value *ShadowAddr,
Value *OriginAddr, uint64_t
Size, Align ShadowAlign,
2151 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2152 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2154 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2157 std::vector<Value *> Shadows;
2158 std::vector<Value *> Origins;
2171 Type *WideShadowTy =
2172 ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) :
Type::getInt64Ty(*DFS.Ctx);
2175 Value *CombinedWideShadow =
2179 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2181 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2182 if (BytesPerWideShadow > 4) {
2183 assert(BytesPerWideShadow == 8);
2191 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2192 Shadows.push_back(WideShadow);
2193 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2195 Shadows.push_back(WideShadowLo);
2196 Origins.push_back(Origin);
2198 Shadows.push_back(WideShadow);
2199 Origins.push_back(Origin);
2203 if (ShouldTrackOrigins)
2204 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2211 for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2212 ByteOfs += BytesPerWideShadow) {
2213 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2214 ConstantInt::get(DFS.IntptrTy, 1));
2215 Value *NextWideShadow =
2217 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2218 if (ShouldTrackOrigins) {
2219 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2220 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2223 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2226 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2228 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2230 ? combineOrigins(Shadows, Origins, Pos,
2235std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2237 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2241 const auto SI = AllocaShadowMap.
find(AI);
2242 if (SI != AllocaShadowMap.
end()) {
2245 const auto OI = AllocaOriginMap.
find(AI);
2246 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2247 return {ShadowLI, ShouldTrackOrigins
2254 SmallVector<const Value *, 2> Objs;
2256 bool AllConstants =
true;
2257 for (
const Value *Obj : Objs) {
2263 AllConstants =
false;
2267 return {DFS.ZeroPrimitiveShadow,
2268 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2271 return {DFS.ZeroPrimitiveShadow,
2272 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2276 if (ShouldTrackOrigins &&
2277 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2280 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2281 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2284 DFS.PrimitiveShadowTy),
2289 Value *ShadowAddr, *OriginAddr;
2290 std::tie(ShadowAddr, OriginAddr) =
2291 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2293 const Align ShadowAlign = getShadowAlign(InstAlignment);
2294 const Align OriginAlign = getOriginAlign(InstAlignment);
2295 Value *Origin =
nullptr;
2296 if (ShouldTrackOrigins) {
2305 LoadInst *LI =
new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr,
"", Pos);
2307 return {LI, Origin};
2311 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2312 ConstantInt::get(DFS.IntptrTy, 1));
2317 return {combineShadows(Load, Load1, Pos), Origin};
2320 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2322 if (HasSizeForFastPath)
2323 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2324 OriginAlign, Origin, Pos);
2328 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2330 return {FallbackCall, Origin};
2333std::pair<Value *, Value *>
2334DFSanFunction::loadShadowOrigin(
Value *Addr, uint64_t
Size, Align InstAlignment,
2336 Value *PrimitiveShadow, *Origin;
2337 std::tie(PrimitiveShadow, Origin) =
2338 loadShadowOriginSansLoadTracking(Addr,
Size, InstAlignment, Pos);
2339 if (DFS.shouldTrackOrigins()) {
2343 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2344 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2347 return {PrimitiveShadow, Origin};
2368 if (!V->getType()->isPointerTy())
2377 V =
GEP->getPointerOperand();
2380 if (!V->getType()->isPointerTy())
2385 }
while (Visited.
insert(V).second);
2390void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2394 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2395 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2410 Pos = std::next(Pos);
2412 std::vector<Value *> Shadows;
2413 std::vector<Value *> Origins;
2414 Value *PrimitiveShadow, *Origin;
2415 std::tie(PrimitiveShadow, Origin) =
2417 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2418 if (ShouldTrackOrigins) {
2419 Shadows.push_back(PrimitiveShadow);
2420 Origins.push_back(Origin);
2423 DFSF.isLookupTableConstant(
2426 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2427 if (ShouldTrackOrigins) {
2428 Shadows.push_back(PtrShadow);
2432 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2433 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2436 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2437 DFSF.setShadow(&LI, Shadow);
2439 if (ShouldTrackOrigins) {
2440 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2447 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2452 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2455Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2457 assert(DFS.shouldTrackOrigins());
2458 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2462 if (!DFS.shouldTrackOrigins())
2464 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2468 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2469 const DataLayout &
DL =
F->getDataLayout();
2470 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2471 if (IntptrSize == OriginSize)
2473 assert(IntptrSize == OriginSize * 2);
2479 Value *StoreOriginAddr,
2480 uint64_t StoreOriginSize, Align Alignment) {
2481 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2482 const DataLayout &
DL =
F->getDataLayout();
2483 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2484 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2486 assert(IntptrSize >= OriginSize);
2489 Align CurrentAlignment = Alignment;
2490 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2491 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2492 Value *IntptrStoreOriginPtr =
2494 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2497 : IntptrStoreOriginPtr;
2499 Ofs += IntptrSize / OriginSize;
2500 CurrentAlignment = IntptrAlignment;
2504 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2514 const Twine &Name) {
2515 Type *VTy =
V->getType();
2520 return IRB.
CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2525 Value *StoreOriginAddr, Align InstAlignment) {
2528 const Align OriginAlignment = getOriginAlign(InstAlignment);
2529 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2532 if (!ConstantShadow->isZeroValue())
2533 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2538 if (shouldInstrumentWithCall()) {
2540 DFS.DFSanMaybeStoreOriginFn,
2541 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2543 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2544 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2546 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2548 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2554void DFSanFunction::storeZeroPrimitiveShadow(
Value *Addr, uint64_t
Size,
2558 IntegerType *ShadowTy =
2560 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2561 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2567void DFSanFunction::storePrimitiveShadowOrigin(
Value *Addr, uint64_t
Size,
2568 Align InstAlignment,
2569 Value *PrimitiveShadow,
2572 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2575 const auto SI = AllocaShadowMap.
find(AI);
2576 if (SI != AllocaShadowMap.
end()) {
2582 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2583 const auto OI = AllocaOriginMap.
find(AI);
2584 assert(OI != AllocaOriginMap.
end() && Origin);
2591 const Align ShadowAlign = getShadowAlign(InstAlignment);
2592 if (DFS.isZeroShadow(PrimitiveShadow)) {
2593 storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign, Pos);
2598 Value *ShadowAddr, *OriginAddr;
2599 std::tie(ShadowAddr, OriginAddr) =
2600 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2602 const unsigned ShadowVecSize = 8;
2603 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2604 "Shadow vector is too large!");
2607 uint64_t LeftSize =
Size;
2608 if (LeftSize >= ShadowVecSize) {
2612 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2614 ShadowVec, PrimitiveShadow,
2615 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx),
I));
2618 Value *CurShadowVecAddr =
2621 LeftSize -= ShadowVecSize;
2623 }
while (LeftSize >= ShadowVecSize);
2626 while (LeftSize > 0) {
2627 Value *CurShadowAddr =
2634 if (ShouldTrackOrigins) {
2635 storeOrigin(Pos, Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2657void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2658 auto &
DL =
SI.getDataLayout();
2659 Value *Val =
SI.getValueOperand();
2672 const bool ShouldTrackOrigins =
2673 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2674 std::vector<Value *> Shadows;
2675 std::vector<Value *> Origins;
2678 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2680 if (ShouldTrackOrigins) {
2681 Shadows.push_back(Shadow);
2682 Origins.push_back(DFSF.getOrigin(Val));
2685 Value *PrimitiveShadow;
2687 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2688 if (ShouldTrackOrigins) {
2689 Shadows.push_back(PtrShadow);
2690 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2692 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2694 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2696 Value *Origin =
nullptr;
2697 if (ShouldTrackOrigins)
2698 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2699 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2700 PrimitiveShadow, Origin,
SI.getIterator());
2703 Value *Addr =
SI.getPointerOperand();
2705 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2710void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &
I) {
2713 Value *Val =
I.getOperand(1);
2714 const auto &
DL =
I.getDataLayout();
2722 Value *Addr =
I.getOperand(0);
2723 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2724 DFSF.storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign,
I.getIterator());
2725 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2726 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2729void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &
I) {
2730 visitCASOrRMW(
I.getAlign(),
I);
2736void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2737 visitCASOrRMW(
I.getAlign(),
I);
2743void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2744 visitInstOperands(UO);
2747void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2748 visitInstOperands(BO);
2751void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2758 visitInstOperands(BCI);
2761void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2763void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2764 visitInstOperands(CI);
2767 Value *CombinedShadow = DFSF.getShadow(&CI);
2769 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2774void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2786 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2787 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2790void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2792 DFSF.isLookupTableConstant(
2794 visitInstOperands(GEPI);
2801 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2802 if (DFSF.DFS.shouldTrackOrigins())
2803 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2806void DFSanVisitor::visitExtractElementInst(ExtractElementInst &
I) {
2807 visitInstOperands(
I);
2810void DFSanVisitor::visitInsertElementInst(InsertElementInst &
I) {
2811 visitInstOperands(
I);
2814void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &
I) {
2815 visitInstOperands(
I);
2818void DFSanVisitor::visitExtractValueInst(ExtractValueInst &
I) {
2820 Value *Agg =
I.getAggregateOperand();
2821 Value *AggShadow = DFSF.getShadow(Agg);
2823 DFSF.setShadow(&
I, ResShadow);
2824 visitInstOperandOrigins(
I);
2827void DFSanVisitor::visitInsertValueInst(InsertValueInst &
I) {
2829 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2830 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2832 DFSF.setShadow(&
I, Res);
2833 visitInstOperandOrigins(
I);
2836void DFSanVisitor::visitAllocaInst(AllocaInst &
I) {
2837 bool AllLoadsStores =
true;
2838 for (User *U :
I.users()) {
2843 if (
SI->getPointerOperand() == &
I)
2847 AllLoadsStores =
false;
2850 if (AllLoadsStores) {
2852 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2853 if (DFSF.DFS.shouldTrackOrigins()) {
2854 DFSF.AllocaOriginMap[&
I] =
2858 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2859 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2862void DFSanVisitor::visitSelectInst(SelectInst &
I) {
2863 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2864 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2865 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2866 Value *ShadowSel =
nullptr;
2867 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2868 std::vector<Value *> Shadows;
2869 std::vector<Value *> Origins;
2871 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2872 Value *FalseOrigin =
2873 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2875 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2878 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2879 FalseShadow,
I.getIterator());
2880 if (ShouldTrackOrigins) {
2881 Shadows.push_back(TrueShadow);
2882 Shadows.push_back(FalseShadow);
2883 Origins.push_back(TrueOrigin);
2884 Origins.push_back(FalseOrigin);
2887 if (TrueShadow == FalseShadow) {
2888 ShadowSel = TrueShadow;
2889 if (ShouldTrackOrigins) {
2890 Shadows.push_back(TrueShadow);
2891 Origins.push_back(TrueOrigin);
2895 "",
I.getIterator());
2896 if (ShouldTrackOrigins) {
2897 Shadows.push_back(ShadowSel);
2899 FalseOrigin,
"",
I.getIterator()));
2904 I.getType(), CondShadow,
2905 ShadowSel,
I.getIterator())
2907 if (ShouldTrackOrigins) {
2909 Shadows.push_back(CondShadow);
2910 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2912 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2916void DFSanVisitor::visitMemSetInst(MemSetInst &
I) {
2918 Value *ValShadow = DFSF.getShadow(
I.getValue());
2919 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2920 ? DFSF.getOrigin(
I.getValue())
2921 : DFSF.DFS.ZeroOrigin;
2923 {ValShadow, ValOrigin, I.getDest(),
2924 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2927void DFSanVisitor::visitMemTransferInst(MemTransferInst &
I) {
2932 if (DFSF.DFS.shouldTrackOrigins()) {
2934 DFSF.DFS.DFSanMemOriginTransferFn,
2935 {I.getArgOperand(0), I.getArgOperand(1),
2936 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2939 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2940 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2942 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2943 DFSF.DFS.ShadowWidthBytes));
2945 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2946 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2947 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2948 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2951 DFSF.DFS.DFSanMemTransferCallbackFn,
2952 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2956void DFSanVisitor::visitBranchInst(BranchInst &BR) {
2960 DFSF.addConditionalCallbacksIfEnabled(BR, BR.
getCondition());
2963void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
2964 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2970 RetVal =
I->getOperand(0);
2973 return I->isMustTailCall();
2978void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
2987 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2993 if (DFSF.DFS.shouldTrackOrigins()) {
3000void DFSanVisitor::addShadowArguments(Function &
F, CallBase &CB,
3001 std::vector<Value *> &Args,
3003 FunctionType *FT =
F.getFunctionType();
3008 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3010 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3013 if (FT->isVarArg()) {
3014 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3015 CB.
arg_size() - FT->getNumParams());
3016 auto *LabelVAAlloca =
3017 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3020 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3023 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3031 if (!FT->getReturnType()->isVoidTy()) {
3032 if (!DFSF.LabelReturnAlloca) {
3033 DFSF.LabelReturnAlloca =
new AllocaInst(
3034 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3037 Args.push_back(DFSF.LabelReturnAlloca);
3041void DFSanVisitor::addOriginArguments(Function &
F, CallBase &CB,
3042 std::vector<Value *> &Args,
3044 FunctionType *FT =
F.getFunctionType();
3049 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3050 Args.push_back(DFSF.getOrigin(*
I));
3053 if (FT->isVarArg()) {
3055 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3056 auto *OriginVAAlloca =
3057 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3060 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3069 if (!FT->getReturnType()->isVoidTy()) {
3070 if (!DFSF.OriginReturnAlloca) {
3071 DFSF.OriginReturnAlloca =
new AllocaInst(
3072 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3075 Args.push_back(DFSF.OriginReturnAlloca);
3079bool DFSanVisitor::visitWrappedCallBase(Function &
F, CallBase &CB) {
3081 switch (DFSF.DFS.getWrapperKind(&
F)) {
3082 case DataFlowSanitizer::WK_Warning:
3084 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3086 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3087 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3088 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3090 case DataFlowSanitizer::WK_Discard:
3092 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3093 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3094 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3096 case DataFlowSanitizer::WK_Functional:
3098 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3099 visitInstOperands(CB);
3101 case DataFlowSanitizer::WK_Custom:
3109 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3110 FunctionType *FT =
F.getFunctionType();
3111 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3112 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3113 CustomFName +=
F.getName();
3115 CustomFName, CustomFn.TransformedType);
3117 CustomFn->copyAttributesFrom(&
F);
3120 if (!FT->getReturnType()->isVoidTy()) {
3121 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3125 std::vector<Value *>
Args;
3129 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3134 const unsigned ShadowArgStart =
Args.size();
3135 addShadowArguments(
F, CB, Args, IRB);
3138 const unsigned OriginArgStart =
Args.size();
3139 if (ShouldTrackOrigins)
3140 addOriginArguments(
F, CB, Args, IRB);
3145 CallInst *CustomCI = IRB.
CreateCall(CustomF, Args);
3153 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3154 const unsigned ArgNo = ShadowArgStart +
N;
3156 DFSF.DFS.PrimitiveShadowTy)
3158 if (ShouldTrackOrigins) {
3159 const unsigned OriginArgNo = OriginArgStart +
N;
3167 if (!FT->getReturnType()->isVoidTy()) {
3168 LoadInst *LabelLoad =
3169 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3170 DFSF.setShadow(CustomCI,
3171 DFSF.expandFromPrimitiveShadow(
3172 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3173 if (ShouldTrackOrigins) {
3174 LoadInst *OriginLoad =
3175 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3176 DFSF.setOrigin(CustomCI, OriginLoad);
3188 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3189 uint32_t OrderingTable[NumOrderings] = {};
3191 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3192 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3193 OrderingTable[(int)AtomicOrderingCABI::consume] =
3194 (
int)AtomicOrderingCABI::acquire;
3195 OrderingTable[(int)AtomicOrderingCABI::release] =
3196 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3197 (int)AtomicOrderingCABI::acq_rel;
3198 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3199 (
int)AtomicOrderingCABI::seq_cst;
3204void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3215 Value *NewOrdering =
3220 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3226 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3227 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3231 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3232 uint32_t OrderingTable[NumOrderings] = {};
3234 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3235 OrderingTable[(
int)AtomicOrderingCABI::release] =
3236 (int)AtomicOrderingCABI::release;
3237 OrderingTable[(int)AtomicOrderingCABI::consume] =
3238 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3239 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3240 (
int)AtomicOrderingCABI::acq_rel;
3241 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3242 (
int)AtomicOrderingCABI::seq_cst;
3247void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3255 Value *NewOrdering =
3263 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3264 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3267void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3283 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3284 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3288 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3289 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3292void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3306 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3308 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3312 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3313 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3314 TargetPtr, ExpectedPtr, DesiredPtr,
3315 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3318void DFSanVisitor::visitCallBase(CallBase &CB) {
3321 visitInstOperands(CB);
3336 case LibFunc_atomic_load:
3338 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3342 visitLibAtomicLoad(CB);
3344 case LibFunc_atomic_store:
3345 visitLibAtomicStore(CB);
3353 if (
F &&
F->hasName() && !
F->isVarArg()) {
3354 if (
F->getName() ==
"__atomic_exchange") {
3355 visitLibAtomicExchange(CB);
3358 if (
F->getName() ==
"__atomic_compare_exchange") {
3359 visitLibAtomicCompareExchange(CB);
3364 DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
3366 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3367 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3372 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3374 const DataLayout &
DL = getDataLayout();
3377 unsigned ArgOffset = 0;
3378 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3379 if (ShouldTrackOrigins) {
3382 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3383 !DFSF.DFS.isZeroShadow(ArgShadow))
3385 DFSF.getArgOriginTLS(
I, IRB));
3389 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3395 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3403 if (
II->getNormalDest()->getSinglePredecessor()) {
3404 Next = &
II->getNormalDest()->front();
3421 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3424 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3426 LoadInst *LI = NextIRB.CreateAlignedLoad(
3427 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3429 DFSF.SkipInsts.insert(LI);
3430 DFSF.setShadow(&CB, LI);
3431 DFSF.NonZeroChecks.push_back(LI);
3434 if (ShouldTrackOrigins) {
3435 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3436 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3437 DFSF.SkipInsts.insert(LI);
3438 DFSF.setOrigin(&CB, LI);
3441 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3445void DFSanVisitor::visitPHINode(PHINode &PN) {
3446 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3452 for (BasicBlock *BB : PN.
blocks())
3455 DFSF.setShadow(&PN, ShadowPN);
3457 PHINode *OriginPN =
nullptr;
3458 if (DFSF.DFS.shouldTrackOrigins()) {
3462 for (BasicBlock *BB : PN.
blocks())
3464 DFSF.setOrigin(&PN, OriginPN);
3467 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3480 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, 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.