LLVM: lib/Transforms/Instrumentation/DataFlowSanitizer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
110#include
111#include
112#include
113#include
114#include
115#include
116#include
117#include
118#include
119
120using namespace llvm;
121
122
124
126
127
128
131
132
133
134
135
136
137
139 "dfsan-preserve-alignment",
140 cl::desc("respect alignment requirements provided by input IR"), cl::Hidden,
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
160 "dfsan-abilist",
161 cl::desc("File listing native ABI functions and how the pass treats them"),
163
164
165
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."),
171
172
173
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."),
179
180
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."),
187
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)."),
196
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"),
202
203
204
205
206
207
208
209
210
211
212
214 "dfsan-event-callbacks",
215 cl::desc("Insert calls to __dfsan_*_callback functions on data events."),
217
218
219
220
222 "dfsan-conditional-callbacks",
223 cl::desc("Insert calls to callback functions on conditionals."), cl::Hidden,
225
226
227
228
230 "dfsan-reaches-function-callbacks",
231 cl::desc("Insert calls to callback functions on data reaching a function."),
233
234
236 "dfsan-track-select-control-flow",
237 cl::desc("Propagate labels from condition values of select instructions "
238 "to results."),
240
241
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)."),
248
249
250
251
252
253
255 cl::desc("Track origins of labels"),
257
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."),
263
265 "dfsan-add-global-name-suffix",
266 cl::desc("Whether to add .dfsan suffix to global names"), cl::Hidden,
268
270
271 Type *GType = G.getValueType();
272
274 if (!SGType->isLiteral())
275 return SGType->getName();
276 }
277 return "";
278}
279
280namespace {
281
282
283
284
285
286struct MemoryMapParams {
287 uint64_t AndMask;
288 uint64_t XorMask;
289 uint64_t ShadowBase;
290 uint64_t OriginBase;
291};
292
293}
294
295
296
298 0,
299 0x0B00000000000,
300 0,
301 0x0200000000000,
302};
303
304
306 0,
307 0x500000000000,
308 0,
309 0x100000000000,
310};
311
312
313
315 0,
316 0x500000000000,
317 0,
318 0x100000000000,
319};
320
321namespace {
322
323class DFSanABIList {
324 std::unique_ptr SCL;
325
326public:
327 DFSanABIList() = default;
328
329 void set(std::unique_ptr List) { SCL = std::move(List); }
330
331
332
333 bool isIn(const Function &F, StringRef Category) const {
334 return isIn(*F.getParent(), Category) ||
335 SCL->inSection("dataflow", "fun", F.getName(), Category);
336 }
337
338
339
340
341
342 bool isIn(const GlobalAlias &GA, StringRef Category) const {
343 if (isIn(*GA.getParent(), Category))
344 return true;
345
347 return SCL->inSection("dataflow", "fun", GA.getName(), Category);
348
349 return SCL->inSection("dataflow", "global", GA.getName(), Category) ||
351 Category);
352 }
353
354
355 bool isIn(const Module &M, StringRef Category) const {
356 return SCL->inSection("dataflow", "src", M.getModuleIdentifier(), Category);
357 }
358};
359
360
361
362
363struct TransformedFunction {
364 TransformedFunction(FunctionType *OriginalType, FunctionType *TransformedType,
365 const std::vector &ArgumentIndexMapping)
366 : OriginalType(OriginalType), TransformedType(TransformedType),
367 ArgumentIndexMapping(ArgumentIndexMapping) {}
368
369
370 TransformedFunction(const TransformedFunction &) = delete;
371 TransformedFunction &operator=(const TransformedFunction &) = delete;
372
373
374 TransformedFunction(TransformedFunction &&) = default;
375 TransformedFunction &operator=(TransformedFunction &&) = default;
376
377
378 FunctionType *OriginalType;
379
380
381 FunctionType *TransformedType;
382
383
384
385
386
387
388 std::vector ArgumentIndexMapping;
389};
390
391
392
393
394AttributeList
395transformFunctionAttributes(const TransformedFunction &TransformedFunction,
396 LLVMContext &Ctx, AttributeList CallSiteAttrs) {
397
398
399 std::vectorllvm::AttributeSet ArgumentAttributes(
400 TransformedFunction.TransformedType->getNumParams());
401
402
403
404
405 for (unsigned I = 0, IE = TransformedFunction.ArgumentIndexMapping.size();
407 unsigned TransformedIndex = TransformedFunction.ArgumentIndexMapping[I];
408 ArgumentAttributes[TransformedIndex] = CallSiteAttrs.getParamAttrs(I);
409 }
410
411
412 for (unsigned I = TransformedFunction.OriginalType->getNumParams(),
413 IE = CallSiteAttrs.getNumAttrSets();
415 ArgumentAttributes.push_back(CallSiteAttrs.getParamAttrs(I));
416 }
417
418 return AttributeList::get(Ctx, CallSiteAttrs.getFnAttrs(),
419 CallSiteAttrs.getRetAttrs(),
421}
422
423class DataFlowSanitizer {
424 friend struct DFSanFunction;
425 friend class DFSanVisitor;
426
427 enum { ShadowWidthBits = 8, ShadowWidthBytes = ShadowWidthBits / 8 };
428
429 enum { OriginWidthBits = 32, OriginWidthBytes = OriginWidthBits / 8 };
430
431
432 enum WrapperKind {
433
434
435
436 WK_Warning,
437
438
439
440 WK_Discard,
441
442
443
444 WK_Functional,
445
446
447
448
449
450
451 WK_Custom
452 };
453
455 LLVMContext *Ctx;
456 Type *Int8Ptr;
457 IntegerType *OriginTy;
459 ConstantInt *ZeroOrigin;
460
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;
518
519
520
521 const MemoryMapParams *MapParams;
522
526 Value *ShadowOffset);
527 std::pair<Value *, Value *> getShadowOriginAddress(Value *Addr,
528 Align InstAlignment,
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);
543
544
545
547 Value **OriginAddr);
548
549
550
551 bool hasLoadSizeForFastPath(uint64_t Size);
552
553
554 bool shouldTrackOrigins();
555
556
557
558
559
560
562
564
565
566 bool isZeroShadow(Value *V);
567
568
569
570
571
572
573 Type *getShadowTy(Type *OrigTy);
574
576
577 const uint64_t NumOfElementsInArgOrgTLS = ArgTLSSize / OriginWidthBytes;
578
579public:
580 DataFlowSanitizer(const std::vectorstd::string &ABIListFiles,
581 IntrusiveRefCntPtrvfs::FileSystem FS);
582
584 llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI);
585};
586
587struct DFSanFunction {
588 DataFlowSanitizer &DFS;
590 DominatorTree DT;
591 bool IsNativeABI;
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;
600
601 struct PHIFixupElement {
602 PHINode *Phi;
603 PHINode *ShadowPhi;
604 PHINode *OriginPhi;
605 };
606 std::vector PHIFixups;
607
608 DenseSet<Instruction *> SkipInsts;
609 std::vector<Value *> NonZeroChecks;
610
611 struct CachedShadow {
612 BasicBlock *Block;
614 };
615
616 DenseMap<std::pair<Value *, Value *>, CachedShadow> CachedShadows;
617
618
619
620
621 DenseMap<Value *, Value *> CachedCollapsedShadows;
622 DenseMap<Value *, std::set<Value *>> ShadowElements;
623
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) {
628 DT.recalculate(*F);
629 }
630
631
632
633
635
636
638
639
640
641
643
644
645 Value *getRetvalOriginTLS();
646
648 void setOrigin(Instruction *I, Value *Origin);
649
650 Value *combineOperandOrigins(Instruction *Inst);
651
652
653
654
655
656
657 Value *combineOrigins(const std::vector<Value *> &Shadows,
658 const std::vector<Value *> &Origins,
660
662 void setShadow(Instruction *I, Value *Shadow);
663
664
666
667
670 Value *combineOperandShadows(Instruction *Inst);
671
672
673
674
675
676
677
678
679 std::pair<Value *, Value *> loadShadowOrigin(Value *Addr, uint64_t Size,
680 Align InstAlignment,
682
683 void storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
684 Align InstAlignment, Value *PrimitiveShadow,
686
687
688
689
690
691
692 Value *expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
694
695
696
697
698
699
700
702
703 void storeZeroPrimitiveShadow(Value *Addr, uint64_t Size, Align ShadowAlign,
705
706 Align getShadowAlign(Align InstAlignment);
707
708
709
710 void addConditionalCallbacksIfEnabled(Instruction &I, Value *Condition);
711
712
713
714 void addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB, Instruction &I,
716
717 bool isLookupTableConstant(Value *P);
718
719private:
720
721
722 template
723 Value *collapseAggregateShadow(AggregateType *AT, Value *Shadow,
725
727
728
729 Value *getShadowForTLSArgument(Argument *A);
730
731
732 std::pair<Value *, Value *>
733 loadShadowFast(Value *ShadowAddr, Value *OriginAddr, uint64_t Size,
734 Align ShadowAlign, Align OriginAlign, Value *FirstOrigin,
736
737 Align getOriginAlign(Align InstAlignment);
738
739
740
741
742
743
744
745
746
747
748 bool useCallbackLoadLabelAndOrigin(uint64_t Size, Align InstAlignment);
749
750
752
753
754
756
757
758
760
761
762
764 uint64_t StoreOriginSize, Align Alignment);
765
766
767
768
769
770
773 Align InstAlignment);
774
775
777
778 bool shouldInstrumentWithCall();
779
780
781
782
783
784 std::pair<Value *, Value *>
785 loadShadowOriginSansLoadTracking(Value *Addr, uint64_t Size,
786 Align InstAlignment,
788 int NumOriginStores = 0;
789};
790
791class DFSanVisitor : public InstVisitor {
792public:
793 DFSanFunction &DFSF;
794
795 DFSanVisitor(DFSanFunction &DFSF) : DFSF(DFSF) {}
796
797 const DataLayout &getDataLayout() const {
798 return DFSF.F->getDataLayout();
799 }
800
801
802 void visitInstOperands(Instruction &I);
803
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);
833
834private:
835 void visitCASOrRMW(Align InstAlignment, Instruction &I);
836
837
838 bool visitWrappedCallBase(Function &F, CallBase &CB);
839
840
841 void visitInstOperandOrigins(Instruction &I);
842
843 void addShadowArguments(Function &F, CallBase &CB, std::vector<Value *> &Args,
845
846 void addOriginArguments(Function &F, CallBase &CB, std::vector<Value *> &Args,
848
851};
852
853bool LibAtomicFunction(const Function &F) {
854
855
856
857
858
859 if (.hasName() || F.isVarArg())
860 return false;
861 switch (F.arg_size()) {
862 case 4:
863 return F.getName() == "__atomic_load" || F.getName() == "__atomic_store";
864 case 5:
865 return F.getName() == "__atomic_exchange";
866 case 6:
867 return F.getName() == "__atomic_compare_exchange";
868 default:
869 return false;
870 }
871}
872
873}
874
875DataFlowSanitizer::DataFlowSanitizer(
876 const std::vectorstd::string &ABIListFiles,
878 std::vectorstd::string AllABIListFiles(std::move(ABIListFiles));
881
883}
884
885TransformedFunction DataFlowSanitizer::getCustomFunctionType(FunctionType *T) {
887
888
889
890
891
892 std::vector ArgumentIndexMapping;
893 for (unsigned I = 0, E = T->getNumParams(); I != E; ++I) {
894 Type *ParamType = T->getParamType(I);
895 ArgumentIndexMapping.push_back(ArgTypes.size());
897 }
898 for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
899 ArgTypes.push_back(PrimitiveShadowTy);
900 if (T->isVarArg())
901 ArgTypes.push_back(PrimitiveShadowPtrTy);
902 Type *RetType = T->getReturnType();
904 ArgTypes.push_back(PrimitiveShadowPtrTy);
905
906 if (shouldTrackOrigins()) {
907 for (unsigned I = 0, E = T->getNumParams(); I != E; ++I)
909 if (T->isVarArg())
913 }
914
915 return TransformedFunction(
916 T, FunctionType::get(T->getReturnType(), ArgTypes, T->isVarArg()),
917 ArgumentIndexMapping);
918}
919
920bool DataFlowSanitizer::isZeroShadow(Value *V) {
924 return CI->isZero();
925 return false;
926 }
927
929}
930
931bool DataFlowSanitizer::hasLoadSizeForFastPath(uint64_t Size) {
932 uint64_t ShadowSize = Size * ShadowWidthBytes;
933 return ShadowSize % 8 == 0 || ShadowSize == 4;
934}
935
936bool DataFlowSanitizer::shouldTrackOrigins() {
937 static const bool ShouldTrackOrigins = ClTrackOrigins;
938 return ShouldTrackOrigins;
939}
940
941Constant *DataFlowSanitizer::getZeroShadow(Type *OrigTy) {
943 return ZeroPrimitiveShadow;
944 Type *ShadowTy = getShadowTy(OrigTy);
946}
947
948Constant *DataFlowSanitizer::getZeroShadow(Value *V) {
949 return getZeroShadow(V->getType());
950}
951
957
959 for (unsigned Idx = 0; Idx < AT->getNumElements(); Idx++) {
962 Shadow, Indices, AT->getElementType(), PrimitiveShadow, IRB);
964 }
965 return Shadow;
966 }
967
969 for (unsigned Idx = 0; Idx < ST->getNumElements(); Idx++) {
972 Shadow, Indices, ST->getElementType(Idx), PrimitiveShadow, IRB);
974 }
975 return Shadow;
976 }
978}
979
980bool DFSanFunction::shouldInstrumentWithCall() {
983}
984
985Value *DFSanFunction::expandFromPrimitiveShadow(Type *T, Value *PrimitiveShadow,
987 Type *ShadowTy = DFS.getShadowTy(T);
988
990 return PrimitiveShadow;
991
992 if (DFS.isZeroShadow(PrimitiveShadow))
993 return DFS.getZeroShadow(ShadowTy);
994
996 SmallVector<unsigned, 4> Indices;
999 PrimitiveShadow, IRB);
1000
1001
1002 CachedCollapsedShadows[Shadow] = PrimitiveShadow;
1003 return Shadow;
1004}
1005
1006template
1007Value *DFSanFunction::collapseAggregateShadow(AggregateType *AT, Value *Shadow,
1009 if (!AT->getNumElements())
1010 return DFS.ZeroPrimitiveShadow;
1011
1013 Value *Aggregator = collapseToPrimitiveShadow(FirstItem, IRB);
1014
1015 for (unsigned Idx = 1; Idx < AT->getNumElements(); Idx++) {
1017 Value *ShadowInner = collapseToPrimitiveShadow(ShadowItem, IRB);
1018 Aggregator = IRB.CreateOr(Aggregator, ShadowInner);
1019 }
1020 return Aggregator;
1021}
1022
1023Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
1027 return Shadow;
1029 return collapseAggregateShadow<>(AT, Shadow, IRB);
1031 return collapseAggregateShadow<>(ST, Shadow, IRB);
1033}
1034
1035Value *DFSanFunction::collapseToPrimitiveShadow(Value *Shadow,
1039 return Shadow;
1040
1041
1042 Value *&CS = CachedCollapsedShadows[Shadow];
1043 if (CS && DT.dominates(CS, Pos))
1044 return CS;
1045
1047 Value *PrimitiveShadow = collapseToPrimitiveShadow(Shadow, IRB);
1048
1049 CS = PrimitiveShadow;
1050 return PrimitiveShadow;
1051}
1052
1053void DFSanFunction::addConditionalCallbacksIfEnabled(Instruction &I,
1054 Value *Condition) {
1056 return;
1057 }
1059 Value *CondShadow = getShadow(Condition);
1060 CallInst *CI;
1061 if (DFS.shouldTrackOrigins()) {
1062 Value *CondOrigin = getOrigin(Condition);
1063 CI = IRB.CreateCall(DFS.DFSanConditionalCallbackOriginFn,
1064 {CondShadow, CondOrigin});
1065 } else {
1066 CI = IRB.CreateCall(DFS.DFSanConditionalCallbackFn, {CondShadow});
1067 }
1069}
1070
1071void DFSanFunction::addReachesFunctionCallbacksIfEnabled(IRBuilder<> &IRB,
1072 Instruction &I,
1075 return;
1076 }
1077 const DebugLoc &dbgloc = I.getDebugLoc();
1078 Value *DataShadow = collapseToPrimitiveShadow(getShadow(Data), IRB);
1079 ConstantInt *CILine;
1081
1082 if (dbgloc.get() == nullptr) {
1083 CILine = llvm::ConstantInt::get(I.getContext(), llvm::APInt(32, 0));
1085 I.getFunction()->getParent()->getSourceFileName());
1086 } else {
1087 CILine = llvm::ConstantInt::get(I.getContext(),
1088 llvm::APInt(32, dbgloc.getLine()));
1090 }
1091
1094
1095 CallInst *CB;
1096 std::vector<Value *> args;
1097
1098 if (DFS.shouldTrackOrigins()) {
1099 Value *DataOrigin = getOrigin(Data);
1100 args = { DataShadow, DataOrigin, FilePathPtr, CILine, FunctionNamePtr };
1101 CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackOriginFn, args);
1102 } else {
1103 args = { DataShadow, FilePathPtr, CILine, FunctionNamePtr };
1104 CB = IRB.CreateCall(DFS.DFSanReachesFunctionCallbackFn, args);
1105 }
1108}
1109
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)));
1125 }
1126 return PrimitiveShadowTy;
1127}
1128
1129Type *DataFlowSanitizer::getShadowTy(Value *V) {
1130 return getShadowTy(V->getType());
1131}
1132
1133bool DataFlowSanitizer::initializeModule(Module &M) {
1134 Triple TargetTriple(M.getTargetTriple());
1135 const DataLayout &DL = M.getDataLayout();
1136
1139 switch (TargetTriple.getArch()) {
1142 break;
1145 break;
1148 break;
1149 default:
1151 }
1152
1154 Ctx = &M.getContext();
1155 Int8Ptr = PointerType::getUnqual(*Ctx);
1157 OriginPtrTy = PointerType::getUnqual(*Ctx);
1158 PrimitiveShadowTy = IntegerType::get(*Ctx, ShadowWidthBits);
1159 PrimitiveShadowPtrTy = PointerType::getUnqual(*Ctx);
1160 IntptrTy = DL.getIntPtrType(*Ctx);
1163
1164 Type *DFSanUnionLoadArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1165 DFSanUnionLoadFnTy = FunctionType::get(PrimitiveShadowTy, DFSanUnionLoadArgs,
1166 false);
1167 Type *DFSanLoadLabelAndOriginArgs[2] = {Int8Ptr, IntptrTy};
1168 DFSanLoadLabelAndOriginFnTy =
1169 FunctionType::get(IntegerType::get(*Ctx, 64), DFSanLoadLabelAndOriginArgs,
1170 false);
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,
1176 false);
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), {},
1182 false);
1183 DFSanVarargWrapperFnTy = FunctionType::get(
1184 Type::getVoidTy(*Ctx), PointerType::getUnqual(*Ctx), false);
1185 DFSanConditionalCallbackFnTy =
1186 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1187 false);
1188 Type *DFSanConditionalCallbackOriginArgs[2] = {PrimitiveShadowTy, OriginTy};
1189 DFSanConditionalCallbackOriginFnTy = FunctionType::get(
1190 Type::getVoidTy(*Ctx), DFSanConditionalCallbackOriginArgs,
1191 false);
1192 Type *DFSanReachesFunctionCallbackArgs[4] = {PrimitiveShadowTy, Int8Ptr,
1193 OriginTy, Int8Ptr};
1194 DFSanReachesFunctionCallbackFnTy =
1195 FunctionType::get(Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackArgs,
1196 false);
1197 Type *DFSanReachesFunctionCallbackOriginArgs[5] = {
1198 PrimitiveShadowTy, OriginTy, Int8Ptr, OriginTy, Int8Ptr};
1199 DFSanReachesFunctionCallbackOriginFnTy = FunctionType::get(
1200 Type::getVoidTy(*Ctx), DFSanReachesFunctionCallbackOriginArgs,
1201 false);
1202 DFSanCmpCallbackFnTy =
1203 FunctionType::get(Type::getVoidTy(*Ctx), PrimitiveShadowTy,
1204 false);
1205 DFSanChainOriginFnTy =
1206 FunctionType::get(OriginTy, OriginTy, false);
1207 Type *DFSanChainOriginIfTaintedArgs[2] = {PrimitiveShadowTy, OriginTy};
1208 DFSanChainOriginIfTaintedFnTy = FunctionType::get(
1209 OriginTy, DFSanChainOriginIfTaintedArgs, false);
1210 Type *DFSanMaybeStoreOriginArgs[4] = {IntegerType::get(*Ctx, ShadowWidthBits),
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,
1220 false);
1221 Type *DFSanMemShadowOriginConditionalExchangeArgs[5] = {
1222 IntegerType::get(*Ctx, 8), Int8Ptr, Int8Ptr, Int8Ptr, IntptrTy};
1223 DFSanMemShadowOriginConditionalExchangeFnTy = FunctionType::get(
1224 Type::getVoidTy(*Ctx), DFSanMemShadowOriginConditionalExchangeArgs,
1225 false);
1226 Type *DFSanLoadStoreCallbackArgs[2] = {PrimitiveShadowTy, Int8Ptr};
1227 DFSanLoadStoreCallbackFnTy =
1228 FunctionType::get(Type::getVoidTy(*Ctx), DFSanLoadStoreCallbackArgs,
1229 false);
1230 Type *DFSanMemTransferCallbackArgs[2] = {PrimitiveShadowPtrTy, IntptrTy};
1231 DFSanMemTransferCallbackFnTy =
1232 FunctionType::get(Type::getVoidTy(*Ctx), DFSanMemTransferCallbackArgs,
1233 false);
1234
1235 ColdCallWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1236 OriginStoreWeights = MDBuilder(*Ctx).createUnlikelyBranchWeights();
1237 return true;
1238}
1239
1240bool DataFlowSanitizer::isInstrumented(const Function *F) {
1241 return !ABIList.isIn(*F, "uninstrumented");
1242}
1243
1244bool DataFlowSanitizer::isInstrumented(const GlobalAlias *GA) {
1245 return !ABIList.isIn(*GA, "uninstrumented");
1246}
1247
1248bool DataFlowSanitizer::isForceZeroLabels(const Function *F) {
1249 return ABIList.isIn(*F, "force_zero_labels");
1250}
1251
1252DataFlowSanitizer::WrapperKind DataFlowSanitizer::getWrapperKind(Function *F) {
1253 if (ABIList.isIn(*F, "functional"))
1254 return WK_Functional;
1255 if (ABIList.isIn(*F, "discard"))
1256 return WK_Discard;
1257 if (ABIList.isIn(*F, "custom"))
1258 return WK_Custom;
1259
1260 return WK_Warning;
1261}
1262
1263void DataFlowSanitizer::addGlobalNameSuffix(GlobalValue *GV) {
1265 return;
1266
1267 std::string GVName = std::string(GV->getName()), Suffix = ".dfsan";
1268 GV->setName(GVName + Suffix);
1269
1270
1271
1272
1273
1274
1276 std::string SearchStr = ".symver " + GVName + ",";
1277 size_t Pos = Asm.find(SearchStr);
1278 if (Pos != std:🧵:npos) {
1279 Asm.replace(Pos, SearchStr.size(), ".symver " + GVName + Suffix + ",");
1280 Pos = Asm.find('@');
1281
1282 if (Pos == std:🧵:npos)
1284
1285 Asm.replace(Pos, 1, Suffix + "@");
1287 }
1288}
1289
1290void DataFlowSanitizer::buildExternWeakCheckIfNeeded(IRBuilder<> &IRB,
1291 Function *F) {
1292
1293
1294
1295
1296
1297
1298
1300 std::vector<Value *> Args;
1303 IRB.CreateCall(DFSanWrapperExternWeakNullFn, Args);
1304 }
1305}
1306
1308DataFlowSanitizer::buildWrapperFunction(Function *F, StringRef NewFName,
1310 FunctionType *NewFT) {
1311 FunctionType *FT = F->getFunctionType();
1313 NewFName, F->getParent());
1315 NewF->removeRetAttrs(AttributeFuncs::typeIncompatible(
1316 NewFT->getReturnType(), NewF->getAttributes().getRetAttrs()));
1317
1319 if (F->isVarArg()) {
1322 IRBuilder<>(BB).CreateGlobalString(F->getName()), "", BB);
1323 new UnreachableInst(*Ctx, BB);
1324 } else {
1325 auto ArgIt = pointer_iterator<Argument *>(NewF->arg_begin());
1326 std::vector<Value *> Args(ArgIt, ArgIt + FT->getNumParams());
1327
1329 if (FT->getReturnType()->isVoidTy())
1331 else
1333 }
1334
1335 return NewF;
1336}
1337
1338
1339void DataFlowSanitizer::initializeRuntimeFunctions(Module &M) {
1340 LLVMContext &C = M.getContext();
1341 {
1342 AttributeList AL;
1343 AL = AL.addFnAttribute(C, Attribute::NoUnwind);
1346 AL = AL.addRetAttribute(C, Attribute::ZExt);
1347 DFSanUnionLoadFn =
1348 Mod->getOrInsertFunction("__dfsan_union_load", DFSanUnionLoadFnTy, AL);
1349 }
1350 {
1351 AttributeList AL;
1352 AL = AL.addFnAttribute(C, Attribute::NoUnwind);
1355 AL = AL.addRetAttribute(C, Attribute::ZExt);
1356 DFSanLoadLabelAndOriginFn = Mod->getOrInsertFunction(
1357 "__dfsan_load_label_and_origin", DFSanLoadLabelAndOriginFnTy, AL);
1358 }
1359 DFSanUnimplementedFn =
1360 Mod->getOrInsertFunction("__dfsan_unimplemented", DFSanUnimplementedFnTy);
1361 DFSanWrapperExternWeakNullFn = Mod->getOrInsertFunction(
1362 "__dfsan_wrapper_extern_weak_null", DFSanWrapperExternWeakNullFnTy);
1363 {
1364 AttributeList AL;
1365 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1366 AL = AL.addParamAttribute(M.getContext(), 1, Attribute::ZExt);
1367 DFSanSetLabelFn =
1368 Mod->getOrInsertFunction("__dfsan_set_label", DFSanSetLabelFnTy, AL);
1369 }
1370 DFSanNonzeroLabelFn =
1371 Mod->getOrInsertFunction("__dfsan_nonzero_label", DFSanNonzeroLabelFnTy);
1372 DFSanVarargWrapperFn = Mod->getOrInsertFunction("__dfsan_vararg_wrapper",
1373 DFSanVarargWrapperFnTy);
1374 {
1375 AttributeList AL;
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);
1380 }
1381 {
1382 AttributeList 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);
1388 }
1389 DFSanMemOriginTransferFn = Mod->getOrInsertFunction(
1390 "__dfsan_mem_origin_transfer", DFSanMemOriginTransferFnTy);
1391
1392 DFSanMemShadowOriginTransferFn = Mod->getOrInsertFunction(
1393 "__dfsan_mem_shadow_origin_transfer", DFSanMemShadowOriginTransferFnTy);
1394
1395 DFSanMemShadowOriginConditionalExchangeFn =
1396 Mod->getOrInsertFunction("__dfsan_mem_shadow_origin_conditional_exchange",
1397 DFSanMemShadowOriginConditionalExchangeFnTy);
1398
1399 {
1400 AttributeList AL;
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);
1405 }
1406
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(
1450}
1451
1452
1453void DataFlowSanitizer::initializeCallbackFunctions(Module &M) {
1454 {
1455 AttributeList AL;
1456 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1457 DFSanLoadCallbackFn = Mod->getOrInsertFunction(
1458 "__dfsan_load_callback", DFSanLoadStoreCallbackFnTy, AL);
1459 }
1460 {
1461 AttributeList AL;
1462 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1463 DFSanStoreCallbackFn = Mod->getOrInsertFunction(
1464 "__dfsan_store_callback", DFSanLoadStoreCallbackFnTy, AL);
1465 }
1466 DFSanMemTransferCallbackFn = Mod->getOrInsertFunction(
1467 "__dfsan_mem_transfer_callback", DFSanMemTransferCallbackFnTy);
1468 {
1469 AttributeList AL;
1470 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1471 DFSanCmpCallbackFn = Mod->getOrInsertFunction("__dfsan_cmp_callback",
1472 DFSanCmpCallbackFnTy, AL);
1473 }
1474 {
1475 AttributeList AL;
1476 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1477 DFSanConditionalCallbackFn = Mod->getOrInsertFunction(
1478 "__dfsan_conditional_callback", DFSanConditionalCallbackFnTy, AL);
1479 }
1480 {
1481 AttributeList AL;
1482 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1483 DFSanConditionalCallbackOriginFn =
1484 Mod->getOrInsertFunction("__dfsan_conditional_callback_origin",
1485 DFSanConditionalCallbackOriginFnTy, AL);
1486 }
1487 {
1488 AttributeList AL;
1489 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1490 DFSanReachesFunctionCallbackFn =
1491 Mod->getOrInsertFunction("__dfsan_reaches_function_callback",
1492 DFSanReachesFunctionCallbackFnTy, AL);
1493 }
1494 {
1495 AttributeList AL;
1496 AL = AL.addParamAttribute(M.getContext(), 0, Attribute::ZExt);
1497 DFSanReachesFunctionCallbackOriginFn =
1498 Mod->getOrInsertFunction("__dfsan_reaches_function_callback_origin",
1499 DFSanReachesFunctionCallbackOriginFnTy, AL);
1500 }
1501}
1502
1503bool DataFlowSanitizer::runImpl(
1504 Module &M, llvm::function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1505 initializeModule(M);
1506
1507 if (ABIList.isIn(M, "skip"))
1508 return false;
1509
1510 const unsigned InitialGlobalSize = M.global_size();
1511 const unsigned InitialModuleSize = M.size();
1512
1514
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);
1520 return G;
1521 };
1522
1523
1524 ArgTLS =
1525 GetOrInsertGlobal("__dfsan_arg_tls",
1526 ArrayType::get(Type::getInt64Ty(*Ctx), ArgTLSSize / 8));
1527 RetvalTLS = GetOrInsertGlobal(
1528 "__dfsan_retval_tls",
1529 ArrayType::get(Type::getInt64Ty(*Ctx), RetvalTLSSize / 8));
1530 ArgOriginTLSTy = ArrayType::get(OriginTy, NumOfElementsInArgOrgTLS);
1531 ArgOriginTLS = GetOrInsertGlobal("__dfsan_arg_origin_tls", ArgOriginTLSTy);
1532 RetvalOriginTLS = GetOrInsertGlobal("__dfsan_retval_origin_tls", OriginTy);
1533
1534 (void)Mod->getOrInsertGlobal("__dfsan_track_origins", OriginTy, [&] {
1535 Changed = true;
1536 return new GlobalVariable(
1537 M, OriginTy, true, GlobalValue::WeakODRLinkage,
1538 ConstantInt::getSigned(OriginTy,
1539 shouldTrackOrigins() ? ClTrackOrigins : 0),
1540 "__dfsan_track_origins");
1541 });
1542
1543 initializeCallbackFunctions(M);
1544 initializeRuntimeFunctions(M);
1545
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 (.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F) &&
1552 !LibAtomicFunction(F) &&
1553 .hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {
1554 FnsToInstrument.push_back(&F);
1555 if (F.hasPersonalityFn())
1556 PersonalityFns.insert(F.getPersonalityFn()->stripPointerCasts());
1557 }
1558
1560 for (auto *C : PersonalityFns) {
1563 if (!isInstrumented(F))
1565 }
1566 }
1567
1568
1569
1571
1572
1574 if ()
1575 continue;
1576
1577 bool GAInst = isInstrumented(&GA), FInst = isInstrumented(F);
1578 if (GAInst && FInst) {
1579 addGlobalNameSuffix(&GA);
1580 } else if (GAInst != FInst) {
1581
1582
1583
1585 buildWrapperFunction(F, "", GA.getLinkage(), F->getFunctionType());
1589 FnsToInstrument.push_back(NewF);
1590 }
1591 }
1592
1593
1594 ReadOnlyNoneAttrs.addAttribute(Attribute::Memory);
1595
1596
1597
1598 for (std::vector<Function *>::iterator FI = FnsToInstrument.begin(),
1599 FE = FnsToInstrument.end();
1600 FI != FE; ++FI) {
1602 FunctionType *FT = F.getFunctionType();
1603
1604 bool IsZeroArgsVoidRet = (FT->getNumParams() == 0 && !FT->isVarArg() &&
1605 FT->getReturnType()->isVoidTy());
1606
1607 if (isInstrumented(&F)) {
1608 if (isForceZeroLabels(&F))
1609 FnsWithForceZeroLabel.insert(&F);
1610
1611
1612
1613
1614 addGlobalNameSuffix(&F);
1615 } else if (!IsZeroArgsVoidRet || getWrapperKind(&F) == WK_Custom) {
1616
1617
1618
1619
1620
1621
1623 F.hasLocalLinkage() ? F.getLinkage()
1625
1626 Function *NewF = buildWrapperFunction(
1627 &F,
1628 (shouldTrackOrigins() ? std::string("dfso$") : std::string("dfsw$")) +
1629 std::string(F.getName()),
1630 WrapperLinkage, FT);
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650 auto IsNotCmpUse = [](Use &U) -> bool {
1653
1654 if (CE->getOpcode() == Instruction::ICmp) {
1655 return false;
1656 }
1657 }
1659 if (I->getOpcode() == Instruction::ICmp) {
1660 return false;
1661 }
1662 }
1663 return true;
1664 };
1665 F.replaceUsesWithIf(NewF, IsNotCmpUse);
1666
1667 UnwrappedFnMap[NewF] = &F;
1668 *FI = NewF;
1669
1670 if (.isDeclaration()) {
1671
1672
1673
1674
1675 FnsWithNativeABI.insert(&F);
1676
1677
1678
1679
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;
1685 }
1686
1687
1688 } else if (FT->isVarArg()) {
1690 *FI = nullptr;
1691 }
1692 }
1693
1694 for (Function *F : FnsToInstrument) {
1695 if ( || F->isDeclaration())
1696 continue;
1697
1699
1700 DFSanFunction DFSF(*this, F, FnsWithNativeABI.count(F),
1701 FnsWithForceZeroLabel.count(F), GetTLI(*F));
1702
1704
1705 for (auto &FArg : F->args()) {
1707 Value *FArgShadow = DFSF.getShadow(&FArg);
1708 if (isZeroShadow(FArgShadow))
1709 continue;
1711 Next = FArgShadowInst->getNextNode();
1712 }
1713 if (shouldTrackOrigins()) {
1714 if (Instruction *Origin =
1716
1717 Instruction *OriginNext = Origin->getNextNode();
1718 if (Next->comesBefore(OriginNext)) {
1719 Next = OriginNext;
1720 }
1721 }
1722 }
1724 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, *Next, &FArg);
1725 }
1726 }
1727
1728
1729
1731
1732 for (BasicBlock *BB : BBList) {
1734 while (true) {
1735
1736
1737
1739
1740
1742 if (!DFSF.SkipInsts.count(Inst))
1743 DFSanVisitor(DFSF).visit(Inst);
1744 if (IsTerminator)
1745 break;
1746 Inst = Next;
1747 }
1748 }
1749
1750
1751
1752
1753
1754 for (DFSanFunction::PHIFixupElement &P : DFSF.PHIFixups) {
1755 for (unsigned Val = 0, N = P.Phi->getNumIncomingValues(); Val != N;
1756 ++Val) {
1757 P.ShadowPhi->setIncomingValue(
1758 Val, DFSF.getShadow(P.Phi->getIncomingValue(Val)));
1759 if (P.OriginPhi)
1760 P.OriginPhi->setIncomingValue(
1761 Val, DFSF.getOrigin(P.Phi->getIncomingValue(Val)));
1762 }
1763 }
1764
1765
1766
1767
1768
1770 for (Value *V : DFSF.NonZeroChecks) {
1773 Pos = std::next(I->getIterator());
1774 else
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, {});
1786 }
1787 }
1788 }
1789
1790 return Changed || !FnsToInstrument.empty() ||
1791 M.global_size() != InitialGlobalSize || M.size() != InitialModuleSize;
1792}
1793
1795 return IRB.CreatePtrAdd(DFS.ArgTLS, ConstantInt::get(DFS.IntptrTy, ArgOffset),
1796 "_dfsarg");
1797}
1798
1800 return IRB.CreatePointerCast(DFS.RetvalTLS, PointerType::get(*DFS.Ctx, 0),
1801 "_dfsret");
1802}
1803
1804Value *DFSanFunction::getRetvalOriginTLS() { return DFS.RetvalOriginTLS; }
1805
1806Value *DFSanFunction::getArgOriginTLS(unsigned ArgNo, IRBuilder<> &IRB) {
1808 ArgNo, "_dfsarg_o");
1809}
1810
1811Value *DFSanFunction::getOrigin(Value *V) {
1812 assert(DFS.shouldTrackOrigins());
1814 return DFS.ZeroOrigin;
1815 Value *&Origin = ValOriginMap[V];
1816 if (!Origin) {
1818 if (IsNativeABI)
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);
1825 } else {
1826
1827 Origin = DFS.ZeroOrigin;
1828 }
1829 } else {
1830 Origin = DFS.ZeroOrigin;
1831 }
1832 }
1833 return Origin;
1834}
1835
1836void DFSanFunction::setOrigin(Instruction *I, Value *Origin) {
1837 if (!DFS.shouldTrackOrigins())
1838 return;
1841 ValOriginMap[I] = Origin;
1842}
1843
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()) {
1849 if (A == &FArg)
1850 break;
1851 continue;
1852 }
1853
1854 unsigned Size = DL.getTypeAllocSize(DFS.getShadowTy(&FArg));
1855 if (A != &FArg) {
1858 break;
1859 continue;
1860 }
1861
1863 break;
1864
1865 Instruction *ArgTLSPos = &*F->getEntryBlock().begin();
1867 Value *ArgShadowPtr = getArgTLS(FArg.getType(), ArgOffset, IRB);
1868 return IRB.CreateAlignedLoad(DFS.getShadowTy(&FArg), ArgShadowPtr,
1870 }
1871
1872 return DFS.getZeroShadow(A);
1873}
1874
1875Value *DFSanFunction::getShadow(Value *V) {
1877 return DFS.getZeroShadow(V);
1878 if (IsForceZeroLabels)
1879 return DFS.getZeroShadow(V);
1880 Value *&Shadow = ValShadowMap[V];
1881 if (!Shadow) {
1883 if (IsNativeABI)
1884 return DFS.getZeroShadow(V);
1885 Shadow = getShadowForTLSArgument(A);
1886 NonZeroChecks.push_back(Shadow);
1887 } else {
1888 Shadow = DFS.getZeroShadow(V);
1889 }
1890 }
1891 return Shadow;
1892}
1893
1894void DFSanFunction::setShadow(Instruction *I, Value *Shadow) {
1896 ValShadowMap[I] = Shadow;
1897}
1898
1899
1900
1901
1902
1904 assert(Addr != RetvalTLS && "Reinstrumenting?");
1906
1907 uint64_t AndMask = MapParams->AndMask;
1908 if (AndMask)
1909 OffsetLong =
1910 IRB.CreateAnd(OffsetLong, ConstantInt::get(IntptrTy, ~AndMask));
1911
1912 uint64_t XorMask = MapParams->XorMask;
1913 if (XorMask)
1914 OffsetLong = IRB.CreateXor(OffsetLong, ConstantInt::get(IntptrTy, XorMask));
1915 return OffsetLong;
1916}
1917
1918std::pair<Value *, Value *>
1919DataFlowSanitizer::getShadowOriginAddress(Value *Addr, Align InstAlignment,
1921
1923 Value *ShadowOffset = getShadowOffset(Addr, IRB);
1924 Value *ShadowLong = ShadowOffset;
1925 uint64_t ShadowBase = MapParams->ShadowBase;
1926 if (ShadowBase != 0) {
1927 ShadowLong =
1928 IRB.CreateAdd(ShadowLong, ConstantInt::get(IntptrTy, ShadowBase));
1929 }
1930 Value *ShadowPtr = IRB.CreateIntToPtr(ShadowLong, PointerType::get(*Ctx, 0));
1931 Value *OriginPtr = nullptr;
1932 if (shouldTrackOrigins()) {
1933 Value *OriginLong = ShadowOffset;
1934 uint64_t OriginBase = MapParams->OriginBase;
1935 if (OriginBase != 0)
1936 OriginLong =
1937 IRB.CreateAdd(OriginLong, ConstantInt::get(IntptrTy, OriginBase));
1939
1940
1943 OriginLong = IRB.CreateAnd(OriginLong, ConstantInt::get(IntptrTy, ~Mask));
1944 }
1945 OriginPtr = IRB.CreateIntToPtr(OriginLong, OriginPtrTy);
1946 }
1947 return std::make_pair(ShadowPtr, OriginPtr);
1948}
1949
1950Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
1952 Value *ShadowOffset) {
1954 return IRB.CreateIntToPtr(ShadowOffset, PrimitiveShadowPtrTy);
1955}
1956
1957Value *DataFlowSanitizer::getShadowAddress(Value *Addr,
1960 Value *ShadowAddr = getShadowOffset(Addr, IRB);
1961 uint64_t ShadowBase = MapParams->ShadowBase;
1962 if (ShadowBase != 0)
1963 ShadowAddr =
1964 IRB.CreateAdd(ShadowAddr, ConstantInt::get(IntptrTy, ShadowBase));
1965 return getShadowAddress(Addr, Pos, ShadowAddr);
1966}
1967
1968Value *DFSanFunction::combineShadowsThenConvert(Type *T, Value *V1, Value *V2,
1970 Value *PrimitiveValue = combineShadows(V1, V2, Pos);
1971 return expandFromPrimitiveShadow(T, PrimitiveValue, Pos);
1972}
1973
1974
1975
1976Value *DFSanFunction::combineShadows(Value *V1, Value *V2,
1978 if (DFS.isZeroShadow(V1))
1979 return collapseToPrimitiveShadow(V2, Pos);
1980 if (DFS.isZeroShadow(V2))
1981 return collapseToPrimitiveShadow(V1, Pos);
1982 if (V1 == V2)
1983 return collapseToPrimitiveShadow(V1, Pos);
1984
1985 auto V1Elems = ShadowElements.find(V1);
1986 auto V2Elems = ShadowElements.find(V2);
1987 if (V1Elems != ShadowElements.end() && V2Elems != ShadowElements.end()) {
1988 if (llvm::includes(V1Elems->second, V2Elems->second)) {
1989 return collapseToPrimitiveShadow(V1, Pos);
1990 }
1991 if (llvm::includes(V2Elems->second, V1Elems->second)) {
1992 return collapseToPrimitiveShadow(V2, Pos);
1993 }
1994 } else if (V1Elems != ShadowElements.end()) {
1995 if (V1Elems->second.count(V2))
1996 return collapseToPrimitiveShadow(V1, Pos);
1997 } else if (V2Elems != ShadowElements.end()) {
1998 if (V2Elems->second.count(V1))
1999 return collapseToPrimitiveShadow(V2, Pos);
2000 }
2001
2002 auto Key = std::make_pair(V1, V2);
2003 if (V1 > V2)
2005 CachedShadow &CCS = CachedShadows[Key];
2006 if (CCS.Block && DT.dominates(CCS.Block, Pos->getParent()))
2007 return CCS.Shadow;
2008
2009
2010 Value *PV1 = collapseToPrimitiveShadow(V1, Pos);
2011 Value *PV2 = collapseToPrimitiveShadow(V2, Pos);
2012
2014 CCS.Block = Pos->getParent();
2015 CCS.Shadow = IRB.CreateOr(PV1, PV2);
2016
2017 std::set<Value *> UnionElems;
2018 if (V1Elems != ShadowElements.end()) {
2019 UnionElems = V1Elems->second;
2020 } else {
2021 UnionElems.insert(V1);
2022 }
2023 if (V2Elems != ShadowElements.end()) {
2024 UnionElems.insert(V2Elems->second.begin(), V2Elems->second.end());
2025 } else {
2026 UnionElems.insert(V2);
2027 }
2028 ShadowElements[CCS.Shadow] = std::move(UnionElems);
2029
2030 return CCS.Shadow;
2031}
2032
2033
2034
2035
2036Value *DFSanFunction::combineOperandShadows(Instruction *Inst) {
2038 return DFS.getZeroShadow(Inst);
2039
2042 Shadow = combineShadows(Shadow, getShadow(Inst->getOperand(I)),
2044
2045 return expandFromPrimitiveShadow(Inst->getType(), Shadow,
2047}
2048
2049void DFSanVisitor::visitInstOperands(Instruction &I) {
2050 Value *CombinedShadow = DFSF.combineOperandShadows(&I);
2051 DFSF.setShadow(&I, CombinedShadow);
2052 visitInstOperandOrigins(I);
2053}
2054
2055Value *DFSanFunction::combineOrigins(const std::vector<Value *> &Shadows,
2056 const std::vector<Value *> &Origins,
2058 ConstantInt *Zero) {
2059 assert(Shadows.size() == Origins.size());
2060 size_t Size = Origins.size();
2061 if (Size == 0)
2062 return DFS.ZeroOrigin;
2063 Value *Origin = nullptr;
2064 if (!Zero)
2065 Zero = DFS.ZeroPrimitiveShadow;
2066 for (size_t I = 0; I != Size; ++I) {
2067 Value *OpOrigin = Origins[I];
2069 if (ConstOpOrigin && ConstOpOrigin->isNullValue())
2070 continue;
2071 if (!Origin) {
2072 Origin = OpOrigin;
2073 continue;
2074 }
2075 Value *OpShadow = Shadows[I];
2076 Value *PrimitiveShadow = collapseToPrimitiveShadow(OpShadow, Pos);
2080 }
2081 return Origin ? Origin : DFS.ZeroOrigin;
2082}
2083
2084Value *DFSanFunction::combineOperandOrigins(Instruction *Inst) {
2086 std::vector<Value *> Shadows(Size);
2087 std::vector<Value *> Origins(Size);
2088 for (unsigned I = 0; I != Size; ++I) {
2089 Shadows[I] = getShadow(Inst->getOperand(I));
2090 Origins[I] = getOrigin(Inst->getOperand(I));
2091 }
2092 return combineOrigins(Shadows, Origins, Inst->getIterator());
2093}
2094
2095void DFSanVisitor::visitInstOperandOrigins(Instruction &I) {
2096 if (!DFSF.DFS.shouldTrackOrigins())
2097 return;
2098 Value *CombinedOrigin = DFSF.combineOperandOrigins(&I);
2099 DFSF.setOrigin(&I, CombinedOrigin);
2100}
2101
2102Align DFSanFunction::getShadowAlign(Align InstAlignment) {
2104 return Align(Alignment.value() * DFS.ShadowWidthBytes);
2105}
2106
2107Align DFSanFunction::getOriginAlign(Align InstAlignment) {
2110}
2111
2112bool DFSanFunction::isLookupTableConstant(Value *P) {
2114 if (GV->isConstant() && GV->hasName())
2115 return DFS.CombineTaintLookupTableNames.count(GV->getName());
2116
2117 return false;
2118}
2119
2120bool DFSanFunction::useCallbackLoadLabelAndOrigin(uint64_t Size,
2121 Align InstAlignment) {
2122
2123
2125 return true;
2126
2128
2129
2130
2131
2132
2133
2134
2135
2136 if (Size <= 2)
2137 return false;
2138
2141}
2142
2144 Align OriginAlign,
2145 Value **OriginAddr) {
2147 *OriginAddr =
2148 IRB.CreateGEP(OriginTy, *OriginAddr, ConstantInt::get(IntptrTy, 1));
2149 return IRB.CreateAlignedLoad(OriginTy, *OriginAddr, OriginAlign);
2150}
2151
2152std::pair<Value *, Value *> DFSanFunction::loadShadowFast(
2153 Value *ShadowAddr, Value *OriginAddr, uint64_t Size, Align ShadowAlign,
2155 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2156 const uint64_t ShadowSize = Size * DFS.ShadowWidthBytes;
2157
2158 assert(Size >= 4 && "Not large enough load size for fast path!");
2159
2160
2161 std::vector<Value *> Shadows;
2162 std::vector<Value *> Origins;
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175 Type *WideShadowTy =
2176 ShadowSize == 4 ? Type::getInt32Ty(*DFS.Ctx) : Type::getInt64Ty(*DFS.Ctx);
2177
2179 Value *CombinedWideShadow =
2181
2183 const uint64_t BytesPerWideShadow = WideShadowBitWidth / DFS.ShadowWidthBits;
2184
2185 auto AppendWideShadowAndOrigin = [&](Value *WideShadow, Value *Origin) {
2186 if (BytesPerWideShadow > 4) {
2187 assert(BytesPerWideShadow == 8);
2188
2189
2190
2191
2192
2193
2194 Value *WideShadowLo =
2195 F->getParent()->getDataLayout().isLittleEndian()
2197 WideShadow,
2198 ConstantInt::get(WideShadowTy, WideShadowBitWidth / 2))
2200 WideShadow,
2201 ConstantInt::get(WideShadowTy,
2202 (1 - (1 << (WideShadowBitWidth / 2)))
2203 << (WideShadowBitWidth / 2)));
2204 Shadows.push_back(WideShadow);
2205 Origins.push_back(DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr));
2206
2207 Shadows.push_back(WideShadowLo);
2208 Origins.push_back(Origin);
2209 } else {
2210 Shadows.push_back(WideShadow);
2211 Origins.push_back(Origin);
2212 }
2213 };
2214
2215 if (ShouldTrackOrigins)
2216 AppendWideShadowAndOrigin(CombinedWideShadow, FirstOrigin);
2217
2218
2219
2220
2221
2222
2223 for (uint64_t ByteOfs = BytesPerWideShadow; ByteOfs < Size;
2224 ByteOfs += BytesPerWideShadow) {
2225 ShadowAddr = IRB.CreateGEP(WideShadowTy, ShadowAddr,
2226 ConstantInt::get(DFS.IntptrTy, 1));
2227 Value *NextWideShadow =
2229 CombinedWideShadow = IRB.CreateOr(CombinedWideShadow, NextWideShadow);
2230 if (ShouldTrackOrigins) {
2231 Value *NextOrigin = DFS.loadNextOrigin(Pos, OriginAlign, &OriginAddr);
2232 AppendWideShadowAndOrigin(NextWideShadow, NextOrigin);
2233 }
2234 }
2235 for (unsigned Width = WideShadowBitWidth / 2; Width >= DFS.ShadowWidthBits;
2236 Width >>= 1) {
2237 Value *ShrShadow = IRB.CreateLShr(CombinedWideShadow, Width);
2238 CombinedWideShadow = IRB.CreateOr(CombinedWideShadow, ShrShadow);
2239 }
2240 return {IRB.CreateTrunc(CombinedWideShadow, DFS.PrimitiveShadowTy),
2241 ShouldTrackOrigins
2242 ? combineOrigins(Shadows, Origins, Pos,
2244 : DFS.ZeroOrigin};
2245}
2246
2247std::pair<Value *, Value *> DFSanFunction::loadShadowOriginSansLoadTracking(
2249 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins();
2250
2251
2253 const auto SI = AllocaShadowMap.find(AI);
2254 if (SI != AllocaShadowMap.end()) {
2256 Value *ShadowLI = IRB.CreateLoad(DFS.PrimitiveShadowTy, SI->second);
2257 const auto OI = AllocaOriginMap.find(AI);
2258 assert(!ShouldTrackOrigins || OI != AllocaOriginMap.end());
2259 return {ShadowLI, ShouldTrackOrigins
2260 ? IRB.CreateLoad(DFS.OriginTy, OI->second)
2261 : nullptr};
2262 }
2263 }
2264
2265
2266 SmallVector<const Value *, 2> Objs;
2268 bool AllConstants = true;
2269 for (const Value *Obj : Objs) {
2271 continue;
2273 continue;
2274
2275 AllConstants = false;
2276 break;
2277 }
2278 if (AllConstants)
2279 return {DFS.ZeroPrimitiveShadow,
2280 ShouldTrackOrigins ? DFS.ZeroOrigin : nullptr};
2281
2282 if (Size == 0)
2283 return {DFS.ZeroPrimitiveShadow,
2284 ShouldTrackOrigins ? DFS.ZeroOrigin : nullptr};
2285
2286
2287
2288 if (ShouldTrackOrigins &&
2289 useCallbackLoadLabelAndOrigin(Size, InstAlignment)) {
2291 CallInst *Call =
2292 IRB.CreateCall(DFS.DFSanLoadLabelAndOriginFn,
2293 {Addr, ConstantInt::get(DFS.IntptrTy, Size)});
2296 DFS.PrimitiveShadowTy),
2298 }
2299
2300
2301 Value *ShadowAddr, *OriginAddr;
2302 std::tie(ShadowAddr, OriginAddr) =
2303 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2304
2305 const Align ShadowAlign = getShadowAlign(InstAlignment);
2306 const Align OriginAlign = getOriginAlign(InstAlignment);
2307 Value *Origin = nullptr;
2308 if (ShouldTrackOrigins) {
2310 Origin = IRB.CreateAlignedLoad(DFS.OriginTy, OriginAddr, OriginAlign);
2311 }
2312
2313
2314
2315 switch (Size) {
2316 case 1: {
2317 LoadInst *LI = new LoadInst(DFS.PrimitiveShadowTy, ShadowAddr, "", Pos);
2319 return {LI, Origin};
2320 }
2321 case 2: {
2323 Value *ShadowAddr1 = IRB.CreateGEP(DFS.PrimitiveShadowTy, ShadowAddr,
2324 ConstantInt::get(DFS.IntptrTy, 1));
2326 IRB.CreateAlignedLoad(DFS.PrimitiveShadowTy, ShadowAddr, ShadowAlign);
2328 IRB.CreateAlignedLoad(DFS.PrimitiveShadowTy, ShadowAddr1, ShadowAlign);
2329 return {combineShadows(Load, Load1, Pos), Origin};
2330 }
2331 }
2332 bool HasSizeForFastPath = DFS.hasLoadSizeForFastPath(Size);
2333
2334 if (HasSizeForFastPath)
2335 return loadShadowFast(ShadowAddr, OriginAddr, Size, ShadowAlign,
2336 OriginAlign, Origin, Pos);
2337
2339 CallInst *FallbackCall = IRB.CreateCall(
2340 DFS.DFSanUnionLoadFn, {ShadowAddr, ConstantInt::get(DFS.IntptrTy, Size)});
2341 FallbackCall->addRetAttr(Attribute::ZExt);
2342 return {FallbackCall, Origin};
2343}
2344
2345std::pair<Value *, Value *>
2346DFSanFunction::loadShadowOrigin(Value *Addr, uint64_t Size, Align InstAlignment,
2348 Value *PrimitiveShadow, *Origin;
2349 std::tie(PrimitiveShadow, Origin) =
2350 loadShadowOriginSansLoadTracking(Addr, Size, InstAlignment, Pos);
2351 if (DFS.shouldTrackOrigins()) {
2355 if (!ConstantShadow || !ConstantShadow->isZeroValue())
2356 Origin = updateOriginIfTainted(PrimitiveShadow, Origin, IRB);
2357 }
2358 }
2359 return {PrimitiveShadow, Origin};
2360}
2361
2363 switch (AO) {
2375 }
2377}
2378
2380 if (!V->getType()->isPointerTy())
2381 return V;
2382
2383
2384
2387 do {
2389 V = GEP->getPointerOperand();
2392 if (!V->getType()->isPointerTy())
2393 return V;
2396 }
2397 } while (Visited.insert(V).second);
2398
2399 return V;
2400}
2401
2402void DFSanVisitor::visitLoadInst(LoadInst &LI) {
2404 uint64_t Size = DL.getTypeStoreSize(LI.getType());
2405 if (Size == 0) {
2406 DFSF.setShadow(&LI, DFSF.DFS.getZeroShadow(&LI));
2407 DFSF.setOrigin(&LI, DFSF.DFS.ZeroOrigin);
2408 return;
2409 }
2410
2411
2412
2413
2414
2415
2418
2422 Pos = std::next(Pos);
2423
2424 std::vector<Value *> Shadows;
2425 std::vector<Value *> Origins;
2426 Value *PrimitiveShadow, *Origin;
2427 std::tie(PrimitiveShadow, Origin) =
2429 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2430 if (ShouldTrackOrigins) {
2431 Shadows.push_back(PrimitiveShadow);
2432 Origins.push_back(Origin);
2433 }
2435 DFSF.isLookupTableConstant(
2438 PrimitiveShadow = DFSF.combineShadows(PrimitiveShadow, PtrShadow, Pos);
2439 if (ShouldTrackOrigins) {
2440 Shadows.push_back(PtrShadow);
2442 }
2443 }
2444 if (!DFSF.DFS.isZeroShadow(PrimitiveShadow))
2445 DFSF.NonZeroChecks.push_back(PrimitiveShadow);
2446
2448 DFSF.expandFromPrimitiveShadow(LI.getType(), PrimitiveShadow, Pos);
2449 DFSF.setShadow(&LI, Shadow);
2450
2451 if (ShouldTrackOrigins) {
2452 DFSF.setOrigin(&LI, DFSF.combineOrigins(Shadows, Origins, Pos));
2453 }
2454
2458 CallInst *CI =
2459 IRB.CreateCall(DFSF.DFS.DFSanLoadCallbackFn, {PrimitiveShadow, Addr});
2461 }
2462
2463 IRBuilder<> IRB(AfterLi->getParent(), AfterLi);
2464 DFSF.addReachesFunctionCallbacksIfEnabled(IRB, LI, &LI);
2465}
2466
2467Value *DFSanFunction::updateOriginIfTainted(Value *Shadow, Value *Origin,
2469 assert(DFS.shouldTrackOrigins());
2470 return IRB.CreateCall(DFS.DFSanChainOriginIfTaintedFn, {Shadow, Origin});
2471}
2472
2474 if (!DFS.shouldTrackOrigins())
2475 return V;
2476 return IRB.CreateCall(DFS.DFSanChainOriginFn, V);
2477}
2478
2480 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2481 const DataLayout &DL = F->getDataLayout();
2482 unsigned IntptrSize = DL.getTypeStoreSize(DFS.IntptrTy);
2483 if (IntptrSize == OriginSize)
2484 return Origin;
2485 assert(IntptrSize == OriginSize * 2);
2486 Origin = IRB.CreateIntCast(Origin, DFS.IntptrTy, false);
2487 return IRB.CreateOr(Origin, IRB.CreateShl(Origin, OriginSize * 8));
2488}
2489
2490void DFSanFunction::paintOrigin(IRBuilder<> &IRB, Value *Origin,
2491 Value *StoreOriginAddr,
2492 uint64_t StoreOriginSize, Align Alignment) {
2493 const unsigned OriginSize = DataFlowSanitizer::OriginWidthBytes;
2494 const DataLayout &DL = F->getDataLayout();
2495 const Align IntptrAlignment = DL.getABITypeAlign(DFS.IntptrTy);
2496 unsigned IntptrSize = DL.getTypeStoreSize(DFS.IntptrTy);
2498 assert(IntptrSize >= OriginSize);
2499
2500 unsigned Ofs = 0;
2501 Align CurrentAlignment = Alignment;
2502 if (Alignment >= IntptrAlignment && IntptrSize > OriginSize) {
2503 Value *IntptrOrigin = originToIntptr(IRB, Origin);
2504 Value *IntptrStoreOriginPtr =
2505 IRB.CreatePointerCast(StoreOriginAddr, PointerType::get(*DFS.Ctx, 0));
2506 for (unsigned I = 0; I < StoreOriginSize / IntptrSize; ++I) {
2509 : IntptrStoreOriginPtr;
2511 Ofs += IntptrSize / OriginSize;
2512 CurrentAlignment = IntptrAlignment;
2513 }
2514 }
2515
2516 for (unsigned I = Ofs; I < (StoreOriginSize + OriginSize - 1) / OriginSize;
2517 ++I) {
2519 : StoreOriginAddr;
2522 }
2523}
2524
2526 const Twine &Name) {
2527 Type *VTy = V->getType();
2530
2531 return V;
2532 return IRB.CreateICmpNE(V, ConstantInt::get(VTy, 0), Name);
2533}
2534
2537 Value *StoreOriginAddr, Align InstAlignment) {
2538
2539
2540 const Align OriginAlignment = getOriginAlign(InstAlignment);
2541 Value *CollapsedShadow = collapseToPrimitiveShadow(Shadow, Pos);
2544 if (!ConstantShadow->isZeroValue())
2545 paintOrigin(IRB, updateOrigin(Origin, IRB), StoreOriginAddr, Size,
2546 OriginAlignment);
2547 return;
2548 }
2549
2550 if (shouldInstrumentWithCall()) {
2552 DFS.DFSanMaybeStoreOriginFn,
2553 {CollapsedShadow, Addr, ConstantInt::get(DFS.IntptrTy, Size), Origin});
2554 } else {
2555 Value *Cmp = convertToBool(CollapsedShadow, IRB, "_dfscmp");
2556 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
2558 Cmp, &*IRB.GetInsertPoint(), false, DFS.OriginStoreWeights, &DTU);
2560 paintOrigin(IRBNew, updateOrigin(Origin, IRBNew), StoreOriginAddr, Size,
2561 OriginAlignment);
2562 ++NumOriginStores;
2563 }
2564}
2565
2566void DFSanFunction::storeZeroPrimitiveShadow(Value *Addr, uint64_t Size,
2567 Align ShadowAlign,
2570 IntegerType *ShadowTy =
2572 Value *ExtZeroShadow = ConstantInt::get(ShadowTy, 0);
2573 Value *ShadowAddr = DFS.getShadowAddress(Addr, Pos);
2575
2576
2577}
2578
2579void DFSanFunction::storePrimitiveShadowOrigin(Value *Addr, uint64_t Size,
2580 Align InstAlignment,
2581 Value *PrimitiveShadow,
2584 const bool ShouldTrackOrigins = DFS.shouldTrackOrigins() && Origin;
2585
2587 const auto SI = AllocaShadowMap.find(AI);
2588 if (SI != AllocaShadowMap.end()) {
2591
2592
2593
2594 if (ShouldTrackOrigins && !DFS.isZeroShadow(PrimitiveShadow)) {
2595 const auto OI = AllocaOriginMap.find(AI);
2596 assert(OI != AllocaOriginMap.end() && Origin);
2598 }
2599 return;
2600 }
2601 }
2602
2603 const Align ShadowAlign = getShadowAlign(InstAlignment);
2604 if (DFS.isZeroShadow(PrimitiveShadow)) {
2605 storeZeroPrimitiveShadow(Addr, Size, ShadowAlign, Pos);
2606 return;
2607 }
2608
2610 Value *ShadowAddr, *OriginAddr;
2611 std::tie(ShadowAddr, OriginAddr) =
2612 DFS.getShadowOriginAddress(Addr, InstAlignment, Pos);
2613
2614 const unsigned ShadowVecSize = 8;
2615 assert(ShadowVecSize * DFS.ShadowWidthBits <= 128 &&
2616 "Shadow vector is too large!");
2617
2618 uint64_t Offset = 0;
2619 uint64_t LeftSize = Size;
2620 if (LeftSize >= ShadowVecSize) {
2621 auto *ShadowVecTy =
2624 for (unsigned I = 0; I != ShadowVecSize; ++I) {
2626 ShadowVec, PrimitiveShadow,
2627 ConstantInt::get(Type::getInt32Ty(*DFS.Ctx), I));
2628 }
2629 do {
2630 Value *CurShadowVecAddr =
2633 LeftSize -= ShadowVecSize;
2635 } while (LeftSize >= ShadowVecSize);
2636 Offset *= ShadowVecSize;
2637 }
2638 while (LeftSize > 0) {
2639 Value *CurShadowAddr =
2641 IRB.CreateAlignedStore(PrimitiveShadow, CurShadowAddr, ShadowAlign);
2642 --LeftSize;
2644 }
2645
2646 if (ShouldTrackOrigins) {
2647 storeOrigin(Pos, Addr, Size, PrimitiveShadow, Origin, OriginAddr,
2648 InstAlignment);
2649 }
2650}
2651
2653 switch (AO) {
2665 }
2667}
2668
2669void DFSanVisitor::visitStoreInst(StoreInst &SI) {
2670 auto &DL = SI.getDataLayout();
2671 Value *Val = SI.getValueOperand();
2672 uint64_t Size = DL.getTypeStoreSize(Val->getType());
2673 if (Size == 0)
2674 return;
2675
2676
2677
2678
2679
2680
2681 if (SI.isAtomic())
2683
2684 const bool ShouldTrackOrigins =
2685 DFSF.DFS.shouldTrackOrigins() && .isAtomic();
2686 std::vector<Value *> Shadows;
2687 std::vector<Value *> Origins;
2688
2690 SI.isAtomic() ? DFSF.DFS.getZeroShadow(Val) : DFSF.getShadow(Val);
2691
2692 if (ShouldTrackOrigins) {
2693 Shadows.push_back(Shadow);
2694 Origins.push_back(DFSF.getOrigin(Val));
2695 }
2696
2697 Value *PrimitiveShadow;
2699 Value *PtrShadow = DFSF.getShadow(SI.getPointerOperand());
2700 if (ShouldTrackOrigins) {
2701 Shadows.push_back(PtrShadow);
2702 Origins.push_back(DFSF.getOrigin(SI.getPointerOperand()));
2703 }
2704 PrimitiveShadow = DFSF.combineShadows(Shadow, PtrShadow, SI.getIterator());
2705 } else {
2706 PrimitiveShadow = DFSF.collapseToPrimitiveShadow(Shadow, SI.getIterator());
2707 }
2708 Value *Origin = nullptr;
2709 if (ShouldTrackOrigins)
2710 Origin = DFSF.combineOrigins(Shadows, Origins, SI.getIterator());
2711 DFSF.storePrimitiveShadowOrigin(SI.getPointerOperand(), Size, SI.getAlign(),
2712 PrimitiveShadow, Origin, SI.getIterator());
2715 Value *Addr = SI.getPointerOperand();
2716 CallInst *CI =
2717 IRB.CreateCall(DFSF.DFS.DFSanStoreCallbackFn, {PrimitiveShadow, Addr});
2719 }
2720}
2721
2722void DFSanVisitor::visitCASOrRMW(Align InstAlignment, Instruction &I) {
2724
2725 Value *Val = I.getOperand(1);
2726 const auto &DL = I.getDataLayout();
2727 uint64_t Size = DL.getTypeStoreSize(Val->getType());
2728 if (Size == 0)
2729 return;
2730
2731
2732
2734 Value *Addr = I.getOperand(0);
2735 const Align ShadowAlign = DFSF.getShadowAlign(InstAlignment);
2736 DFSF.storeZeroPrimitiveShadow(Addr, Size, ShadowAlign, I.getIterator());
2737 DFSF.setShadow(&I, DFSF.DFS.getZeroShadow(&I));
2738 DFSF.setOrigin(&I, DFSF.DFS.ZeroOrigin);
2739}
2740
2741void DFSanVisitor::visitAtomicRMWInst(AtomicRMWInst &I) {
2742 visitCASOrRMW(I.getAlign(), I);
2743
2744
2746}
2747
2748void DFSanVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) {
2749 visitCASOrRMW(I.getAlign(), I);
2750
2751
2753}
2754
2755void DFSanVisitor::visitUnaryOperator(UnaryOperator &UO) {
2756 visitInstOperands(UO);
2757}
2758
2759void DFSanVisitor::visitBinaryOperator(BinaryOperator &BO) {
2760 visitInstOperands(BO);
2761}
2762
2763void DFSanVisitor::visitBitCastInst(BitCastInst &BCI) {
2764
2765
2766
2769 return;
2770 visitInstOperands(BCI);
2771}
2772
2773void DFSanVisitor::visitCastInst(CastInst &CI) { visitInstOperands(CI); }
2774
2775void DFSanVisitor::visitCmpInst(CmpInst &CI) {
2776 visitInstOperands(CI);
2779 Value *CombinedShadow = DFSF.getShadow(&CI);
2780 CallInst *CallI =
2781 IRB.CreateCall(DFSF.DFS.DFSanCmpCallbackFn, CombinedShadow);
2783 }
2784}
2785
2786void DFSanVisitor::visitLandingPadInst(LandingPadInst &LPI) {
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798 DFSF.setShadow(&LPI, DFSF.DFS.getZeroShadow(&LPI));
2799 DFSF.setOrigin(&LPI, DFSF.DFS.ZeroOrigin);
2800}
2801
2802void DFSanVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
2804 DFSF.isLookupTableConstant(
2806 visitInstOperands(GEPI);
2807 return;
2808 }
2809
2810
2811
2813 DFSF.setShadow(&GEPI, DFSF.getShadow(BasePointer));
2814 if (DFSF.DFS.shouldTrackOrigins())
2815 DFSF.setOrigin(&GEPI, DFSF.getOrigin(BasePointer));
2816}
2817
2818void DFSanVisitor::visitExtractElementInst(ExtractElementInst &I) {
2819 visitInstOperands(I);
2820}
2821
2822void DFSanVisitor::visitInsertElementInst(InsertElementInst &I) {
2823 visitInstOperands(I);
2824}
2825
2826void DFSanVisitor::visitShuffleVectorInst(ShuffleVectorInst &I) {
2827 visitInstOperands(I);
2828}
2829
2830void DFSanVisitor::visitExtractValueInst(ExtractValueInst &I) {
2832 Value *Agg = I.getAggregateOperand();
2833 Value *AggShadow = DFSF.getShadow(Agg);
2835 DFSF.setShadow(&I, ResShadow);
2836 visitInstOperandOrigins(I);
2837}
2838
2839void DFSanVisitor::visitInsertValueInst(InsertValueInst &I) {
2841 Value *AggShadow = DFSF.getShadow(I.getAggregateOperand());
2842 Value *InsShadow = DFSF.getShadow(I.getInsertedValueOperand());
2844 DFSF.setShadow(&I, Res);
2845 visitInstOperandOrigins(I);
2846}
2847
2848void DFSanVisitor::visitAllocaInst(AllocaInst &I) {
2849 bool AllLoadsStores = true;
2850 for (User *U : I.users()) {
2852 continue;
2853
2855 if (SI->getPointerOperand() == &I)
2856 continue;
2857 }
2858
2859 AllLoadsStores = false;
2860 break;
2861 }
2862 if (AllLoadsStores) {
2864 DFSF.AllocaShadowMap[&I] = IRB.CreateAlloca(DFSF.DFS.PrimitiveShadowTy);
2865 if (DFSF.DFS.shouldTrackOrigins()) {
2866 DFSF.AllocaOriginMap[&I] =
2867 IRB.CreateAlloca(DFSF.DFS.OriginTy, nullptr, "_dfsa");
2868 }
2869 }
2870 DFSF.setShadow(&I, DFSF.DFS.ZeroPrimitiveShadow);
2871 DFSF.setOrigin(&I, DFSF.DFS.ZeroOrigin);
2872}
2873
2874void DFSanVisitor::visitSelectInst(SelectInst &I) {
2875 Value *CondShadow = DFSF.getShadow(I.getCondition());
2876 Value *TrueShadow = DFSF.getShadow(I.getTrueValue());
2877 Value *FalseShadow = DFSF.getShadow(I.getFalseValue());
2878 Value *ShadowSel = nullptr;
2879 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
2880 std::vector<Value *> Shadows;
2881 std::vector<Value *> Origins;
2882 Value *TrueOrigin =
2883 ShouldTrackOrigins ? DFSF.getOrigin(I.getTrueValue()) : nullptr;
2884 Value *FalseOrigin =
2885 ShouldTrackOrigins ? DFSF.getOrigin(I.getFalseValue()) : nullptr;
2886
2887 DFSF.addConditionalCallbacksIfEnabled(I, I.getCondition());
2888
2890 ShadowSel = DFSF.combineShadowsThenConvert(I.getType(), TrueShadow,
2891 FalseShadow, I.getIterator());
2892 if (ShouldTrackOrigins) {
2893 Shadows.push_back(TrueShadow);
2894 Shadows.push_back(FalseShadow);
2895 Origins.push_back(TrueOrigin);
2896 Origins.push_back(FalseOrigin);
2897 }
2898 } else {
2899 if (TrueShadow == FalseShadow) {
2900 ShadowSel = TrueShadow;
2901 if (ShouldTrackOrigins) {
2902 Shadows.push_back(TrueShadow);
2903 Origins.push_back(TrueOrigin);
2904 }
2905 } else {
2906 ShadowSel = SelectInst::Create(I.getCondition(), TrueShadow, FalseShadow,
2907 "", I.getIterator());
2908 if (ShouldTrackOrigins) {
2909 Shadows.push_back(ShadowSel);
2911 FalseOrigin, "", I.getIterator()));
2912 }
2913 }
2914 }
2916 I.getType(), CondShadow,
2917 ShadowSel, I.getIterator())
2918 : ShadowSel);
2919 if (ShouldTrackOrigins) {
2921 Shadows.push_back(CondShadow);
2922 Origins.push_back(DFSF.getOrigin(I.getCondition()));
2923 }
2924 DFSF.setOrigin(&I, DFSF.combineOrigins(Shadows, Origins, I.getIterator()));
2925 }
2926}
2927
2928void DFSanVisitor::visitMemSetInst(MemSetInst &I) {
2930 Value *ValShadow = DFSF.getShadow(I.getValue());
2931 Value *ValOrigin = DFSF.DFS.shouldTrackOrigins()
2932 ? DFSF.getOrigin(I.getValue())
2933 : DFSF.DFS.ZeroOrigin;
2934 IRB.CreateCall(DFSF.DFS.DFSanSetLabelFn,
2935 {ValShadow, ValOrigin, I.getDest(),
2936 IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2937}
2938
2939void DFSanVisitor::visitMemTransferInst(MemTransferInst &I) {
2941
2942
2943
2944 if (DFSF.DFS.shouldTrackOrigins()) {
2946 DFSF.DFS.DFSanMemOriginTransferFn,
2947 {I.getArgOperand(0), I.getArgOperand(1),
2948 IRB.CreateIntCast(I.getArgOperand(2), DFSF.DFS.IntptrTy, false)});
2949 }
2950
2951 Value *DestShadow = DFSF.DFS.getShadowAddress(I.getDest(), I.getIterator());
2952 Value *SrcShadow = DFSF.DFS.getShadowAddress(I.getSource(), I.getIterator());
2953 Value *LenShadow =
2954 IRB.CreateMul(I.getLength(), ConstantInt::get(I.getLength()->getType(),
2955 DFSF.DFS.ShadowWidthBytes));
2957 IRB.CreateCall(I.getFunctionType(), I.getCalledOperand(),
2958 {DestShadow, SrcShadow, LenShadow, I.getVolatileCst()}));
2959 MTI->setDestAlignment(DFSF.getShadowAlign(I.getDestAlign().valueOrOne()));
2960 MTI->setSourceAlignment(DFSF.getShadowAlign(I.getSourceAlign().valueOrOne()));
2963 DFSF.DFS.DFSanMemTransferCallbackFn,
2964 {DestShadow, IRB.CreateZExtOrTrunc(I.getLength(), DFSF.DFS.IntptrTy)});
2965 }
2966}
2967
2968void DFSanVisitor::visitBranchInst(BranchInst &BR) {
2970 return;
2971
2972 DFSF.addConditionalCallbacksIfEnabled(BR, BR.getCondition());
2973}
2974
2975void DFSanVisitor::visitSwitchInst(SwitchInst &SW) {
2976 DFSF.addConditionalCallbacksIfEnabled(SW, SW.getCondition());
2977}
2978
2980
2982 RetVal = I->getOperand(0);
2983 }
2985 return I->isMustTailCall();
2986 }
2987 return false;
2988}
2989
2990void DFSanVisitor::visitReturnInst(ReturnInst &RI) {
2992
2994 return;
2995
2999 unsigned Size = getDataLayout().getTypeAllocSize(DFSF.DFS.getShadowTy(RT));
3001
3002
3004 }
3005 if (DFSF.DFS.shouldTrackOrigins()) {
3007 IRB.CreateStore(O, DFSF.getRetvalOriginTLS());
3008 }
3009 }
3010}
3011
3012void DFSanVisitor::addShadowArguments(Function &F, CallBase &CB,
3013 std::vector<Value *> &Args,
3015 FunctionType *FT = F.getFunctionType();
3016
3018
3019
3020 for (unsigned N = FT->getNumParams(); N != 0; ++I, --N)
3021 Args.push_back(
3022 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*I), CB.getIterator()));
3023
3024
3025 if (FT->isVarArg()) {
3026 auto *LabelVATy = ArrayType::get(DFSF.DFS.PrimitiveShadowTy,
3027 CB.arg_size() - FT->getNumParams());
3028 auto *LabelVAAlloca =
3029 new AllocaInst(LabelVATy, getDataLayout().getAllocaAddrSpace(),
3031
3032 for (unsigned N = 0; I != CB.arg_end(); ++I, ++N) {
3033 auto *LabelVAPtr = IRB.CreateStructGEP(LabelVATy, LabelVAAlloca, N);
3035 DFSF.collapseToPrimitiveShadow(DFSF.getShadow(*I), CB.getIterator()),
3036 LabelVAPtr);
3037 }
3038
3040 }
3041
3042
3043 if (!FT->getReturnType()->isVoidTy()) {
3044 if (!DFSF.LabelReturnAlloca) {
3045 DFSF.LabelReturnAlloca = new AllocaInst(
3046 DFSF.DFS.PrimitiveShadowTy, getDataLayout().getAllocaAddrSpace(),
3048 }
3049 Args.push_back(DFSF.LabelReturnAlloca);
3050 }
3051}
3052
3053void DFSanVisitor::addOriginArguments(Function &F, CallBase &CB,
3054 std::vector<Value *> &Args,
3056 FunctionType *FT = F.getFunctionType();
3057
3059
3060
3061 for (unsigned N = FT->getNumParams(); N != 0; ++I, --N)
3062 Args.push_back(DFSF.getOrigin(*I));
3063
3064
3065 if (FT->isVarArg()) {
3066 auto *OriginVATy =
3067 ArrayType::get(DFSF.DFS.OriginTy, CB.arg_size() - FT->getNumParams());
3068 auto *OriginVAAlloca =
3069 new AllocaInst(OriginVATy, getDataLayout().getAllocaAddrSpace(),
3071
3072 for (unsigned N = 0; I != CB.arg_end(); ++I, ++N) {
3073 auto *OriginVAPtr = IRB.CreateStructGEP(OriginVATy, OriginVAAlloca, N);
3074 IRB.CreateStore(DFSF.getOrigin(*I), OriginVAPtr);
3075 }
3076
3078 }
3079
3080
3081 if (!FT->getReturnType()->isVoidTy()) {
3082 if (!DFSF.OriginReturnAlloca) {
3083 DFSF.OriginReturnAlloca = new AllocaInst(
3084 DFSF.DFS.OriginTy, getDataLayout().getAllocaAddrSpace(),
3086 }
3087 Args.push_back(DFSF.OriginReturnAlloca);
3088 }
3089}
3090
3091bool DFSanVisitor::visitWrappedCallBase(Function &F, CallBase &CB) {
3093 switch (DFSF.DFS.getWrapperKind(&F)) {
3094 case DataFlowSanitizer::WK_Warning:
3096 IRB.CreateCall(DFSF.DFS.DFSanUnimplementedFn,
3098 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3099 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3100 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3101 return true;
3102 case DataFlowSanitizer::WK_Discard:
3104 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3105 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3106 DFSF.setOrigin(&CB, DFSF.DFS.ZeroOrigin);
3107 return true;
3108 case DataFlowSanitizer::WK_Functional:
3110 DFSF.DFS.buildExternWeakCheckIfNeeded(IRB, &F);
3111 visitInstOperands(CB);
3112 return true;
3113 case DataFlowSanitizer::WK_Custom:
3114
3115
3116
3118 if (!CI)
3119 return false;
3120
3121 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3122 FunctionType *FT = F.getFunctionType();
3123 TransformedFunction CustomFn = DFSF.DFS.getCustomFunctionType(FT);
3124 std::string CustomFName = ShouldTrackOrigins ? "__dfso_" : "__dfsw_";
3125 CustomFName += F.getName();
3127 CustomFName, CustomFn.TransformedType);
3129 CustomFn->copyAttributesFrom(&F);
3130
3131
3132 if (!FT->getReturnType()->isVoidTy()) {
3133 CustomFn->removeFnAttrs(DFSF.DFS.ReadOnlyNoneAttrs);
3134 }
3135 }
3136
3137 std::vector<Value *> Args;
3138
3139
3141 for (unsigned N = FT->getNumParams(); N != 0; ++I, --N) {
3143 }
3144
3145
3146 const unsigned ShadowArgStart = Args.size();
3147 addShadowArguments(F, CB, Args, IRB);
3148
3149
3150 const unsigned OriginArgStart = Args.size();
3151 if (ShouldTrackOrigins)
3152 addOriginArguments(F, CB, Args, IRB);
3153
3154
3156
3157 CallInst *CustomCI = IRB.CreateCall(CustomF, Args);
3159 CustomCI->setAttributes(transformFunctionAttributes(
3161
3162
3163
3164
3165 for (unsigned N = 0; N < FT->getNumParams(); N++) {
3166 const unsigned ArgNo = ShadowArgStart + N;
3168 DFSF.DFS.PrimitiveShadowTy)
3169 CustomCI->addParamAttr(ArgNo, Attribute::ZExt);
3170 if (ShouldTrackOrigins) {
3171 const unsigned OriginArgNo = OriginArgStart + N;
3173 DFSF.DFS.OriginTy)
3174 CustomCI->addParamAttr(OriginArgNo, Attribute::ZExt);
3175 }
3176 }
3177
3178
3179 if (!FT->getReturnType()->isVoidTy()) {
3180 LoadInst *LabelLoad =
3181 IRB.CreateLoad(DFSF.DFS.PrimitiveShadowTy, DFSF.LabelReturnAlloca);
3182 DFSF.setShadow(CustomCI,
3183 DFSF.expandFromPrimitiveShadow(
3184 FT->getReturnType(), LabelLoad, CB.getIterator()));
3185 if (ShouldTrackOrigins) {
3186 LoadInst *OriginLoad =
3187 IRB.CreateLoad(DFSF.DFS.OriginTy, DFSF.OriginReturnAlloca);
3188 DFSF.setOrigin(CustomCI, OriginLoad);
3189 }
3190 }
3191
3194 return true;
3195 }
3196 return false;
3197}
3198
3199Value *DFSanVisitor::makeAddAcquireOrderingTable(IRBuilder<> &IRB) {
3200 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3201 uint32_t OrderingTable[NumOrderings] = {};
3202
3203 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3204 OrderingTable[(int)AtomicOrderingCABI::acquire] =
3205 OrderingTable[(int)AtomicOrderingCABI::consume] =
3206 (int)AtomicOrderingCABI::acquire;
3207 OrderingTable[(int)AtomicOrderingCABI::release] =
3208 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3209 (int)AtomicOrderingCABI::acq_rel;
3210 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3211 (int)AtomicOrderingCABI::seq_cst;
3212
3214}
3215
3216void DFSanVisitor::visitLibAtomicLoad(CallBase &CB) {
3217
3219
3225
3226
3227 Value *NewOrdering =
3230
3232 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
3233
3234
3235
3236
3237 NextIRB.CreateCall(
3238 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3239 {DstPtr, SrcPtr, NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3240}
3241
3242Value *DFSanVisitor::makeAddReleaseOrderingTable(IRBuilder<> &IRB) {
3243 constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1;
3244 uint32_t OrderingTable[NumOrderings] = {};
3245
3246 OrderingTable[(int)AtomicOrderingCABI::relaxed] =
3247 OrderingTable[(int)AtomicOrderingCABI::release] =
3248 (int)AtomicOrderingCABI::release;
3249 OrderingTable[(int)AtomicOrderingCABI::consume] =
3250 OrderingTable[(int)AtomicOrderingCABI::acquire] =
3251 OrderingTable[(int)AtomicOrderingCABI::acq_rel] =
3252 (int)AtomicOrderingCABI::acq_rel;
3253 OrderingTable[(int)AtomicOrderingCABI::seq_cst] =
3254 (int)AtomicOrderingCABI::seq_cst;
3255
3257}
3258
3259void DFSanVisitor::visitLibAtomicStore(CallBase &CB) {
3265
3266
3267 Value *NewOrdering =
3270
3271
3272
3273
3275 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3276 {DstPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3277}
3278
3279void DFSanVisitor::visitLibAtomicExchange(CallBase &CB) {
3280
3281
3287
3288
3289
3290
3291
3292
3293
3295 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3296 {DstPtr, TargetPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3297
3298
3300 DFSF.DFS.DFSanMemShadowOriginTransferFn,
3301 {TargetPtr, SrcPtr, IRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3302}
3303
3304void DFSanVisitor::visitLibAtomicCompareExchange(CallBase &CB) {
3305
3306
3311
3312
3313
3314
3315
3316
3318 NextIRB.SetCurrentDebugLocation(CB.getDebugLoc());
3319
3320 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3321
3322
3323
3324 NextIRB.CreateCall(DFSF.DFS.DFSanMemShadowOriginConditionalExchangeFn,
3325 {NextIRB.CreateIntCast(&CB, NextIRB.getInt8Ty(), false),
3326 TargetPtr, ExpectedPtr, DesiredPtr,
3327 NextIRB.CreateIntCast(Size, DFSF.DFS.IntptrTy, false)});
3328}
3329
3330void DFSanVisitor::visitCallBase(CallBase &CB) {
3332 if ((F && F->isIntrinsic()) || CB.isInlineAsm()) {
3333 visitInstOperands(CB);
3334 return;
3335 }
3336
3337
3338
3340 return;
3341
3342 LibFunc LF;
3344
3345
3346
3347 switch (LF) {
3348 case LibFunc_atomic_load:
3350 llvm::errs() << "DFSAN -- cannot instrument invoke of libatomic load. "
3351 "Ignoring!\n";
3352 break;
3353 }
3354 visitLibAtomicLoad(CB);
3355 return;
3356 case LibFunc_atomic_store:
3357 visitLibAtomicStore(CB);
3358 return;
3359 default:
3360 break;
3361 }
3362 }
3363
3364
3365 if (F && F->hasName() && ->isVarArg()) {
3366 if (F->getName() == "__atomic_exchange") {
3367 visitLibAtomicExchange(CB);
3368 return;
3369 }
3370 if (F->getName() == "__atomic_compare_exchange") {
3371 visitLibAtomicCompareExchange(CB);
3372 return;
3373 }
3374 }
3375
3376 DenseMap<Value *, Function *>::iterator UnwrappedFnIt =
3378 if (UnwrappedFnIt != DFSF.DFS.UnwrappedFnMap.end())
3379 if (visitWrappedCallBase(*UnwrappedFnIt->second, CB))
3380 return;
3381
3383
3384 const bool ShouldTrackOrigins = DFSF.DFS.shouldTrackOrigins();
3386 const DataLayout &DL = getDataLayout();
3387
3388
3389 unsigned ArgOffset = 0;
3390 for (unsigned I = 0, N = FT->getNumParams(); I != N; ++I) {
3391 if (ShouldTrackOrigins) {
3392
3394 if (I < DFSF.DFS.NumOfElementsInArgOrgTLS &&
3395 !DFSF.DFS.isZeroShadow(ArgShadow))
3397 DFSF.getArgOriginTLS(I, IRB));
3398 }
3399
3400 unsigned Size =
3401 DL.getTypeAllocSize(DFSF.DFS.getShadowTy(FT->getParamType(I)));
3402
3403
3405 break;
3407 DFSF.getArgTLS(FT->getParamType(I), ArgOffset, IRB),
3410 }
3411
3415 if (II->getNormalDest()->getSinglePredecessor()) {
3416 Next = &II->getNormalDest()->front();
3417 } else {
3419 SplitEdge(II->getParent(), II->getNormalDest(), &DFSF.DT);
3421 }
3422 } else {
3425 }
3426
3427
3429 return;
3430
3431
3433 unsigned Size = DL.getTypeAllocSize(DFSF.DFS.getShadowTy(&CB));
3435
3436 DFSF.setShadow(&CB, DFSF.DFS.getZeroShadow(&CB));
3437 } else {
3438 LoadInst *LI = NextIRB.CreateAlignedLoad(
3439 DFSF.DFS.getShadowTy(&CB), DFSF.getRetvalTLS(CB.getType(), NextIRB),
3441 DFSF.SkipInsts.insert(LI);
3442 DFSF.setShadow(&CB, LI);
3443 DFSF.NonZeroChecks.push_back(LI);
3444 }
3445
3446 if (ShouldTrackOrigins) {
3447 LoadInst *LI = NextIRB.CreateLoad(DFSF.DFS.OriginTy,
3448 DFSF.getRetvalOriginTLS(), "_dfsret_o");
3449 DFSF.SkipInsts.insert(LI);
3450 DFSF.setOrigin(&CB, LI);
3451 }
3452
3453 DFSF.addReachesFunctionCallbacksIfEnabled(NextIRB, CB, &CB);
3454 }
3455}
3456
3457void DFSanVisitor::visitPHINode(PHINode &PN) {
3458 Type *ShadowTy = DFSF.DFS.getShadowTy(&PN);
3461
3462
3464 for (BasicBlock *BB : PN.blocks())
3465 ShadowPN->addIncoming(PoisonShadow, BB);
3466
3467 DFSF.setShadow(&PN, ShadowPN);
3468
3469 PHINode *OriginPN = nullptr;
3470 if (DFSF.DFS.shouldTrackOrigins()) {
3474 for (BasicBlock *BB : PN.blocks())
3475 OriginPN->addIncoming(PoisonOrigin, BB);
3476 DFSF.setOrigin(&PN, OriginPN);
3477 }
3478
3479 DFSF.PHIFixups.push_back({&PN, ShadowPN, OriginPN});
3480}
3481
3484
3488 auto &FAM =
3491 };
3492 if (!DataFlowSanitizer(ABIListFiles, FS).runImpl(M, GetTLI))
3494
3496
3497
3498
3500 return PA;
3501}
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
Definition DataFlowSanitizer.cpp:314
const MemoryMapParams Linux_X86_64_MemoryMapParams
Definition DataFlowSanitizer.cpp:305
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
Definition DataFlowSanitizer.cpp:125
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)
Definition DataFlowSanitizer.cpp:952
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
Definition DataFlowSanitizer.cpp:123
static AtomicOrdering addReleaseOrdering(AtomicOrdering AO)
Definition DataFlowSanitizer.cpp:2652
static AtomicOrdering addAcquireOrdering(AtomicOrdering AO)
Definition DataFlowSanitizer.cpp:2362
Value * StripPointerGEPsAndCasts(Value *V)
Definition DataFlowSanitizer.cpp:2379
const MemoryMapParams Linux_AArch64_MemoryMapParams
Definition DataFlowSanitizer.cpp:297
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)
Definition DataFlowSanitizer.cpp:269
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
Definition DataFlowSanitizer.cpp:129
static const unsigned RetvalTLSSize
Definition DataFlowSanitizer.cpp:130
static bool isAMustTailRetVal(Value *RetVal)
Definition DataFlowSanitizer.cpp:2979
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, const LibcallLoweringInfo &Libcalls, 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)
Definition DataFlowSanitizer.cpp:3482
LLVM_ABI unsigned getLine() const
LLVM_ABI DILocation * get() const
Get the underlying DILocation.
iterator find(const_arg_type_t< KeyT > Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
Type * getReturnType() const
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
const BasicBlock & getEntryBlock() const
FunctionType * getFunctionType() const
Returns the FunctionType for me.
void removeFnAttrs(const AttributeMask &Attrs)
AttributeList getAttributes() const
Return the attribute list for this Function.
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
void removeRetAttrs(const AttributeMask &Attrs)
removes the attributes from the return value list of attributes.
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Value * getPointerOperand()
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
LLVM_ABI const GlobalObject * getAliaseeObject() const
static bool isExternalWeakLinkage(LinkageTypes Linkage)
LinkageTypes getLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
Analysis pass providing a never-invalidated alias analysis result.
Value * CreateInsertElement(Type *VecTy, Value *NewElt, Value *Idx, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
Value * CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, const Twine &Name="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVMContext & getContext() const
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateConstInBoundsGEP2_64(Type *Ty, Value *Ptr, uint64_t Idx0, uint64_t Idx1, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LLVM_ABI GlobalVariable * CreateGlobalString(StringRef Str, const Twine &Name="", unsigned AddressSpace=0, Module *M=nullptr, bool AddNull=true)
Make a new global variable with initializer type i8*.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Base class for instruction visitors.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
bool isTerminator() const
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is an important class for using LLVM in a threaded context.
void setAlignment(Align Align)
Value * getPointerOperand()
void setOrdering(AtomicOrdering Ordering)
Sets the ordering constraint of this load instruction.
AtomicOrdering getOrdering() const
Returns the ordering constraint of this load instruction.
Align getAlign() const
Return the alignment of the access that is being performed.
static MemoryEffectsBase readOnly()
A Module instance is used to store all the information related to an LLVM module.
const std::string & getModuleInlineAsm() const
Get any module-scope inline assembly blocks.
void setModuleInlineAsm(StringRef Asm)
Set the module-scope inline assembly blocks.
FunctionCallee getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
iterator_range< const_block_iterator > blocks() const
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
static SelectInst * Create(Value *C, Value *S1, Value *S2, const Twine &NameStr="", InsertPosition InsertBefore=nullptr, const Instruction *MDFrom=nullptr)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static LLVM_ABI std::unique_ptr< SpecialCaseList > createOrDie(const std::vector< std::string > &Paths, llvm::vfs::FileSystem &FS)
Parses the special case list entries from files.
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
void insert_range(Range &&R)
Class to represent struct types.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Value * getCondition() const
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
bool isVoidTy() const
Return true if this is 'void'.
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
std::pair< iterator, bool > insert(const ValueT &V)
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
const ParentTy * getParent() const
self_iterator getIterator()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
FunctionAddr VTableAddr Value
bool includes(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::includes which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - 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 - 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 - 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.