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."),
266 Type *GType =
G.getValueType();
269 if (!SGType->isLiteral())
270 return SGType->getName();
272 return "<unknown type>";
281struct MemoryMapParams {
319 std::unique_ptr<SpecialCaseList> SCL;
322 DFSanABIList() =
default;
324 void set(std::unique_ptr<SpecialCaseList>
List) { SCL = std::move(
List); }
328 bool isIn(
const Function &
F, StringRef Category)
const {
329 return isIn(*
F.getParent(), Category) ||
330 SCL->inSection(
"dataflow",
"fun",
F.getName(), Category);
337 bool isIn(
const GlobalAlias &GA, StringRef Category)
const {
342 return SCL->inSection(
"dataflow",
"fun", GA.
getName(), Category);
344 return SCL->inSection(
"dataflow",
"global", GA.
getName(), Category) ||
350 bool isIn(
const Module &M, StringRef Category)
const {
351 return SCL->inSection(
"dataflow",
"src",
M.getModuleIdentifier(), Category);
358struct TransformedFunction {
359 TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
360 const std::vector<unsigned> &ArgumentIndexMapping)
361 : OriginalType(OriginalType), TransformedType(TransformedType),
362 ArgumentIndexMapping(ArgumentIndexMapping) {}
365 TransformedFunction(
const TransformedFunction &) =
delete;
366 TransformedFunction &operator=(
const TransformedFunction &) =
delete;
369 TransformedFunction(TransformedFunction &&) =
default;
370 TransformedFunction &operator=(TransformedFunction &&) =
default;
373 FunctionType *OriginalType;
376 FunctionType *TransformedType;
383 std::vector<unsigned> ArgumentIndexMapping;
390transformFunctionAttributes(
const TransformedFunction &TransformedFunction,
394 std::vector<llvm::AttributeSet> ArgumentAttributes(
395 TransformedFunction.TransformedType->getNumParams());
400 for (
unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
402 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[
I];
403 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttrs(
I);
407 for (
unsigned I = TransformedFunction.OriginalType->getNumParams(),
408 IE = CallSiteAttrs.getNumAttrSets();
410 ArgumentAttributes.push_back(CallSiteAttrs.getParamAttrs(
I));
413 return AttributeList::get(Ctx, CallSiteAttrs.getFnAttrs(),
414 CallSiteAttrs.getRetAttrs(),
418class DataFlowSanitizer {
419 friend struct DFSanFunction;
420 friend class DFSanVisitor;
422 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
424 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
452 IntegerType *OriginTy;
454 ConstantInt *ZeroOrigin;
456 IntegerType *PrimitiveShadowTy;
458 IntegerType *IntptrTy;
459 ConstantInt *ZeroPrimitiveShadow;
465 FunctionType *DFSanUnionLoadFnTy;
466 FunctionType *DFSanLoadLabelAndOriginFnTy;
467 FunctionType *DFSanUnimplementedFnTy;
468 FunctionType *DFSanWrapperExternWeakNullFnTy;
469 FunctionType *DFSanSetLabelFnTy;
470 FunctionType *DFSanNonzeroLabelFnTy;
471 FunctionType *DFSanVarargWrapperFnTy;
472 FunctionType *DFSanConditionalCallbackFnTy;
473 FunctionType *DFSanConditionalCallbackOriginFnTy;
474 FunctionType *DFSanReachesFunctionCallbackFnTy;
475 FunctionType *DFSanReachesFunctionCallbackOriginFnTy;
476 FunctionType *DFSanCmpCallbackFnTy;
477 FunctionType *DFSanLoadStoreCallbackFnTy;
478 FunctionType *DFSanMemTransferCallbackFnTy;
479 FunctionType *DFSanChainOriginFnTy;
480 FunctionType *DFSanChainOriginIfTaintedFnTy;
481 FunctionType *DFSanMemOriginTransferFnTy;
482 FunctionType *DFSanMemShadowOriginTransferFnTy;
483 FunctionType *DFSanMemShadowOriginConditionalExchangeFnTy;
484 FunctionType *DFSanMaybeStoreOriginFnTy;
485 FunctionCallee DFSanUnionLoadFn;
486 FunctionCallee DFSanLoadLabelAndOriginFn;
487 FunctionCallee DFSanUnimplementedFn;
488 FunctionCallee DFSanWrapperExternWeakNullFn;
489 FunctionCallee DFSanSetLabelFn;
490 FunctionCallee DFSanNonzeroLabelFn;
491 FunctionCallee DFSanVarargWrapperFn;
492 FunctionCallee DFSanLoadCallbackFn;
493 FunctionCallee DFSanStoreCallbackFn;
494 FunctionCallee DFSanMemTransferCallbackFn;
495 FunctionCallee DFSanConditionalCallbackFn;
496 FunctionCallee DFSanConditionalCallbackOriginFn;
497 FunctionCallee DFSanReachesFunctionCallbackFn;
498 FunctionCallee DFSanReachesFunctionCallbackOriginFn;
499 FunctionCallee DFSanCmpCallbackFn;
500 FunctionCallee DFSanChainOriginFn;
501 FunctionCallee DFSanChainOriginIfTaintedFn;
502 FunctionCallee DFSanMemOriginTransferFn;
503 FunctionCallee DFSanMemShadowOriginTransferFn;
504 FunctionCallee DFSanMemShadowOriginConditionalExchangeFn;
505 FunctionCallee DFSanMaybeStoreOriginFn;
506 SmallPtrSet<Value *, 16> DFSanRuntimeFunctions;
507 MDNode *ColdCallWeights;
508 MDNode *OriginStoreWeights;
509 DFSanABIList ABIList;
510 DenseMap<Value *, Function *> UnwrappedFnMap;
511 AttributeMask ReadOnlyNoneAttrs;
512 StringSet<> CombineTaintLookupTableNames;
516 const MemoryMapParams *MapParams;
521 Value *ShadowOffset);
522 std::pair<Value *, Value *> getShadowOriginAddress(
Value *Addr,
525 bool isInstrumented(
const Function *
F);
526 bool isInstrumented(
const GlobalAlias *GA);
527 bool isForceZeroLabels(
const Function *
F);
528 TransformedFunction getCustomFunctionType(FunctionType *
T);
529 WrapperKind getWrapperKind(Function *
F);
530 void addGlobalNameSuffix(GlobalValue *GV);
531 void buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB, Function *
F);
532 Function *buildWrapperFunction(Function *
F, StringRef NewFName,
534 FunctionType *NewFT);
535 void initializeCallbackFunctions(
Module &M);
536 void initializeRuntimeFunctions(
Module &M);
537 bool initializeModule(
Module &M);
546 bool hasLoadSizeForFastPath(uint64_t
Size);
549 bool shouldTrackOrigins();
561 bool isZeroShadow(
Value *V);
572 const uint64_t NumOfElementsInArgOrgTLS =
ArgTLSSize / OriginWidthBytes;
575 DataFlowSanitizer(
const std::vector<std::string> &ABIListFiles);
578 llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI);
581struct DFSanFunction {
582 DataFlowSanitizer &DFS;
586 bool IsForceZeroLabels;
587 TargetLibraryInfo &TLI;
588 AllocaInst *LabelReturnAlloca =
nullptr;
589 AllocaInst *OriginReturnAlloca =
nullptr;
590 DenseMap<Value *, Value *> ValShadowMap;
591 DenseMap<Value *, Value *> ValOriginMap;
592 DenseMap<AllocaInst *, AllocaInst *> AllocaShadowMap;
593 DenseMap<AllocaInst *, AllocaInst *> AllocaOriginMap;
595 struct PHIFixupElement {
600 std::vector<PHIFixupElement> PHIFixups;
602 DenseSet<Instruction *> SkipInsts;
603 std::vector<Value *> NonZeroChecks;
605 struct CachedShadow {
610 DenseMap<std::pair<Value *, Value *>, CachedShadow> CachedShadows;
615 DenseMap<Value *, Value *> CachedCollapsedShadows;
616 DenseMap<Value *, std::set<Value *>> ShadowElements;
618 DFSanFunction(DataFlowSanitizer &DFS, Function *F,
bool IsNativeABI,
619 bool IsForceZeroLabels, TargetLibraryInfo &TLI)
620 : DFS(DFS), F(F), IsNativeABI(IsNativeABI),
621 IsForceZeroLabels(IsForceZeroLabels), TLI(TLI) {
639 Value *getRetvalOriginTLS();
642 void setOrigin(Instruction *
I,
Value *Origin);
644 Value *combineOperandOrigins(Instruction *Inst);
651 Value *combineOrigins(
const std::vector<Value *> &Shadows,
652 const std::vector<Value *> &Origins,
656 void setShadow(Instruction *
I,
Value *Shadow);
664 Value *combineOperandShadows(Instruction *Inst);
673 std::pair<Value *, Value *> loadShadowOrigin(
Value *Addr, uint64_t
Size,
677 void storePrimitiveShadowOrigin(
Value *Addr, uint64_t
Size,
678 Align InstAlignment,
Value *PrimitiveShadow,
697 void storeZeroPrimitiveShadow(
Value *Addr, uint64_t
Size, Align ShadowAlign,
700 Align getShadowAlign(Align InstAlignment);
704 void addConditionalCallbacksIfEnabled(Instruction &
I,
Value *Condition);
708 void addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB, Instruction &
I,
711 bool isLookupTableConstant(
Value *
P);
716 template <
class AggregateType>
717 Value *collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
723 Value *getShadowForTLSArgument(Argument *
A);
726 std::pair<Value *, Value *>
727 loadShadowFast(
Value *ShadowAddr,
Value *OriginAddr, uint64_t
Size,
728 Align ShadowAlign, Align OriginAlign,
Value *FirstOrigin,
731 Align getOriginAlign(Align InstAlignment);
742 bool useCallbackLoadLabelAndOrigin(uint64_t
Size, Align InstAlignment);
758 uint64_t StoreOriginSize, Align Alignment);
767 Align InstAlignment);
772 bool shouldInstrumentWithCall();
778 std::pair<Value *, Value *>
779 loadShadowOriginSansLoadTracking(
Value *Addr, uint64_t
Size,
782 int NumOriginStores = 0;
785class DFSanVisitor :
public InstVisitor<DFSanVisitor> {
789 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
791 const DataLayout &getDataLayout()
const {
792 return DFSF.F->getDataLayout();
796 void visitInstOperands(Instruction &
I);
798 void visitUnaryOperator(UnaryOperator &UO);
799 void visitBinaryOperator(BinaryOperator &BO);
800 void visitBitCastInst(BitCastInst &BCI);
801 void visitCastInst(CastInst &CI);
802 void visitCmpInst(CmpInst &CI);
803 void visitLandingPadInst(LandingPadInst &LPI);
804 void visitGetElementPtrInst(GetElementPtrInst &GEPI);
805 void visitLoadInst(LoadInst &LI);
806 void visitStoreInst(StoreInst &SI);
807 void visitAtomicRMWInst(AtomicRMWInst &
I);
808 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I);
809 void visitReturnInst(ReturnInst &RI);
810 void visitLibAtomicLoad(CallBase &CB);
811 void visitLibAtomicStore(CallBase &CB);
812 void visitLibAtomicExchange(CallBase &CB);
813 void visitLibAtomicCompareExchange(CallBase &CB);
814 void visitCallBase(CallBase &CB);
815 void visitPHINode(PHINode &PN);
816 void visitExtractElementInst(ExtractElementInst &
I);
817 void visitInsertElementInst(InsertElementInst &
I);
818 void visitShuffleVectorInst(ShuffleVectorInst &
I);
819 void visitExtractValueInst(ExtractValueInst &
I);
820 void visitInsertValueInst(InsertValueInst &
I);
821 void visitAllocaInst(AllocaInst &
I);
822 void visitSelectInst(SelectInst &
I);
823 void visitMemSetInst(MemSetInst &
I);
824 void visitMemTransferInst(MemTransferInst &
I);
825 void visitBranchInst(BranchInst &BR);
826 void visitSwitchInst(SwitchInst &SW);
829 void visitCASOrRMW(Align InstAlignment, Instruction &
I);
832 bool visitWrappedCallBase(Function &
F, CallBase &CB);
835 void visitInstOperandOrigins(Instruction &
I);
837 void addShadowArguments(Function &
F, CallBase &CB, std::vector<Value *> &Args,
840 void addOriginArguments(Function &
F, CallBase &CB, std::vector<Value *> &Args,
847bool LibAtomicFunction(
const Function &
F) {
853 if (!
F.hasName() ||
F.isVarArg())
855 switch (
F.arg_size()) {
857 return F.getName() ==
"__atomic_load" ||
F.getName() ==
"__atomic_store";
859 return F.getName() ==
"__atomic_exchange";
861 return F.getName() ==
"__atomic_compare_exchange";
869DataFlowSanitizer::DataFlowSanitizer(
870 const std::vector<std::string> &ABIListFiles) {
871 std::vector<std::string> AllABIListFiles(std::move(ABIListFiles));
880TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *
T) {
887 std::vector<unsigned> ArgumentIndexMapping;
888 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I) {
889 Type *ParamType =
T->getParamType(
I);
890 ArgumentIndexMapping.push_back(ArgTypes.
size());
893 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
896 ArgTypes.
push_back(PrimitiveShadowPtrTy);
897 Type *RetType =
T->getReturnType();
899 ArgTypes.
push_back(PrimitiveShadowPtrTy);
901 if (shouldTrackOrigins()) {
902 for (
unsigned I = 0,
E =
T->getNumParams();
I !=
E; ++
I)
910 return TransformedFunction(
911 T, FunctionType::get(
T->getReturnType(), ArgTypes,
T->isVarArg()),
912 ArgumentIndexMapping);
915bool DataFlowSanitizer::isZeroShadow(
Value *V) {
926bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t
Size) {
927 uint64_t ShadowSize =
Size * ShadowWidthBytes;
928 return ShadowSize % 8 == 0 || ShadowSize == 4;
931bool DataFlowSanitizer::shouldTrackOrigins() {
933 return ShouldTrackOrigins;
936Constant *DataFlowSanitizer::getZeroShadow(
Type *OrigTy) {
938 return ZeroPrimitiveShadow;
939 Type *ShadowTy = getShadowTy(OrigTy);
944 return getZeroShadow(
V->getType());
954 for (
unsigned Idx = 0; Idx < AT->getNumElements(); Idx++) {
957 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
964 for (
unsigned Idx = 0; Idx < ST->getNumElements(); Idx++) {
967 Shadow, Indices, ST->getElementType(Idx), PrimitiveShadow, IRB);
975bool DFSanFunction::shouldInstrumentWithCall() {
980Value *DFSanFunction::expandFromPrimitiveShadow(
Type *
T,
Value *PrimitiveShadow,
982 Type *ShadowTy = DFS.getShadowTy(
T);
985 return PrimitiveShadow;
987 if (DFS.isZeroShadow(PrimitiveShadow))
988 return DFS.getZeroShadow(ShadowTy);
991 SmallVector<unsigned, 4> Indices;
994 PrimitiveShadow, IRB);
997 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
1001template <
class AggregateType>
1002Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT,
Value *Shadow,
1004 if (!AT->getNumElements())
1005 return DFS.ZeroPrimitiveShadow;
1008 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1010 for (
unsigned Idx = 1; Idx < AT->getNumElements(); Idx++) {
1012 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1013 Aggregator = IRB.
CreateOr(Aggregator, ShadowInner);
1018Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1024 return collapseAggregateShadow<>(AT, Shadow, IRB);
1026 return collapseAggregateShadow<>(ST, Shadow, IRB);
1030Value *DFSanFunction::collapseToPrimitiveShadow(
Value *Shadow,
1037 Value *&CS = CachedCollapsedShadows[Shadow];
1042 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1044 CS = PrimitiveShadow;
1045 return PrimitiveShadow;
1048void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &
I,
1054 Value *CondShadow = getShadow(Condition);
1056 if (DFS.shouldTrackOrigins()) {
1057 Value *CondOrigin = getOrigin(Condition);
1058 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1059 {CondShadow, CondOrigin});
1061 CI = IRB.
CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1066void DFSanFunction::addReachesFunctionCallbacksIfEnabled(
IRBuilder<> &IRB,
1072 const DebugLoc &dbgloc =
I.getDebugLoc();
1073 Value *DataShadow = collapseToPrimitiveShadow(getShadow(
Data), IRB);
1074 ConstantInt *CILine;
1077 if (dbgloc.
get() ==
nullptr) {
1078 CILine = llvm::ConstantInt::get(
I.getContext(), llvm::APInt(32, 0));
1080 I.getFunction()->getParent()->getSourceFileName());
1082 CILine = llvm::ConstantInt::get(
I.getContext(),
1083 llvm::APInt(32, dbgloc.
getLine()));
1091 std::vector<Value *>
args;
1093 if (DFS.shouldTrackOrigins()) {
1095 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1096 CB = IRB.
CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn,
args);
1098 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1105Type *DataFlowSanitizer::getShadowTy(
Type *OrigTy) {
1107 return PrimitiveShadowTy;
1109 return PrimitiveShadowTy;
1111 return PrimitiveShadowTy;
1113 return ArrayType::get(getShadowTy(AT->getElementType()),
1114 AT->getNumElements());
1117 for (
unsigned I = 0,
N =
ST->getNumElements();
I <
N; ++
I)
1118 Elements.push_back(getShadowTy(
ST->getElementType(
I)));
1121 return PrimitiveShadowTy;
1124Type *DataFlowSanitizer::getShadowTy(
Value *V) {
1125 return getShadowTy(
V->getType());
1128bool DataFlowSanitizer::initializeModule(
Module &M) {
1129 Triple TargetTriple(
M.getTargetTriple());
1130 const DataLayout &
DL =
M.getDataLayout();
1134 switch (TargetTriple.getArch()) {
1149 Ctx = &
M.getContext();
1150 Int8Ptr = PointerType::getUnqual(*Ctx);
1152 OriginPtrTy = PointerType::getUnqual(*Ctx);
1154 PrimitiveShadowPtrTy = PointerType::getUnqual(*Ctx);
1155 IntptrTy =
DL.getIntPtrType(*Ctx);
1159 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1160 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1162 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1163 DFSanLoadLabelAndOriginFnTy =
1166 DFSanUnimplementedFnTy = FunctionType::get(
1167 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx),
false);
1168 Type *DFSanWrapperExternWeakNullArgs[2] = {Int8Ptr, Int8Ptr};
1169 DFSanWrapperExternWeakNullFnTy =
1170 FunctionType::get(Type::getVoidTy(*Ctx), DFSanWrapperExternWeakNullArgs,
1172 Type *DFSanSetLabelArgs[4] = {PrimitiveShadowTy, OriginTy,
1173 PointerType::getUnqual(*Ctx), IntptrTy};
1174 DFSanSetLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx),
1175 DFSanSetLabelArgs,
false);
1176 DFSanNonzeroLabelFnTy = FunctionType::get(Type::getVoidTy(*Ctx), {},
1178 DFSanVarargWrapperFnTy = FunctionType::get(
1179 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx),
false);
1180 DFSanConditionalCallbackFnTy =
1181 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1183 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1184 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1185 Type::getVoidTy(*Ctx), DFSanConditionalCallbackOriginArgs,
1187 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1189 DFSanReachesFunctionCallbackFnTy =
1190 FunctionType::get(Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1192 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1193 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1194 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1195 Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackOriginArgs,
1197 DFSanCmpCallbackFnTy =
1198 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1200 DFSanChainOriginFnTy =
1201 FunctionType::get(OriginTy, OriginTy,
false);
1202 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1203 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1204 OriginTy, DFSanChainOriginIfTaintedArgs,
false);
1206 Int8Ptr, IntptrTy, OriginTy};
1207 DFSanMaybeStoreOriginFnTy = FunctionType::get(
1208 Type::getVoidTy(*Ctx), DFSanMaybeStoreOriginArgs,
false);
1209 Type *DFSanMemOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1210 DFSanMemOriginTransferFnTy = FunctionType::get(
1211 Type::getVoidTy(*Ctx), DFSanMemOriginTransferArgs,
false);
1212 Type *DFSanMemShadowOriginTransferArgs[3] = {Int8Ptr, Int8Ptr, IntptrTy};
1213 DFSanMemShadowOriginTransferFnTy =
1214 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemShadowOriginTransferArgs,
1216 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1218 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1219 Type::getVoidTy(*Ctx), DFSanMemShadowOriginConditionalExchangeArgs,
1221 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1222 DFSanLoadStoreCallbackFnTy =
1223 FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs,
1225 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1226 DFSanMemTransferCallbackFnTy =
1227 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1230 ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1231 OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1235bool DataFlowSanitizer::isInstrumented(
const Function *
F) {
1236 return !ABIList.isIn(*
F,
"uninstrumented");
1239bool DataFlowSanitizer::isInstrumented(
const GlobalAlias *GA) {
1240 return !ABIList.isIn(*GA,
"uninstrumented");
1243bool DataFlowSanitizer::isForceZeroLabels(
const Function *
F) {
1244 return ABIList.isIn(*
F,
"force_zero_labels");
1247DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *
F) {
1248 if (ABIList.isIn(*
F,
"functional"))
1249 return WK_Functional;
1250 if (ABIList.isIn(*
F,
"discard"))
1252 if (ABIList.isIn(*
F,
"custom"))
1258void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) {
1259 std::string GVName = std::string(GV->
getName()), Suffix =
".dfsan";
1268 std::string SearchStr =
".symver " + GVName +
",";
1269 size_t Pos =
Asm.find(SearchStr);
1270 if (Pos != std::string::npos) {
1271 Asm.replace(Pos, SearchStr.size(),
".symver " + GVName + Suffix +
",");
1272 Pos =
Asm.find(
'@');
1274 if (Pos == std::string::npos)
1277 Asm.replace(Pos, 1, Suffix +
"@");
1282void DataFlowSanitizer::buildExternWeakCheckIfNeeded(
IRBuilder<> &IRB,
1292 std::vector<Value *>
Args;
1295 IRB.
CreateCall(DFSanWrapperExternWeakNullFn, Args);
1300DataFlowSanitizer::buildWrapperFunction(Function *
F, StringRef NewFName,
1302 FunctionType *NewFT) {
1303 FunctionType *FT =
F->getFunctionType();
1305 NewFName,
F->getParent());
1308 NewFT->getReturnType(), NewF->
getAttributes().getRetAttrs()));
1311 if (
F->isVarArg()) {
1314 IRBuilder<>(BB).CreateGlobalString(
F->getName()),
"", BB);
1315 new UnreachableInst(*Ctx, BB);
1317 auto ArgIt = pointer_iterator<Argument *>(NewF->
arg_begin());
1318 std::vector<Value *>
Args(ArgIt, ArgIt + FT->getNumParams());
1321 if (FT->getReturnType()->isVoidTy())
1331void DataFlowSanitizer::initializeRuntimeFunctions(
Module &M) {
1332 LLVMContext &
C =
M.getContext();
1335 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1336 AL =
AL.addFnAttribute(
1338 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1340 Mod->getOrInsertFunction(
"__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1344 AL =
AL.addFnAttribute(
C, Attribute::NoUnwind);
1345 AL =
AL.addFnAttribute(
1347 AL =
AL.addRetAttribute(
C, Attribute::ZExt);
1348 DFSanLoadLabelAndOriginFn =
Mod->getOrInsertFunction(
1349 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1351 DFSanUnimplementedFn =
1352 Mod->getOrInsertFunction(
"__dfsan_unimplemented", DFSanUnimplementedFnTy);
1353 DFSanWrapperExternWeakNullFn =
Mod->getOrInsertFunction(
1354 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1357 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1358 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1360 Mod->getOrInsertFunction(
"__dfsan_set_label", DFSanSetLabelFnTy, AL);
1362 DFSanNonzeroLabelFn =
1363 Mod->getOrInsertFunction(
"__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1364 DFSanVarargWrapperFn =
Mod->getOrInsertFunction(
"__dfsan_vararg_wrapper",
1365 DFSanVarargWrapperFnTy);
1368 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1369 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1370 DFSanChainOriginFn =
Mod->getOrInsertFunction(
"__dfsan_chain_origin",
1371 DFSanChainOriginFnTy, AL);
1375 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1376 AL =
AL.addParamAttribute(
M.getContext(), 1, Attribute::ZExt);
1377 AL =
AL.addRetAttribute(
M.getContext(), Attribute::ZExt);
1378 DFSanChainOriginIfTaintedFn =
Mod->getOrInsertFunction(
1379 "__dfsan_chain_origin_if_tainted", DFSanChainOriginIfTaintedFnTy, AL);
1381 DFSanMemOriginTransferFn =
Mod->getOrInsertFunction(
1382 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1384 DFSanMemShadowOriginTransferFn =
Mod->getOrInsertFunction(
1385 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1387 DFSanMemShadowOriginConditionalExchangeFn =
1388 Mod->getOrInsertFunction(
"__dfsan_mem_shadow_origin_conditional_exchange",
1389 DFSanMemShadowOriginConditionalExchangeFnTy);
1393 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1394 AL =
AL.addParamAttribute(
M.getContext(), 3, Attribute::ZExt);
1395 DFSanMaybeStoreOriginFn =
Mod->getOrInsertFunction(
1396 "__dfsan_maybe_store_origin", DFSanMaybeStoreOriginFnTy, AL);
1399 DFSanRuntimeFunctions.
insert(
1401 DFSanRuntimeFunctions.
insert(
1403 DFSanRuntimeFunctions.
insert(
1405 DFSanRuntimeFunctions.
insert(
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(
1438 DFSanMemShadowOriginConditionalExchangeFn.
getCallee()
1440 DFSanRuntimeFunctions.
insert(
1445void DataFlowSanitizer::initializeCallbackFunctions(
Module &M) {
1448 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1449 DFSanLoadCallbackFn =
Mod->getOrInsertFunction(
1450 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1454 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1455 DFSanStoreCallbackFn =
Mod->getOrInsertFunction(
1456 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1458 DFSanMemTransferCallbackFn =
Mod->getOrInsertFunction(
1459 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1462 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1463 DFSanCmpCallbackFn =
Mod->getOrInsertFunction(
"__dfsan_cmp_callback",
1464 DFSanCmpCallbackFnTy, AL);
1468 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1469 DFSanConditionalCallbackFn =
Mod->getOrInsertFunction(
1470 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1474 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1475 DFSanConditionalCallbackOriginFn =
1476 Mod->getOrInsertFunction(
"__dfsan_conditional_callback_origin",
1477 DFSanConditionalCallbackOriginFnTy, AL);
1481 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1482 DFSanReachesFunctionCallbackFn =
1483 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback",
1484 DFSanReachesFunctionCallbackFnTy, AL);
1488 AL =
AL.addParamAttribute(
M.getContext(), 0, Attribute::ZExt);
1489 DFSanReachesFunctionCallbackOriginFn =
1490 Mod->getOrInsertFunction(
"__dfsan_reaches_function_callback_origin",
1491 DFSanReachesFunctionCallbackOriginFnTy, AL);
1495bool DataFlowSanitizer::runImpl(
1496 Module &M, llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1497 initializeModule(M);
1499 if (ABIList.isIn(M,
"skip"))
1502 const unsigned InitialGlobalSize =
M.global_size();
1503 const unsigned InitialModuleSize =
M.size();
1507 auto GetOrInsertGlobal = [
this, &
Changed](StringRef
Name,
1508 Type *Ty) -> Constant * {
1509 GlobalVariable *
G =
Mod->getOrInsertGlobal(Name, Ty);
1510 Changed |=
G->getThreadLocalMode() != GlobalVariable::InitialExecTLSModel;
1511 G->setThreadLocalMode(GlobalVariable::InitialExecTLSModel);
1517 GetOrInsertGlobal(
"__dfsan_arg_tls",
1518 ArrayType::get(Type::getInt64Ty(*Ctx),
ArgTLSSize / 8));
1519 RetvalTLS = GetOrInsertGlobal(
1520 "__dfsan_retval_tls",
1522 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1523 ArgOriginTLS = GetOrInsertGlobal(
"__dfsan_arg_origin_tls", ArgOriginTLSTy);
1524 RetvalOriginTLS = GetOrInsertGlobal(
"__dfsan_retval_origin_tls", OriginTy);
1526 (void)
Mod->getOrInsertGlobal(
"__dfsan_track_origins", OriginTy, [&] {
1528 return new GlobalVariable(
1529 M, OriginTy, true, GlobalValue::WeakODRLinkage,
1530 ConstantInt::getSigned(OriginTy,
1531 shouldTrackOrigins() ? ClTrackOrigins : 0),
1532 "__dfsan_track_origins");
1535 initializeCallbackFunctions(M);
1536 initializeRuntimeFunctions(M);
1538 std::vector<Function *> FnsToInstrument;
1539 SmallPtrSet<Function *, 2> FnsWithNativeABI;
1540 SmallPtrSet<Function *, 2> FnsWithForceZeroLabel;
1541 SmallPtrSet<Constant *, 1> PersonalityFns;
1542 for (Function &
F : M)
1543 if (!
F.isIntrinsic() && !DFSanRuntimeFunctions.
contains(&
F) &&
1544 !LibAtomicFunction(
F) &&
1545 !
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1546 FnsToInstrument.push_back(&
F);
1547 if (
F.hasPersonalityFn())
1548 PersonalityFns.
insert(
F.getPersonalityFn()->stripPointerCasts());
1552 for (
auto *
C : PersonalityFns) {
1555 if (!isInstrumented(
F))
1569 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(
F);
1570 if (GAInst && FInst) {
1571 addGlobalNameSuffix(&GA);
1572 }
else if (GAInst != FInst) {
1577 buildWrapperFunction(
F,
"", GA.
getLinkage(),
F->getFunctionType());
1581 FnsToInstrument.push_back(NewF);
1590 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1591 FE = FnsToInstrument.end();
1594 FunctionType *FT =
F.getFunctionType();
1596 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1597 FT->getReturnType()->isVoidTy());
1599 if (isInstrumented(&
F)) {
1600 if (isForceZeroLabels(&
F))
1601 FnsWithForceZeroLabel.
insert(&
F);
1606 addGlobalNameSuffix(&
F);
1607 }
else if (!IsZeroArgsVoidRet || getWrapperKind(&
F) == WK_Custom) {
1615 F.hasLocalLinkage() ?
F.getLinkage()
1618 Function *NewF = buildWrapperFunction(
1620 (shouldTrackOrigins() ? std::string(
"dfso$") : std::string(
"dfsw$")) +
1621 std::string(
F.getName()),
1622 WrapperLinkage, FT);
1642 auto IsNotCmpUse = [](
Use &
U) ->
bool {
1643 User *Usr =
U.getUser();
1646 if (
CE->getOpcode() == Instruction::ICmp) {
1651 if (
I->getOpcode() == Instruction::ICmp) {
1657 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1659 UnwrappedFnMap[NewF] = &
F;
1662 if (!
F.isDeclaration()) {
1672 size_t N = FI - FnsToInstrument.begin(),
1673 Count = FE - FnsToInstrument.begin();
1674 FnsToInstrument.push_back(&
F);
1675 FI = FnsToInstrument.begin() +
N;
1676 FE = FnsToInstrument.begin() +
Count;
1680 }
else if (FT->isVarArg()) {
1681 UnwrappedFnMap[&
F] = &
F;
1686 for (Function *
F : FnsToInstrument) {
1687 if (!
F ||
F->isDeclaration())
1692 DFSanFunction DFSF(*
this,
F, FnsWithNativeABI.
count(
F),
1693 FnsWithForceZeroLabel.
count(
F), GetTLI(*
F));
1697 for (
auto &FArg :
F->args()) {
1699 Value *FArgShadow = DFSF.getShadow(&FArg);
1700 if (isZeroShadow(FArgShadow))
1703 Next = FArgShadowInst->getNextNode();
1705 if (shouldTrackOrigins()) {
1706 if (Instruction *Origin =
1710 if (
Next->comesBefore(OriginNext)) {
1716 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *
Next, &FArg);
1724 for (BasicBlock *BB : BBList) {
1734 if (!DFSF.SkipInsts.count(Inst))
1735 DFSanVisitor(DFSF).visit(Inst);
1746 for (DFSanFunction::PHIFixupElement &
P : DFSF.PHIFixups) {
1747 for (
unsigned Val = 0,
N =
P.Phi->getNumIncomingValues(); Val !=
N;
1749 P.ShadowPhi->setIncomingValue(
1750 Val, DFSF.getShadow(
P.Phi->getIncomingValue(Val)));
1752 P.OriginPhi->setIncomingValue(
1753 Val, DFSF.getOrigin(
P.Phi->getIncomingValue(Val)));
1762 for (
Value *V : DFSF.NonZeroChecks) {
1765 Pos = std::next(
I->getIterator());
1769 Pos = std::next(Pos->getIterator());
1771 Value *PrimitiveShadow = DFSF.collapseToPrimitiveShadow(V, Pos);
1773 IRB.
CreateICmpNE(PrimitiveShadow, DFSF.DFS.ZeroPrimitiveShadow);
1775 Ne, Pos,
false, ColdCallWeights));
1777 ThenIRB.CreateCall(DFSF.DFS.DFSanNonzeroLabelFn, {});
1782 return Changed || !FnsToInstrument.empty() ||
1783 M.global_size() != InitialGlobalSize ||
M.size() != InitialModuleSize;
1798Value *DFSanFunction::getRetvalOriginTLS() {
return DFS.RetvalOriginTLS; }
1802 ArgNo,
"_dfsarg_o");
1806 assert(DFS.shouldTrackOrigins());
1808 return DFS.ZeroOrigin;
1809 Value *&Origin = ValOriginMap[
V];
1813 return DFS.ZeroOrigin;
1814 if (
A->getArgNo() < DFS.NumOfElementsInArgOrgTLS) {
1815 Instruction *ArgOriginTLSPos = &*
F->getEntryBlock().begin();
1817 Value *ArgOriginPtr = getArgOriginTLS(
A->getArgNo(), IRB);
1818 Origin = IRB.
CreateLoad(DFS.OriginTy, ArgOriginPtr);
1821 Origin = DFS.ZeroOrigin;
1824 Origin = DFS.ZeroOrigin;
1830void DFSanFunction::setOrigin(Instruction *
I,
Value *Origin) {
1831 if (!DFS.shouldTrackOrigins())
1835 ValOriginMap[
I] = Origin;
1838Value *DFSanFunction::getShadowForTLSArgument(Argument *
A) {
1839 unsigned ArgOffset = 0;
1840 const DataLayout &
DL =
F->getDataLayout();
1841 for (
auto &FArg :
F->args()) {
1842 if (!FArg.getType()->isSized()) {
1848 unsigned Size =
DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1861 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1866 return DFS.getZeroShadow(
A);
1871 return DFS.getZeroShadow(V);
1872 if (IsForceZeroLabels)
1873 return DFS.getZeroShadow(V);
1874 Value *&Shadow = ValShadowMap[
V];
1878 return DFS.getZeroShadow(V);
1879 Shadow = getShadowForTLSArgument(
A);
1880 NonZeroChecks.push_back(Shadow);
1882 Shadow = DFS.getZeroShadow(V);
1888void DFSanFunction::setShadow(Instruction *
I,
Value *Shadow) {
1890 ValShadowMap[
I] = Shadow;
1898 assert(Addr != RetvalTLS &&
"Reinstrumenting?");
1901 uint64_t AndMask = MapParams->AndMask;
1904 IRB.
CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1906 uint64_t XorMask = MapParams->XorMask;
1908 OffsetLong = IRB.
CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1912std::pair<Value *, Value *>
1913DataFlowSanitizer::getShadowOriginAddress(
Value *Addr, Align InstAlignment,
1917 Value *ShadowOffset = getShadowOffset(Addr, IRB);
1918 Value *ShadowLong = ShadowOffset;
1919 uint64_t ShadowBase = MapParams->ShadowBase;
1920 if (ShadowBase != 0) {
1922 IRB.
CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1925 Value *OriginPtr =
nullptr;
1926 if (shouldTrackOrigins()) {
1927 Value *OriginLong = ShadowOffset;
1928 uint64_t OriginBase = MapParams->OriginBase;
1929 if (OriginBase != 0)
1931 IRB.
CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1937 OriginLong = IRB.
CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1941 return std::make_pair(ShadowPtr, OriginPtr);
1944Value *DataFlowSanitizer::getShadowAddress(
Value *Addr,
1946 Value *ShadowOffset) {
1951Value *DataFlowSanitizer::getShadowAddress(
Value *Addr,
1954 Value *ShadowOffset = getShadowOffset(Addr, IRB);
1955 return getShadowAddress(Addr, Pos, ShadowOffset);
1960 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1961 return expandFromPrimitiveShadow(
T, PrimitiveValue, Pos);
1968 if (DFS.isZeroShadow(V1))
1969 return collapseToPrimitiveShadow(V2, Pos);
1970 if (DFS.isZeroShadow(V2))
1971 return collapseToPrimitiveShadow(V1, Pos);
1973 return collapseToPrimitiveShadow(V1, Pos);
1975 auto V1Elems = ShadowElements.
find(V1);
1976 auto V2Elems = ShadowElements.
find(V2);
1977 if (V1Elems != ShadowElements.
end() && V2Elems != ShadowElements.
end()) {
1979 return collapseToPrimitiveShadow(V1, Pos);
1982 return collapseToPrimitiveShadow(V2, Pos);
1984 }
else if (V1Elems != ShadowElements.
end()) {
1985 if (V1Elems->second.count(V2))
1986 return collapseToPrimitiveShadow(V1, Pos);
1987 }
else if (V2Elems != ShadowElements.
end()) {
1988 if (V2Elems->second.count(V1))
1989 return collapseToPrimitiveShadow(V2, Pos);
1992 auto Key = std::make_pair(V1, V2);
1995 CachedShadow &CCS = CachedShadows[
Key];
1996 if (CCS.Block && DT.
dominates(CCS.Block, Pos->getParent()))
2000 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2001 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2004 CCS.Block = Pos->getParent();
2005 CCS.Shadow = IRB.
CreateOr(PV1, PV2);
2007 std::set<Value *> UnionElems;
2008 if (V1Elems != ShadowElements.
end()) {
2009 UnionElems = V1Elems->second;
2011 UnionElems.insert(V1);
2013 if (V2Elems != ShadowElements.
end()) {
2014 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2016 UnionElems.insert(V2);
2018 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2026Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
2028 return DFS.getZeroShadow(Inst);
2032 Shadow = combineShadows(Shadow, getShadow(Inst->
getOperand(
I)),
2035 return expandFromPrimitiveShadow(Inst->
getType(), Shadow,
2039void DFSanVisitor::visitInstOperands(Instruction &
I) {
2040 Value *CombinedShadow = DFSF.combineOperandShadows(&
I);
2041 DFSF.setShadow(&
I, CombinedShadow);
2042 visitInstOperandOrigins(
I);
2045Value *DFSanFunction::combineOrigins(
const std::vector<Value *> &Shadows,
2046 const std::vector<Value *> &Origins,
2048 ConstantInt *Zero) {
2049 assert(Shadows.size() == Origins.size());
2050 size_t Size = Origins.size();
2052 return DFS.ZeroOrigin;
2053 Value *Origin =
nullptr;
2055 Zero = DFS.ZeroPrimitiveShadow;
2056 for (
size_t I = 0;
I !=
Size; ++
I) {
2057 Value *OpOrigin = Origins[
I];
2059 if (ConstOpOrigin && ConstOpOrigin->
isNullValue())
2065 Value *OpShadow = Shadows[
I];
2066 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2071 return Origin ? Origin : DFS.ZeroOrigin;
2074Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2076 std::vector<Value *> Shadows(
Size);
2077 std::vector<Value *> Origins(
Size);
2078 for (
unsigned I = 0;
I !=
Size; ++
I) {
2082 return combineOrigins(Shadows, Origins, Inst->
getIterator());
2085void DFSanVisitor::visitInstOperandOrigins(Instruction &
I) {
2086 if (!DFSF.DFS.shouldTrackOrigins())
2088 Value *CombinedOrigin = DFSF.combineOperandOrigins(&
I);
2089 DFSF.setOrigin(&
I, CombinedOrigin);
2092Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2094 return Align(Alignment.
value() * DFS.ShadowWidthBytes);
2097Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2102bool DFSanFunction::isLookupTableConstant(
Value *
P) {
2104 if (GV->isConstant() && GV->
hasName())
2105 return DFS.CombineTaintLookupTableNames.
count(GV->
getName());
2110bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t
Size,
2111 Align InstAlignment) {
2135 Value **OriginAddr) {
2138 IRB.
CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2142std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2143 Value *ShadowAddr,
Value *OriginAddr, uint64_t
Size, Align ShadowAlign,
2145 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2146 const uint64_t ShadowSize =
Size * DFS.ShadowWidthBytes;
2148 assert(
Size >= 4 &&
"Not large enough load size for fast path!");
2151 std::vector<Value *> Shadows;
2152 std::vector<Value *> Origins;
2165 Type *WideShadowTy =
2166 ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) :
Type::getInt64Ty(*DFS.Ctx);
2169 Value *CombinedWideShadow =
2173 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2175 auto AppendWideShadowAndOrigin = [&](
Value *WideShadow,
Value *Origin) {
2176 if (BytesPerWideShadow > 4) {
2177 assert(BytesPerWideShadow == 8);
2185 WideShadow, ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2));
2186 Shadows.push_back(WideShadow);
2187 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2189 Shadows.push_back(WideShadowLo);
2190 Origins.push_back(Origin);
2192 Shadows.push_back(WideShadow);
2193 Origins.push_back(Origin);
2197 if (ShouldTrackOrigins)
2198 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2205 for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs <
Size;
2206 ByteOfs += BytesPerWideShadow) {
2207 ShadowAddr = IRB.
CreateGEP(WideShadowTy, ShadowAddr,
2208 ConstantInt::get(DFS.IntptrTy, 1));
2209 Value *NextWideShadow =
2211 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, NextWideShadow);
2212 if (ShouldTrackOrigins) {
2213 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2214 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2217 for (
unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2220 CombinedWideShadow = IRB.
CreateOr(CombinedWideShadow, ShrShadow);
2222 return {IRB.
CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2224 ? combineOrigins(Shadows, Origins, Pos,
2229std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2231 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2235 const auto SI = AllocaShadowMap.
find(AI);
2236 if (SI != AllocaShadowMap.
end()) {
2239 const auto OI = AllocaOriginMap.
find(AI);
2240 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.
end());
2241 return {ShadowLI, ShouldTrackOrigins
2248 SmallVector<const Value *, 2> Objs;
2250 bool AllConstants =
true;
2251 for (
const Value *Obj : Objs) {
2257 AllConstants =
false;
2261 return {DFS.ZeroPrimitiveShadow,
2262 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2265 return {DFS.ZeroPrimitiveShadow,
2266 ShouldTrackOrigins ? DFS.ZeroOrigin :
nullptr};
2270 if (ShouldTrackOrigins &&
2271 useCallbackLoadLabelAndOrigin(
Size, InstAlignment)) {
2274 IRB.
CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2275 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2278 DFS.PrimitiveShadowTy),
2283 Value *ShadowAddr, *OriginAddr;
2284 std::tie(ShadowAddr, OriginAddr) =
2285 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2287 const Align ShadowAlign = getShadowAlign(InstAlignment);
2288 const Align OriginAlign = getOriginAlign(InstAlignment);
2289 Value *Origin =
nullptr;
2290 if (ShouldTrackOrigins) {
2299 LoadInst *LI =
new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr,
"", Pos);
2301 return {LI, Origin};
2305 Value *ShadowAddr1 = IRB.
CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2306 ConstantInt::get(DFS.IntptrTy, 1));
2311 return {combineShadows(Load, Load1, Pos), Origin};
2314 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(
Size);
2316 if (HasSizeForFastPath)
2317 return loadShadowFast(ShadowAddr, OriginAddr,
Size, ShadowAlign,
2318 OriginAlign, Origin, Pos);
2322 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2324 return {FallbackCall, Origin};
2327std::pair<Value *, Value *>
2328DFSanFunction::loadShadowOrigin(
Value *Addr, uint64_t
Size, Align InstAlignment,
2330 Value *PrimitiveShadow, *Origin;
2331 std::tie(PrimitiveShadow, Origin) =
2332 loadShadowOriginSansLoadTracking(Addr,
Size, InstAlignment, Pos);
2333 if (DFS.shouldTrackOrigins()) {
2337 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2338 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2341 return {PrimitiveShadow, Origin};
2362 if (!V->getType()->isPointerTy())
2371 V =
GEP->getPointerOperand();
2374 if (!V->getType()->isPointerTy())
2379 }
while (Visited.
insert(V).second);
2384void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2388 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2389 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2404 Pos = std::next(Pos);
2406 std::vector<Value *> Shadows;
2407 std::vector<Value *> Origins;
2408 Value *PrimitiveShadow, *Origin;
2409 std::tie(PrimitiveShadow, Origin) =
2411 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2412 if (ShouldTrackOrigins) {
2413 Shadows.push_back(PrimitiveShadow);
2414 Origins.push_back(Origin);
2417 DFSF.isLookupTableConstant(
2420 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2421 if (ShouldTrackOrigins) {
2422 Shadows.push_back(PtrShadow);
2426 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2427 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2430 DFSF.expandFromPrimitiveShadow(LI.
getType(), PrimitiveShadow, Pos);
2431 DFSF.setShadow(&LI, Shadow);
2433 if (ShouldTrackOrigins) {
2434 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2441 IRB.
CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2446 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2449Value *DFSanFunction::updateOriginIfTainted(
Value *Shadow,
Value *Origin,
2451 assert(DFS.shouldTrackOrigins());
2452 return IRB.
CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2456 if (!DFS.shouldTrackOrigins())
2458 return IRB.
CreateCall(DFS.DFSanChainOriginFn, V);
2462 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2463 const DataLayout &
DL =
F->getDataLayout();
2464 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2465 if (IntptrSize == OriginSize)
2467 assert(IntptrSize == OriginSize * 2);
2473 Value *StoreOriginAddr,
2474 uint64_t StoreOriginSize, Align Alignment) {
2475 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2476 const DataLayout &
DL =
F->getDataLayout();
2477 const Align IntptrAlignment =
DL.getABITypeAlign(DFS.IntptrTy);
2478 unsigned IntptrSize =
DL.getTypeStoreSize(DFS.IntptrTy);
2480 assert(IntptrSize >= OriginSize);
2483 Align CurrentAlignment = Alignment;
2484 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2485 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2486 Value *IntptrStoreOriginPtr =
2488 for (
unsigned I = 0;
I < StoreOriginSize / IntptrSize; ++
I) {
2491 : IntptrStoreOriginPtr;
2493 Ofs += IntptrSize / OriginSize;
2494 CurrentAlignment = IntptrAlignment;
2498 for (
unsigned I = Ofs;
I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2508 const Twine &Name) {
2509 Type *VTy =
V->getType();
2514 return IRB.
CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2519 Value *StoreOriginAddr, Align InstAlignment) {
2522 const Align OriginAlignment = getOriginAlign(InstAlignment);
2523 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2526 if (!ConstantShadow->isZeroValue())
2527 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr,
Size,
2532 if (shouldInstrumentWithCall()) {
2534 DFS.DFSanMaybeStoreOriginFn,
2535 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2537 Value *
Cmp = convertToBool(CollapsedShadow, IRB,
"_dfscmp");
2538 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2540 Cmp, &*IRB.
GetInsertPoint(),
false, DFS.OriginStoreWeights, &DTU);
2542 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr,
Size,
2548void DFSanFunction::storeZeroPrimitiveShadow(
Value *Addr, uint64_t
Size,
2552 IntegerType *ShadowTy =
2554 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2555 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2561void DFSanFunction::storePrimitiveShadowOrigin(
Value *Addr, uint64_t
Size,
2562 Align InstAlignment,
2563 Value *PrimitiveShadow,
2566 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2569 const auto SI = AllocaShadowMap.
find(AI);
2570 if (SI != AllocaShadowMap.
end()) {
2576 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2577 const auto OI = AllocaOriginMap.
find(AI);
2578 assert(OI != AllocaOriginMap.
end() && Origin);
2585 const Align ShadowAlign = getShadowAlign(InstAlignment);
2586 if (DFS.isZeroShadow(PrimitiveShadow)) {
2587 storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign, Pos);
2592 Value *ShadowAddr, *OriginAddr;
2593 std::tie(ShadowAddr, OriginAddr) =
2594 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2596 const unsigned ShadowVecSize = 8;
2597 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2598 "Shadow vector is too large!");
2601 uint64_t LeftSize =
Size;
2602 if (LeftSize >= ShadowVecSize) {
2606 for (
unsigned I = 0;
I != ShadowVecSize; ++
I) {
2608 ShadowVec, PrimitiveShadow,
2609 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx),
I));
2612 Value *CurShadowVecAddr =
2615 LeftSize -= ShadowVecSize;
2617 }
while (LeftSize >= ShadowVecSize);
2620 while (LeftSize > 0) {
2621 Value *CurShadowAddr =
2628 if (ShouldTrackOrigins) {
2629 storeOrigin(Pos, Addr,
Size, PrimitiveShadow, Origin, OriginAddr,
2651void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2652 auto &
DL =
SI.getDataLayout();
2653 Value *Val =
SI.getValueOperand();
2666 const bool ShouldTrackOrigins =
2667 DFSF.DFS.shouldTrackOrigins() && !
SI.isAtomic();
2668 std::vector<Value *> Shadows;
2669 std::vector<Value *> Origins;
2672 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2674 if (ShouldTrackOrigins) {
2675 Shadows.push_back(Shadow);
2676 Origins.push_back(DFSF.getOrigin(Val));
2679 Value *PrimitiveShadow;
2681 Value *PtrShadow = DFSF.getShadow(
SI.getPointerOperand());
2682 if (ShouldTrackOrigins) {
2683 Shadows.push_back(PtrShadow);
2684 Origins.push_back(DFSF.getOrigin(
SI.getPointerOperand()));
2686 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow,
SI.getIterator());
2688 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow,
SI.getIterator());
2690 Value *Origin =
nullptr;
2691 if (ShouldTrackOrigins)
2692 Origin = DFSF.combineOrigins(Shadows, Origins,
SI.getIterator());
2693 DFSF.storePrimitiveShadowOrigin(
SI.getPointerOperand(),
Size,
SI.getAlign(),
2694 PrimitiveShadow, Origin,
SI.getIterator());
2697 Value *Addr =
SI.getPointerOperand();
2699 IRB.
CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2704void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &
I) {
2707 Value *Val =
I.getOperand(1);
2708 const auto &
DL =
I.getDataLayout();
2716 Value *Addr =
I.getOperand(0);
2717 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2718 DFSF.storeZeroPrimitiveShadow(Addr,
Size, ShadowAlign,
I.getIterator());
2719 DFSF.setShadow(&
I, DFSF.DFS.getZeroShadow(&
I));
2720 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2723void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &
I) {
2724 visitCASOrRMW(
I.getAlign(),
I);
2730void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &
I) {
2731 visitCASOrRMW(
I.getAlign(),
I);
2737void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2738 visitInstOperands(UO);
2741void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2742 visitInstOperands(BO);
2745void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2752 visitInstOperands(BCI);
2755void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2757void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2758 visitInstOperands(CI);
2761 Value *CombinedShadow = DFSF.getShadow(&CI);
2763 IRB.
CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2768void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2780 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2781 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2784void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2786 DFSF.isLookupTableConstant(
2788 visitInstOperands(GEPI);
2795 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2796 if (DFSF.DFS.shouldTrackOrigins())
2797 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2800void DFSanVisitor::visitExtractElementInst(ExtractElementInst &
I) {
2801 visitInstOperands(
I);
2804void DFSanVisitor::visitInsertElementInst(InsertElementInst &
I) {
2805 visitInstOperands(
I);
2808void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &
I) {
2809 visitInstOperands(
I);
2812void DFSanVisitor::visitExtractValueInst(ExtractValueInst &
I) {
2814 Value *Agg =
I.getAggregateOperand();
2815 Value *AggShadow = DFSF.getShadow(Agg);
2817 DFSF.setShadow(&
I, ResShadow);
2818 visitInstOperandOrigins(
I);
2821void DFSanVisitor::visitInsertValueInst(InsertValueInst &
I) {
2823 Value *AggShadow = DFSF.getShadow(
I.getAggregateOperand());
2824 Value *InsShadow = DFSF.getShadow(
I.getInsertedValueOperand());
2826 DFSF.setShadow(&
I, Res);
2827 visitInstOperandOrigins(
I);
2830void DFSanVisitor::visitAllocaInst(AllocaInst &
I) {
2831 bool AllLoadsStores =
true;
2832 for (User *U :
I.users()) {
2837 if (
SI->getPointerOperand() == &
I)
2841 AllLoadsStores =
false;
2844 if (AllLoadsStores) {
2846 DFSF.AllocaShadowMap[&
I] = IRB.
CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2847 if (DFSF.DFS.shouldTrackOrigins()) {
2848 DFSF.AllocaOriginMap[&
I] =
2852 DFSF.setShadow(&
I, DFSF.DFS.ZeroPrimitiveShadow);
2853 DFSF.setOrigin(&
I, DFSF.DFS.ZeroOrigin);
2856void DFSanVisitor::visitSelectInst(SelectInst &
I) {
2857 Value *CondShadow = DFSF.getShadow(
I.getCondition());
2858 Value *TrueShadow = DFSF.getShadow(
I.getTrueValue());
2859 Value *FalseShadow = DFSF.getShadow(
I.getFalseValue());
2860 Value *ShadowSel =
nullptr;
2861 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2862 std::vector<Value *> Shadows;
2863 std::vector<Value *> Origins;
2865 ShouldTrackOrigins ? DFSF.getOrigin(
I.getTrueValue()) :
nullptr;
2866 Value *FalseOrigin =
2867 ShouldTrackOrigins ? DFSF.getOrigin(
I.getFalseValue()) :
nullptr;
2869 DFSF.addConditionalCallbacksIfEnabled(
I,
I.getCondition());
2872 ShadowSel = DFSF.combineShadowsThenConvert(
I.getType(), TrueShadow,
2873 FalseShadow,
I.getIterator());
2874 if (ShouldTrackOrigins) {
2875 Shadows.push_back(TrueShadow);
2876 Shadows.push_back(FalseShadow);
2877 Origins.push_back(TrueOrigin);
2878 Origins.push_back(FalseOrigin);
2881 if (TrueShadow == FalseShadow) {
2882 ShadowSel = TrueShadow;
2883 if (ShouldTrackOrigins) {
2884 Shadows.push_back(TrueShadow);
2885 Origins.push_back(TrueOrigin);
2889 "",
I.getIterator());
2890 if (ShouldTrackOrigins) {
2891 Shadows.push_back(ShadowSel);
2893 FalseOrigin,
"",
I.getIterator()));
2898 I.getType(), CondShadow,
2899 ShadowSel,
I.getIterator())
2901 if (ShouldTrackOrigins) {
2903 Shadows.push_back(CondShadow);
2904 Origins.push_back(DFSF.getOrigin(
I.getCondition()));
2906 DFSF.setOrigin(&
I, DFSF.combineOrigins(Shadows, Origins,
I.getIterator()));
2910void DFSanVisitor::visitMemSetInst(MemSetInst &
I) {
2912 Value *ValShadow = DFSF.getShadow(
I.getValue());
2913 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2914 ? DFSF.getOrigin(
I.getValue())
2915 : DFSF.DFS.ZeroOrigin;
2917 {ValShadow, ValOrigin, I.getDest(),
2918 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2921void DFSanVisitor::visitMemTransferInst(MemTransferInst &
I) {
2926 if (DFSF.DFS.shouldTrackOrigins()) {
2928 DFSF.DFS.DFSanMemOriginTransferFn,
2929 {I.getArgOperand(0), I.getArgOperand(1),
2930 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2933 Value *DestShadow = DFSF.DFS.getShadowAddress(
I.getDest(),
I.getIterator());
2934 Value *SrcShadow = DFSF.DFS.getShadowAddress(
I.getSource(),
I.getIterator());
2936 IRB.
CreateMul(
I.getLength(), ConstantInt::get(
I.getLength()->getType(),
2937 DFSF.DFS.ShadowWidthBytes));
2939 IRB.
CreateCall(
I.getFunctionType(),
I.getCalledOperand(),
2940 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2941 MTI->setDestAlignment(DFSF.getShadowAlign(
I.getDestAlign().valueOrOne()));
2942 MTI->setSourceAlignment(DFSF.getShadowAlign(
I.getSourceAlign().valueOrOne()));
2945 DFSF.DFS.DFSanMemTransferCallbackFn,
2946 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2950void DFSanVisitor::visitBranchInst(BranchInst &BR) {
2954 DFSF.addConditionalCallbacksIfEnabled(BR, BR.
getCondition());
2957void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
2958 DFSF.addConditionalCallbacksIfEnabled(SW, SW.
getCondition());
2964 RetVal =
I->getOperand(0);
2967 return I->isMustTailCall();
2972void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
2981 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
2987 if (DFSF.DFS.shouldTrackOrigins()) {
2994void DFSanVisitor::addShadowArguments(Function &
F, CallBase &CB,
2995 std::vector<Value *> &Args,
2997 FunctionType *FT =
F.getFunctionType();
3002 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3004 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()));
3007 if (FT->isVarArg()) {
3008 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3009 CB.
arg_size() - FT->getNumParams());
3010 auto *LabelVAAlloca =
3011 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3014 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3017 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*
I), CB.
getIterator()),
3025 if (!FT->getReturnType()->isVoidTy()) {
3026 if (!DFSF.LabelReturnAlloca) {
3027 DFSF.LabelReturnAlloca =
new AllocaInst(
3028 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3031 Args.push_back(DFSF.LabelReturnAlloca);
3035void DFSanVisitor::addOriginArguments(Function &
F, CallBase &CB,
3036 std::vector<Value *> &Args,
3038 FunctionType *FT =
F.getFunctionType();
3043 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N)
3044 Args.push_back(DFSF.getOrigin(*
I));
3047 if (FT->isVarArg()) {
3049 ArrayType::get(DFSF.DFS.OriginTy, CB.
arg_size() - FT->getNumParams());
3050 auto *OriginVAAlloca =
3051 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3054 for (
unsigned N = 0;
I != CB.
arg_end(); ++
I, ++
N) {
3063 if (!FT->getReturnType()->isVoidTy()) {
3064 if (!DFSF.OriginReturnAlloca) {
3065 DFSF.OriginReturnAlloca =
new AllocaInst(
3066 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3069 Args.push_back(DFSF.OriginReturnAlloca);
3073bool DFSanVisitor::visitWrappedCallBase(Function &
F, CallBase &CB) {
3075 switch (DFSF.DFS.getWrapperKind(&
F)) {
3076 case DataFlowSanitizer::WK_Warning:
3078 IRB.
CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3080 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3081 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3082 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3084 case DataFlowSanitizer::WK_Discard:
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_Functional:
3092 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &
F);
3093 visitInstOperands(CB);
3095 case DataFlowSanitizer::WK_Custom:
3103 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3104 FunctionType *FT =
F.getFunctionType();
3105 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3106 std::string CustomFName = ShouldTrackOrigins ?
"__dfso_" :
"__dfsw_";
3107 CustomFName +=
F.getName();
3109 CustomFName, CustomFn.TransformedType);
3111 CustomFn->copyAttributesFrom(&
F);
3114 if (!FT->getReturnType()->isVoidTy()) {
3115 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3119 std::vector<Value *>
Args;
3123 for (
unsigned N = FT->getNumParams();
N != 0; ++
I, --
N) {
3128 const unsigned ShadowArgStart =
Args.size();
3129 addShadowArguments(
F, CB, Args, IRB);
3132 const unsigned OriginArgStart =
Args.size();
3133 if (ShouldTrackOrigins)
3134 addOriginArguments(
F, CB, Args, IRB);
3139 CallInst *CustomCI = IRB.
CreateCall(CustomF, Args);
3147 for (
unsigned N = 0;
N < FT->getNumParams();
N++) {
3148 const unsigned ArgNo = ShadowArgStart +
N;
3150 DFSF.DFS.PrimitiveShadowTy)
3152 if (ShouldTrackOrigins) {
3153 const unsigned OriginArgNo = OriginArgStart +
N;
3161 if (!FT->getReturnType()->isVoidTy()) {
3162 LoadInst *LabelLoad =
3163 IRB.
CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3164 DFSF.setShadow(CustomCI,
3165 DFSF.expandFromPrimitiveShadow(
3166 FT->getReturnType(), LabelLoad, CB.
getIterator()));
3167 if (ShouldTrackOrigins) {
3168 LoadInst *OriginLoad =
3169 IRB.
CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3170 DFSF.setOrigin(CustomCI, OriginLoad);
3182 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3183 uint32_t OrderingTable[NumOrderings] = {};
3185 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3186 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3187 OrderingTable[(int)AtomicOrderingCABI::consume] =
3188 (
int)AtomicOrderingCABI::acquire;
3189 OrderingTable[(int)AtomicOrderingCABI::release] =
3190 OrderingTable[(
int)AtomicOrderingCABI::acq_rel] =
3191 (int)AtomicOrderingCABI::acq_rel;
3192 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3193 (
int)AtomicOrderingCABI::seq_cst;
3198void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3209 Value *NewOrdering =
3214 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3220 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3221 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3225 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3226 uint32_t OrderingTable[NumOrderings] = {};
3228 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3229 OrderingTable[(
int)AtomicOrderingCABI::release] =
3230 (int)AtomicOrderingCABI::release;
3231 OrderingTable[(int)AtomicOrderingCABI::consume] =
3232 OrderingTable[(
int)AtomicOrderingCABI::acquire] =
3233 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3234 (
int)AtomicOrderingCABI::acq_rel;
3235 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3236 (
int)AtomicOrderingCABI::seq_cst;
3241void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3249 Value *NewOrdering =
3257 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3258 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3261void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3277 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3278 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3282 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3283 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3286void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3300 NextIRB.SetCurrentDebugLocation(CB.
getDebugLoc());
3302 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3306 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3307 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3308 TargetPtr, ExpectedPtr, DesiredPtr,
3309 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3312void DFSanVisitor::visitCallBase(CallBase &CB) {
3315 visitInstOperands(CB);
3330 case LibFunc_atomic_load:
3332 llvm::errs() <<
"DFSAN -- cannot instrument invoke of libatomic load. "
3336 visitLibAtomicLoad(CB);
3338 case LibFunc_atomic_store:
3339 visitLibAtomicStore(CB);
3347 if (
F &&
F->hasName() && !
F->isVarArg()) {
3348 if (
F->getName() ==
"__atomic_exchange") {
3349 visitLibAtomicExchange(CB);
3352 if (
F->getName() ==
"__atomic_compare_exchange") {
3353 visitLibAtomicCompareExchange(CB);
3358 DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
3360 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3361 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3366 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3368 const DataLayout &
DL = getDataLayout();
3371 unsigned ArgOffset = 0;
3372 for (
unsigned I = 0,
N = FT->getNumParams();
I !=
N; ++
I) {
3373 if (ShouldTrackOrigins) {
3376 if (
I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3377 !DFSF.DFS.isZeroShadow(ArgShadow))
3379 DFSF.getArgOriginTLS(
I, IRB));
3383 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(
I)));
3389 DFSF.getArgTLS(FT->getParamType(
I), ArgOffset, IRB),
3397 if (
II->getNormalDest()->getSinglePredecessor()) {
3398 Next = &
II->getNormalDest()->front();
3415 unsigned Size =
DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3418 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3420 LoadInst *LI = NextIRB.CreateAlignedLoad(
3421 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.
getType(), NextIRB),
3423 DFSF.SkipInsts.insert(LI);
3424 DFSF.setShadow(&CB, LI);
3425 DFSF.NonZeroChecks.push_back(LI);
3428 if (ShouldTrackOrigins) {
3429 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3430 DFSF.getRetvalOriginTLS(),
"_dfsret_o");
3431 DFSF.SkipInsts.insert(LI);
3432 DFSF.setOrigin(&CB, LI);
3435 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3439void DFSanVisitor::visitPHINode(PHINode &PN) {
3440 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3446 for (BasicBlock *BB : PN.
blocks())
3449 DFSF.setShadow(&PN, ShadowPN);
3451 PHINode *OriginPN =
nullptr;
3452 if (DFSF.DFS.shouldTrackOrigins()) {
3456 for (BasicBlock *BB : PN.
blocks())
3458 DFSF.setOrigin(&PN, OriginPN);
3461 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3474 if (!DataFlowSanitizer(ABIListFiles).
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 > 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)
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.
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.
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
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.
uint64_t value() const
This is a hole in the type system and should not be abused.