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();

406 I < IE; ++I) {

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();

414 I < IE; ++I) {

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 (F.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) {

921 Type *T = V->getType();

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;

1301 Args.push_back(F);

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);

1344 AL = AL.addFnAttribute(

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);

1353 AL = AL.addFnAttribute(

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 (F.isIntrinsic() && !DFSanRuntimeFunctions.contains(&F) &&

1552 !LibAtomicFunction(F) &&

1553 F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) {

1554 FnsToInstrument.push_back(&F);

1555 if (F.hasPersonalityFn())

1556 PersonalityFns.insert(F.getPersonalityFn()->stripPointerCasts());

1557 }

1558

1560 for (auto *C : PersonalityFns) {

1563 if (!isInstrumented(F))

1565 }

1566 }

1567

1568

1569

1571

1572

1574 if (F)

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 {

1651 User *Usr = U.getUser();

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 (F.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()) {

1689 UnwrappedFnMap[&F] = &F;

1690 *FI = nullptr;

1691 }

1692 }

1693

1694 for (Function *F : FnsToInstrument) {

1695 if (F || 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() && SI.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) {

3142 Args.push_back(*I);

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() && F->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.