LLVM: lib/Transforms/Instrumentation/HWAddressSanitizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

66#include

67#include

68

69using namespace llvm;

70

71#define DEBUG_TYPE "hwasan"

72

77

79 "__hwasan_shadow_memory_dynamic_address";

80

81

83

85

87

88namespace {

90 kFixed = 0,

91 kGlobal,

92 kIfunc,

93 kTls,

94};

95}

96

99 cl::desc("Prefix for memory access callbacks"),

101

103 "hwasan-kernel-mem-intrinsic-prefix",

104 cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden,

106

108 "hwasan-instrument-with-calls",

111

113 cl::desc("instrument read instructions"),

115

120

122 "hwasan-instrument-atomics",

123 cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden,

125

127 cl::desc("instrument byval arguments"),

129

132 cl::desc("Enable recovery mode (continue-after-error)."),

134

136 cl::desc("instrument stack (allocas)"),

138

143

147 cl::desc("How many lifetime ends to handle for a single alloca."),

149

152 cl::desc("detect use after scope within function"),

154

156 "hwasan-generate-tags-with-calls",

157 cl::desc("generate new tags with runtime library calls"), cl::Hidden,

159

162

164 "hwasan-all-globals",

166 "Instrument globals, even those within user-defined sections. Warning: "

167 "This may break existing code which walks globals via linker-generated "

168 "symbols, expects certain globals to be contiguous with each other, or "

169 "makes other assumptions which are invalidated by HWASan "

170 "instrumentation."),

172

174 "hwasan-match-all-tag",

175 cl::desc("don't report bad accesses via pointers with this tag"),

177

180 cl::desc("Enable KernelHWAddressSanitizer instrumentation"),

182

183

184

185

186

189 cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"),

191

193 "hwasan-mapping-offset-dynamic",

194 cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden,

196 clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"),

197 clEnumValN(OffsetKind::kTls, "tls", "Use TLS")));

198

201 cl::desc("Use ring buffer for stack allocations"),

203

205 cl::desc("Hot percentile cutoff."));

206

209 cl::desc("Probability value in the range [0.0, 1.0] "

210 "to keep instrumentation of a function. "

211 "Note: instrumentation can be skipped randomly "

212 "OR because of the hot percentile cutoff, if "

213 "both are supplied."));

214

216 "hwasan-static-linking",

217 cl::desc("Don't use .note.hwasan.globals section to instrument globals "

218 "from loadable libraries. "

219 "Note: in static binaries, the global variables section can be "

220 "accessed directly via linker-provided "

221 "__start_hwasan_globals and __stop_hwasan_globals symbols"),

223

224STATISTIC(NumTotalFuncs, "Number of total funcs");

225STATISTIC(NumInstrumentedFuncs, "Number of instrumented funcs");

226STATISTIC(NumNoProfileSummaryFuncs, "Number of funcs without PS");

227

228

229

231

233

234

235

237

238

240};

241

243 "hwasan-record-stack-history",

244 cl::desc("Record stack frames with tagged allocations in a thread-local "

245 "ring buffer"),

247 clEnumVal(instr, "Insert instructions into the prologue for "

248 "storing into the stack ring buffer directly"),

249 clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for "

250 "storing into the stack ring buffer")),

252

255 cl::desc("instrument memory intrinsics"),

257

262

264 "hwasan-use-short-granules",

265 cl::desc("use short granules in allocas and outlined checks"), cl::Hidden,

267

269 "hwasan-instrument-personality-functions",

271

273 cl::desc("inline all checks"),

275

277 cl::desc("inline all checks"),

279

280

282 cl::desc("Use page aliasing in HWASan"),

284

285namespace {

286

289}

290

291bool shouldUsePageAliases(const Triple &TargetTriple) {

293}

294

295bool shouldInstrumentStack(const Triple &TargetTriple) {

297}

298

299bool shouldInstrumentWithCalls(const Triple &TargetTriple) {

301}

302

303bool mightUseStackSafetyAnalysis(bool DisableOptimization) {

305}

306

307bool shouldUseStackSafetyAnalysis(const Triple &TargetTriple,

308 bool DisableOptimization) {

309 return shouldInstrumentStack(TargetTriple) &&

310 mightUseStackSafetyAnalysis(DisableOptimization);

311}

312

313bool shouldDetectUseAfterScope(const Triple &TargetTriple) {

314 return ClUseAfterScope && shouldInstrumentStack(TargetTriple);

315}

316

317

318

319class HWAddressSanitizer {

320public:

321 HWAddressSanitizer(Module &M, bool CompileKernel, bool Recover,

322 const StackSafetyGlobalInfo *SSI)

323 : M(M), SSI(SSI) {

324 this->Recover = optOr(ClRecover, Recover);

325 this->CompileKernel = optOr(ClEnableKhwasan, CompileKernel);

327 : nullptr;

328

329 initializeModule();

330 }

331

333

334private:

335 struct ShadowTagCheckInfo {

337 Value *PtrLong = nullptr;

338 Value *AddrLong = nullptr;

339 Value *PtrTag = nullptr;

340 Value *MemTag = nullptr;

341 };

342

343 bool selectiveInstrumentationShouldSkip(Function &F,

345 void initializeModule();

346 void createHwasanCtorComdat();

347 void createHwasanNote();

348

349 void initializeCallbacks(Module &M);

350

352

355

356 void untagPointerOperand(Instruction *I, Value *Addr);

358

359 int64_t getAccessInfo(bool IsWrite, unsigned AccessSizeIndex);

360 ShadowTagCheckInfo insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,

361 DomTreeUpdater &DTU, LoopInfo *LI);

362 void instrumentMemAccessOutline(Value *Ptr, bool IsWrite,

363 unsigned AccessSizeIndex,

364 Instruction *InsertBefore,

365 DomTreeUpdater &DTU, LoopInfo *LI);

366 void instrumentMemAccessInline(Value *Ptr, bool IsWrite,

367 unsigned AccessSizeIndex,

368 Instruction *InsertBefore, DomTreeUpdater &DTU,

369 LoopInfo *LI);

370 bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *MI);

371 void instrumentMemIntrinsic(MemIntrinsic *MI);

372 bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,

373 LoopInfo *LI, const DataLayout &DL);

374 bool ignoreAccessWithoutRemark(Instruction *Inst, Value *Ptr);

375 bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,

377

379 OptimizationRemarkEmitter &ORE, Instruction *I,

380 const TargetLibraryInfo &TLI,

381 SmallVectorImpl &Interesting);

382

386 void instrumentStack(memtag::StackInfo &Info, Value *StackTag, Value *UARTag,

387 const DominatorTree &DT, const PostDominatorTree &PDT,

388 const LoopInfo &LI);

389 void instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);

394

397 unsigned retagMask(unsigned AllocaNo);

398

399 void emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord);

400

401 void instrumentGlobal(GlobalVariable *GV, uint8_t Tag);

402 void instrumentGlobals();

403

406

407 void instrumentPersonalityFunctions();

408

409 LLVMContext *C;

411 const StackSafetyGlobalInfo *SSI;

412 Triple TargetTriple;

413 std::unique_ptr Rng;

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430 class ShadowMapping {

432 uint64_t Offset;

433 uint8_t Scale;

434 bool WithFrameRecord;

435

436 void SetFixed(uint64_t O) {

437 Kind = OffsetKind::kFixed;

438 Offset = O;

439 }

440

441 public:

442 void init(Triple &TargetTriple, bool InstrumentWithCalls,

443 bool CompileKernel);

444 Align getObjectAlignment() const { return Align(1ULL << Scale); }

445 bool isInGlobal() const { return Kind == OffsetKind::kGlobal; }

446 bool isInIfunc() const { return Kind == OffsetKind::kIfunc; }

447 bool isInTls() const { return Kind == OffsetKind::kTls; }

448 bool isFixed() const { return Kind == OffsetKind::kFixed; }

449 uint8_t scale() const { return Scale; };

450 uint64_t offset() const {

452 return Offset;

453 };

454 bool withFrameRecord() const { return WithFrameRecord; };

455 };

456

457 ShadowMapping Mapping;

458

459 Type *VoidTy = Type::getVoidTy(M.getContext());

460 Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());

461 PointerType *PtrTy = PointerType::getUnqual(M.getContext());

462 Type *Int8Ty = Type::getInt8Ty(M.getContext());

463 Type *Int32Ty = Type::getInt32Ty(M.getContext());

464 Type *Int64Ty = Type::getInt64Ty(M.getContext());

465

466 bool CompileKernel;

467 bool Recover;

468 bool OutlinedChecks;

469 bool InlineFastPath;

470 bool UseShortGranules;

471 bool InstrumentLandingPads;

472 bool InstrumentWithCalls;

473 bool InstrumentStack;

474 bool InstrumentGlobals;

475 bool DetectUseAfterScope;

476 bool UsePageAliases;

477 bool UseMatchAllCallback;

478

479 std::optional<uint8_t> MatchAllTag;

480

481 unsigned PointerTagShift;

482 uint64_t TagMaskByte;

483

484 Function *HwasanCtorFunction;

485

487 FunctionCallee HwasanMemoryAccessCallbackSized[2];

488

489 FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;

490 FunctionCallee HwasanHandleVfork;

491

492 FunctionCallee HwasanTagMemoryFunc;

493 FunctionCallee HwasanGenerateTagFunc;

494 FunctionCallee HwasanRecordFrameRecordFunc;

495

497

498 Value *ShadowBase = nullptr;

499 Value *StackBaseTag = nullptr;

500 Value *CachedFP = nullptr;

501 GlobalValue *ThreadPtrGlobal = nullptr;

502};

503

504}

505

508

512 const Triple &TargetTriple = M.getTargetTriple();

513 if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))

515

516 HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);

519 HWASan.sanitizeFunction(F, FAM);

520

522

523

524

528

529

530

532 return PA;

533}

537 OS, MapClassName2PassName);

538 OS << '<';

539 if (Options.CompileKernel)

540 OS << "kernel;";

541 if (Options.Recover)

542 OS << "recover";

543 OS << '>';

544}

545

546void HWAddressSanitizer::createHwasanNote() {

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

579

581 auto *Start =

583 nullptr, "__start_hwasan_globals");

585 auto *Stop =

587 nullptr, "__stop_hwasan_globals");

589

590

591

593

599 Note->setSection(".note.hwasan.globals");

600 Note->setComdat(NoteComdat);

602

603

604

605 auto CreateRelPtr = [&](Constant *Ptr) {

610 };

612 {ConstantInt::get(Int32Ty, 8),

613 ConstantInt::get(Int32Ty, 8),

615 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));

617

618

619

623 Dummy->setSection("hwasan_globals");

624 Dummy->setComdat(NoteComdat);

625 Dummy->setMetadata(LLVMContext::MD_associated,

628}

629

630void HWAddressSanitizer::createHwasanCtorComdat() {

631 std::tie(HwasanCtorFunction, std::ignore) =

634 {},

635 {},

636

637

642 });

643

644

645

646

647

648

650 createHwasanNote();

651}

652

653

654

655

656void HWAddressSanitizer::initializeModule() {

658 TargetTriple = M.getTargetTriple();

659

660

661

664

665

666

667

669 UsePageAliases = shouldUsePageAliases(TargetTriple);

670 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);

671 InstrumentStack = shouldInstrumentStack(TargetTriple);

672 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);

673 PointerTagShift = IsX86_64 ? 57 : 56;

674 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;

675

676 Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);

677

678 C = &(M.getContext());

680

681 HwasanCtorFunction = nullptr;

682

683

684

685

686 bool NewRuntime =

688

690 OutlinedChecks = (TargetTriple.isAArch64() || TargetTriple.isRISCV64()) &&

693

694

697

701 }

702 } else if (CompileKernel) {

703 MatchAllTag = 0xFF;

704 }

705 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();

706

707

709

710 InstrumentGlobals =

711 !CompileKernel && !UsePageAliases && optOr(ClGlobals, NewRuntime);

712

713 if (!CompileKernel) {

714 if (InstrumentGlobals)

715 instrumentGlobals();

716

717 createHwasanCtorComdat();

718

719 bool InstrumentPersonalityFunctions =

721 if (InstrumentPersonalityFunctions)

722 instrumentPersonalityFunctions();

723 }

724

726 ThreadPtrGlobal = M.getOrInsertGlobal("__hwasan_tls", IntptrTy, [&] {

727 auto *GV = new GlobalVariable(M, IntptrTy, false,

729 "__hwasan_tls", nullptr,

732 return GV;

733 });

734 }

735}

736

737void HWAddressSanitizer::initializeCallbacks(Module &M) {

739 const std::string MatchAllStr = UseMatchAllCallback ? "_match_all" : "";

740 FunctionType *HwasanMemoryAccessCallbackSizedFnTy,

741 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,

742 *HwasanMemsetFnTy;

743 if (UseMatchAllCallback) {

744 HwasanMemoryAccessCallbackSizedFnTy =

746 HwasanMemoryAccessCallbackFnTy =

748 HwasanMemTransferFnTy =

749 FunctionType::get(PtrTy, {PtrTy, PtrTy, IntptrTy, Int8Ty}, false);

750 HwasanMemsetFnTy =

752 } else {

753 HwasanMemoryAccessCallbackSizedFnTy =

755 HwasanMemoryAccessCallbackFnTy =

757 HwasanMemTransferFnTy =

759 HwasanMemsetFnTy =

761 }

762

763 for (size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {

764 const std::string TypeStr = AccessIsWrite ? "store" : "load";

765 const std::string EndingStr = Recover ? "_noabort" : "";

766

767 HwasanMemoryAccessCallbackSized[AccessIsWrite] = M.getOrInsertFunction(

769 HwasanMemoryAccessCallbackSizedFnTy);

770

772 AccessSizeIndex++) {

773 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =

775 itostr(1ULL << AccessSizeIndex) +

776 MatchAllStr + EndingStr,

777 HwasanMemoryAccessCallbackFnTy);

778 }

779 }

780

781 const std::string MemIntrinCallbackPrefix =

783 ? std::string("")

785

786 HwasanMemmove = M.getOrInsertFunction(

787 MemIntrinCallbackPrefix + "memmove" + MatchAllStr, HwasanMemTransferFnTy);

788 HwasanMemcpy = M.getOrInsertFunction(

789 MemIntrinCallbackPrefix + "memcpy" + MatchAllStr, HwasanMemTransferFnTy);

790 HwasanMemset = M.getOrInsertFunction(

791 MemIntrinCallbackPrefix + "memset" + MatchAllStr, HwasanMemsetFnTy);

792

793 HwasanTagMemoryFunc = M.getOrInsertFunction("__hwasan_tag_memory", VoidTy,

794 PtrTy, Int8Ty, IntptrTy);

795 HwasanGenerateTagFunc =

796 M.getOrInsertFunction("__hwasan_generate_tag", Int8Ty);

797

798 HwasanRecordFrameRecordFunc =

799 M.getOrInsertFunction("__hwasan_add_frame_record", VoidTy, Int64Ty);

800

801 ShadowGlobal =

802 M.getOrInsertGlobal("__hwasan_shadow", ArrayType::get(Int8Ty, 0));

803

804 HwasanHandleVfork =

805 M.getOrInsertFunction("__hwasan_handle_vfork", VoidTy, IntptrTy);

806}

807

809

810

811

812

816 false);

817 return IRB.CreateCall(Asm, {Val}, ".hwasan.shadow");

818}

819

820Value *HWAddressSanitizer::getDynamicShadowIfunc(IRBuilder<> &IRB) {

821 return getOpaqueNoopCast(IRB, ShadowGlobal);

822}

823

824Value *HWAddressSanitizer::getShadowNonTls(IRBuilder<> &IRB) {

825 if (Mapping.isFixed()) {

826 return getOpaqueNoopCast(

828 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));

829 }

830

831 if (Mapping.isInIfunc())

832 return getDynamicShadowIfunc(IRB);

833

834 Value *GlobalDynamicAddress =

837 return IRB.CreateLoad(PtrTy, GlobalDynamicAddress);

838}

839

840bool HWAddressSanitizer::ignoreAccessWithoutRemark(Instruction *Inst,

842

843

846 return true;

847

848

849

850

851

853 return true;

854

856 if (!InstrumentStack)

857 return true;

859 return true;

860 }

861

863 if (!InstrumentGlobals)

864 return true;

865

866 }

867

868 return false;

869}

870

873 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);

874 if (Ignored) {

877 } else {

878 ORE.emit([&]() {

880 });

881 }

882 return Ignored;

883}

884

885void HWAddressSanitizer::getInterestingMemoryOperands(

889

890 if (I->hasMetadata(LLVMContext::MD_nosanitize))

891 return;

892

893

894 if (ShadowBase == I)

895 return;

896

898 if (ClInstrumentReads || ignoreAccess(ORE, I, LI->getPointerOperand()))

899 return;

900 Interesting.emplace_back(I, LI->getPointerOperandIndex(), false,

901 LI->getType(), LI->getAlign());

904 return;

905 Interesting.emplace_back(I, SI->getPointerOperandIndex(), true,

906 SI->getValueOperand()->getType(), SI->getAlign());

909 return;

910 Interesting.emplace_back(I, RMW->getPointerOperandIndex(), true,

911 RMW->getValOperand()->getType(), std::nullopt);

914 return;

915 Interesting.emplace_back(I, XCHG->getPointerOperandIndex(), true,

916 XCHG->getCompareOperand()->getType(),

917 std::nullopt);

919 for (unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {

921 ignoreAccess(ORE, I, CI->getArgOperand(ArgNo)))

922 continue;

923 Type *Ty = CI->getParamByValType(ArgNo);

925 }

927 }

928}

929

932 return LI->getPointerOperandIndex();

934 return SI->getPointerOperandIndex();

936 return RMW->getPointerOperandIndex();

938 return XCHG->getPointerOperandIndex();

940 return -1;

941}

942

948

949void HWAddressSanitizer::untagPointerOperand(Instruction *I, Value *Addr) {

952 return;

953

956 Value *UntaggedPtr =

959}

960

962

964 if (Mapping.isFixed() && Mapping.offset() == 0)

966

968}

969

970int64_t HWAddressSanitizer::getAccessInfo(bool IsWrite,

971 unsigned AccessSizeIndex) {

978}

979

980HWAddressSanitizer::ShadowTagCheckInfo

981HWAddressSanitizer::insertShadowTagCheck(Value *Ptr, Instruction *InsertBefore,

983 ShadowTagCheckInfo R;

984

986

988 R.PtrTag =

990 R.AddrLong = untagPointer(IRB, R.PtrLong);

991 Value *Shadow = memToShadow(R.AddrLong, IRB);

992 R.MemTag = IRB.CreateLoad(Int8Ty, Shadow);

994

995 if (MatchAllTag.has_value()) {

997 R.PtrTag, ConstantInt::get(R.PtrTag->getType(), *MatchAllTag));

998 TagMismatch = IRB.CreateAnd(TagMismatch, TagNotIgnored);

999 }

1000

1002 TagMismatch, InsertBefore, false,

1004

1005 return R;

1006}

1007

1008void HWAddressSanitizer::instrumentMemAccessOutline(Value *Ptr, bool IsWrite,

1009 unsigned AccessSizeIndex,

1013 assert(!UsePageAliases);

1014 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);

1015

1016 if (InlineFastPath)

1017 InsertBefore =

1018 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;

1019

1021 bool UseFixedShadowIntrinsic = false;

1022

1023

1024

1025

1026

1027

1028

1029 if (TargetTriple.isAArch64() && Mapping.isFixed()) {

1030 uint16_t OffsetShifted = Mapping.offset() >> 32;

1031 UseFixedShadowIntrinsic =

1032 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();

1033 }

1034

1035 if (UseFixedShadowIntrinsic) {

1037 UseShortGranules

1038 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow

1039 : Intrinsic::hwasan_check_memaccess_fixedshadow,

1040 {Ptr, ConstantInt::get(Int32Ty, AccessInfo),

1041 ConstantInt::get(Int64Ty, Mapping.offset())});

1042 } else {

1044 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules

1045 : Intrinsic::hwasan_check_memaccess,

1046 {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});

1047 }

1048}

1049

1050void HWAddressSanitizer::instrumentMemAccessInline(Value *Ptr, bool IsWrite,

1051 unsigned AccessSizeIndex,

1055 assert(!UsePageAliases);

1056 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);

1057

1058 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);

1059

1061 Value *OutOfShortGranuleTagRange =

1062 IRB.CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));

1064 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,

1066

1070 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));

1074 LI, CheckFailTerm->getParent());

1075

1077 Value *InlineTagAddr = IRB.CreateOr(TCI.AddrLong, 15);

1078 InlineTagAddr = IRB.CreateIntToPtr(InlineTagAddr, PtrTy);

1079 Value *InlineTag = IRB.CreateLoad(Int8Ty, InlineTagAddr);

1080 Value *InlineTagMismatch = IRB.CreateICmpNE(TCI.PtrTag, InlineTag);

1083 LI, CheckFailTerm->getParent());

1084

1087 switch (TargetTriple.getArch()) {

1089

1092 "int3\nnopl " +

1094 "(%rax)",

1095 "{rdi}",

1096 true);

1097 break;

1100

1104 "{x0}",

1105 true);

1106 break;

1108

1111 "ebreak\naddiw x0, x11, " +

1113 "{x10}",

1114 true);

1115 break;

1116 default:

1118 }

1120 if (Recover)

1122 ->setSuccessor(0, TCI.TagMismatchTerm->getParent());

1123}

1124

1128 return (ClInstrumentWrites || ignoreAccess(ORE, MTI, MTI->getDest())) &&

1129 (ClInstrumentReads || ignoreAccess(ORE, MTI, MTI->getSource()));

1130 }

1133 return false;

1134}

1135

1136void HWAddressSanitizer::instrumentMemIntrinsic(MemIntrinsic *MI) {

1140 MI->getOperand(0), MI->getOperand(1),

1142

1143 if (UseMatchAllCallback)

1144 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));

1148 MI->getOperand(0),

1151 if (UseMatchAllCallback)

1152 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));

1154 }

1155 MI->eraseFromParent();

1156}

1157

1161 Value *Addr = O.getPtr();

1162

1163 LLVM_DEBUG(dbgs() << "Instrumenting: " << O.getInsn() << "\n");

1164

1165

1166

1167

1168

1169

1170

1173 if (Known.isZero())

1174 return false;

1175

1176 if (O.MaybeMask)

1177 return false;

1178

1180 if (O.TypeStoreSize.isScalable() && isPowerOf2_64(O.TypeStoreSize) &&

1182 (O.Alignment || *O.Alignment >= Mapping.getObjectAlignment() ||

1183 *O.Alignment >= O.TypeStoreSize / 8)) {

1185 if (InstrumentWithCalls) {

1187 if (UseMatchAllCallback)

1188 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));

1189 IRB.CreateCall(HwasanMemoryAccessCallback[O.IsWrite][AccessSizeIndex],

1190 Args);

1191 } else if (OutlinedChecks) {

1192 instrumentMemAccessOutline(Addr, O.IsWrite, AccessSizeIndex, O.getInsn(),

1193 DTU, LI);

1194 } else {

1195 instrumentMemAccessInline(Addr, O.IsWrite, AccessSizeIndex, O.getInsn(),

1196 DTU, LI);

1197 }

1198 } else {

1202 ConstantInt::get(IntptrTy, 8))};

1203 if (UseMatchAllCallback)

1204 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));

1205 IRB.CreateCall(HwasanMemoryAccessCallbackSized[O.IsWrite], Args);

1206 }

1207 untagPointerOperand(O.getInsn(), Addr);

1208

1209 return true;

1210}

1211

1213 size_t Size) {

1214 size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment());

1215 if (!UseShortGranules)

1216 Size = AlignedSize;

1217

1219 if (InstrumentWithCalls) {

1222 ConstantInt::get(IntptrTy, AlignedSize)});

1223 } else {

1224 size_t ShadowSize = Size >> Mapping.scale();

1226 Value *ShadowPtr = memToShadow(AddrLong, IRB);

1227

1228

1229

1230

1231

1232

1233 if (ShadowSize)

1235 if (Size != AlignedSize) {

1236 const uint8_t SizeRemainder = Size % Mapping.getObjectAlignment().value();

1237 IRB.CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),

1241 AlignedSize - 1));

1242 }

1243 }

1244}

1245

1246unsigned HWAddressSanitizer::retagMask(unsigned AllocaNo) {

1248 return AllocaNo & TagMaskByte;

1249

1250

1251

1252

1253

1254

1255

1256

1257

1258

1259

1260 static const unsigned FastMasks[] = {

1261 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,

1262 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,

1263 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};

1264 return FastMasks[AllocaNo % std::size(FastMasks)];

1265}

1266

1268 if (TagMaskByte == 0xFF)

1269 return OldTag;

1271 ConstantInt::get(OldTag->getType(), TagMaskByte));

1272}

1273

1274Value *HWAddressSanitizer::getNextTagWithCall(IRBuilder<> &IRB) {

1276}

1277

1278Value *HWAddressSanitizer::getStackBaseTag(IRBuilder<> &IRB) {

1280 return nullptr;

1281 if (StackBaseTag)

1282 return StackBaseTag;

1283

1284

1285

1286 Value *FramePointerLong = getCachedFP(IRB);

1287 Value *StackTag =

1288 applyTagMask(IRB, IRB.CreateXor(FramePointerLong,

1289 IRB.CreateLShr(FramePointerLong, 20)));

1290 StackTag->setName("hwasan.stack.base.tag");

1291 return StackTag;

1292}

1293

1295 unsigned AllocaNo) {

1297 return getNextTagWithCall(IRB);

1299 StackTag, ConstantInt::get(StackTag->getType(), retagMask(AllocaNo)));

1300}

1301

1303 Value *FramePointerLong = getCachedFP(IRB);

1305 applyTagMask(IRB, IRB.CreateLShr(FramePointerLong, PointerTagShift));

1306

1307 UARTag->setName("hwasan.uar.tag");

1308 return UARTag;

1309}

1310

1311

1314 assert(!UsePageAliases);

1315 Value *TaggedPtrLong;

1316 if (CompileKernel) {

1317

1318 Value *ShiftedTag =

1320 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));

1321 TaggedPtrLong = IRB.CreateAnd(PtrLong, ShiftedTag);

1322 } else {

1323

1325 TaggedPtrLong = IRB.CreateOr(PtrLong, ShiftedTag);

1326 }

1328}

1329

1330

1332 assert(!UsePageAliases);

1333 Value *UntaggedPtrLong;

1334 if (CompileKernel) {

1335

1336 UntaggedPtrLong =

1337 IRB.CreateOr(PtrLong, ConstantInt::get(PtrLong->getType(),

1338 TagMaskByte << PointerTagShift));

1339 } else {

1340

1341 UntaggedPtrLong = IRB.CreateAnd(

1342 PtrLong, ConstantInt::get(PtrLong->getType(),

1343 ~(TagMaskByte << PointerTagShift)));

1344 }

1345 return UntaggedPtrLong;

1346}

1347

1348Value *HWAddressSanitizer::getHwasanThreadSlotPtr(IRBuilder<> &IRB) {

1349

1350

1351 constexpr int SanitizerSlot = 6;

1354 return ThreadPtrGlobal;

1355}

1356

1358 if (!CachedFP)

1360 return CachedFP;

1361}

1362

1363Value *HWAddressSanitizer::getFrameRecordInfo(IRBuilder<> &IRB) {

1364

1366 Value *FP = getCachedFP(IRB);

1367

1368

1369

1370

1371

1372

1373

1374

1375

1376

1379}

1380

1381void HWAddressSanitizer::emitPrologue(IRBuilder<> &IRB, bool WithFrameRecord) {

1382 if (!Mapping.isInTls())

1383 ShadowBase = getShadowNonTls(IRB);

1384 else if (!WithFrameRecord && TargetTriple.isAndroid())

1385 ShadowBase = getDynamicShadowIfunc(IRB);

1386

1387 if (!WithFrameRecord && ShadowBase)

1388 return;

1389

1390 Value *SlotPtr = nullptr;

1391 Value *ThreadLong = nullptr;

1392 Value *ThreadLongMaybeUntagged = nullptr;

1393

1394 auto getThreadLongMaybeUntagged = [&]() {

1395 if (!SlotPtr)

1396 SlotPtr = getHwasanThreadSlotPtr(IRB);

1397 if (!ThreadLong)

1398 ThreadLong = IRB.CreateLoad(IntptrTy, SlotPtr);

1399

1400

1401 return TargetTriple.isAArch64() ? ThreadLong

1402 : untagPointer(IRB, ThreadLong);

1403 };

1404

1405 if (WithFrameRecord) {

1408

1409

1410 Value *FrameRecordInfo = getFrameRecordInfo(IRB);

1411 IRB.CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});

1412 break;

1413 }

1415 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();

1416

1417 StackBaseTag = IRB.CreateAShr(ThreadLong, 3);

1418

1419

1420 Value *FrameRecordInfo = getFrameRecordInfo(IRB);

1421 Value *RecordPtr =

1423 IRB.CreateStore(FrameRecordInfo, RecordPtr);

1424

1426 break;

1427 }

1428 case none: {

1430 "A stack history recording mode should've been selected.");

1431 }

1432 }

1433 }

1434

1435 if (!ShadowBase) {

1436 if (!ThreadLongMaybeUntagged)

1437 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();

1438

1439

1440

1441

1444 ThreadLongMaybeUntagged,

1446 ConstantInt::get(IntptrTy, 1), "hwasan.shadow");

1448 }

1449}

1450

1451void HWAddressSanitizer::instrumentLandingPads(

1453 for (auto *LP : LandingPadVec) {

1456 HwasanHandleVfork,

1459 }

1460}

1461

1462void HWAddressSanitizer::instrumentStack(memtag::StackInfo &SInfo,

1467

1468

1469

1470

1471

1472 unsigned int I = 0;

1473

1475 auto N = I++;

1476 auto *AI = KV.first;

1479

1480

1481 Value *Tag = getAllocaTag(IRB, StackTag, N);

1483 Value *AINoTagLong = untagPointer(IRB, AILong);

1484 Value *Replacement = tagPointer(IRB, AI->getType(), AINoTagLong, Tag);

1485 std::string Name =

1487 Replacement->setName(Name + ".hwasan");

1488

1490 size_t AlignedSize = alignTo(Size, Mapping.getObjectAlignment());

1491

1493 auto *User = U.getUser();

1495 });

1496

1498

1501

1502

1503

1504

1505 tagAlloca(IRB, AI, UARTag, AlignedSize);

1506 };

1507

1508

1509

1510

1511 bool StandardLifetime =

1515 if (DetectUseAfterScope && StandardLifetime) {

1518 tagAlloca(IRB, AI, Tag, Size);

1520 SInfo.RetVec, TagEnd)) {

1521 for (auto *End : Info.LifetimeEnd)

1522 End->eraseFromParent();

1523 }

1524 } else {

1525 tagAlloca(IRB, AI, Tag, Size);

1526 for (auto *RI : SInfo.RetVec)

1527 TagEnd(RI);

1528

1529

1530 for (auto &II : Info.LifetimeStart)

1531 II->eraseFromParent();

1532 for (auto &II : Info.LifetimeEnd)

1533 II->eraseFromParent();

1534 }

1536 }

1537}

1538

1540 bool Skip) {

1541 if (Skip) {

1542 ORE.emit([&]() {

1544 << "Skipped: F=" << ore::NV("Function", &F);

1545 });

1546 } else {

1547 ORE.emit([&]() {

1549 << "Sanitized: F=" << ore::NV("Function", &F);

1550 });

1551 }

1552}

1553

1554bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(

1556 auto SkipHot = [&]() {

1558 return false;

1562 if (!PSI || !PSI->hasProfileSummary()) {

1563 ++NumNoProfileSummaryFuncs;

1564 return false;

1565 }

1566 return PSI->isFunctionHotInCallGraphNthPercentile(

1568 };

1569

1570 auto SkipRandom = [&]() {

1572 return false;

1574 return D(*Rng);

1575 };

1576

1577 bool Skip = SkipRandom() || SkipHot();

1579 return Skip;

1580}

1581

1582void HWAddressSanitizer::sanitizeFunction(Function &F,

1584 if (&F == HwasanCtorFunction)

1585 return;

1586

1587

1588 if (F.hasFnAttribute(Attribute::Naked))

1589 return;

1590

1591 if (F.hasFnAttribute(Attribute::SanitizeHWAddress))

1592 return;

1593

1594 if (F.empty())

1595 return;

1596

1597 if (F.isPresplitCoroutine())

1598 return;

1599

1600 NumTotalFuncs++;

1601

1604

1605 if (selectiveInstrumentationShouldSkip(F, FAM))

1606 return;

1607

1608 NumInstrumentedFuncs++;

1609

1610 LLVM_DEBUG(dbgs() << "Function: " << F.getName() << "\n");

1611

1616

1619 if (InstrumentStack) {

1620 SIB.visit(ORE, Inst);

1621 }

1622

1625

1627

1629 if (!ignoreMemIntrinsic(ORE, MI))

1631 }

1632

1634

1635 initializeCallbacks(*F.getParent());

1636

1637 if (!LandingPadVec.empty())

1638 instrumentLandingPads(LandingPadVec);

1639

1642

1643

1644 F.setPersonalityFn(nullptr);

1645 }

1646

1648 IntrinToInstrument.empty())

1649 return;

1650

1651 assert(!ShadowBase);

1652

1654 IRBuilder<> EntryIRB(&F.getEntryBlock(), InsertPt);

1655 emitPrologue(EntryIRB,

1657 Mapping.withFrameRecord() &&

1659

1664 Value *StackTag = getStackBaseTag(EntryIRB);

1665 Value *UARTag = getUARTag(EntryIRB);

1666 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);

1667 }

1668

1669

1670

1671

1672 if (EntryIRB.GetInsertBlock() != &F.getEntryBlock()) {

1673 InsertPt = F.getEntryBlock().begin();

1678 I.moveBefore(F.getEntryBlock(), InsertPt);

1679 }

1680 }

1681

1685 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);

1687 for (auto &Operand : OperandsToInstrument)

1688 instrumentMemAccess(Operand, DTU, LI, DL);

1690

1692 for (auto *Inst : IntrinToInstrument)

1693 instrumentMemIntrinsic(Inst);

1694 }

1695

1696 ShadowBase = nullptr;

1697 StackBaseTag = nullptr;

1698 CachedFP = nullptr;

1699}

1700

1701void HWAddressSanitizer::instrumentGlobal(GlobalVariable *GV, uint8_t Tag) {

1702 assert(!UsePageAliases);

1704 uint64_t SizeInBytes =

1705 M.getDataLayout().getTypeAllocSize(Initializer->getType());

1706 uint64_t NewSize = alignTo(SizeInBytes, Mapping.getObjectAlignment());

1707 if (SizeInBytes != NewSize) {

1708

1709

1710 std::vector<uint8_t> Init(NewSize - SizeInBytes, 0);

1714 }

1715

1718 GV->getName() + ".hwasan");

1719 NewGV->copyAttributesFrom(GV);

1721 NewGV->copyMetadata(GV, 0);

1722 NewGV->setAlignment(

1723 std::max(GV->getAlign().valueOrOne(), Mapping.getObjectAlignment()));

1724

1725

1726

1727

1728

1729

1730

1731

1732

1733

1735

1736

1737

1738

1739

1740

1742 const uint64_t MaxDescriptorSize = 0xfffff0;

1743 for (uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;

1744 DescriptorPos += MaxDescriptorSize) {

1745 auto *Descriptor =

1747 nullptr, GV->getName() + ".hwasan.descriptor");

1753 ConstantInt::get(Int64Ty, DescriptorPos)),

1755 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);

1756 auto *SizeAndTag = ConstantInt::get(Int32Ty, Size | (uint32_t(Tag) << 24));

1757 Descriptor->setComdat(NewGV->getComdat());

1759 Descriptor->setSection("hwasan_globals");

1760 Descriptor->setMetadata(LLVMContext::MD_associated,

1763 }

1764

1768 ConstantInt::get(Int64Ty, uint64_t(Tag) << PointerTagShift)),

1773 Alias->takeName(GV);

1776}

1777

1778void HWAddressSanitizer::instrumentGlobals() {

1779 std::vector<GlobalVariable *> Globals;

1782 continue;

1783

1786 continue;

1787

1788

1790 continue;

1791

1793

1794 if (GV.getSection() == "llvm.metadata")

1795 continue;

1796 } else {

1797

1798

1799

1801 continue;

1802 }

1803

1804 Globals.push_back(&GV);

1805 }

1806

1807 MD5 Hasher;

1808 Hasher.update(M.getSourceFileName());

1810 Hasher.final(Hash);

1811 uint8_t Tag = Hash[0];

1812

1813 assert(TagMaskByte >= 16);

1814

1816

1817

1818

1820 Tag = 16;

1821 instrumentGlobal(GV, Tag++);

1822 }

1823}

1824

1825void HWAddressSanitizer::instrumentPersonalityFunctions() {

1826

1827

1828

1829

1830

1831

1834 if (F.isDeclaration() || F.hasFnAttribute(Attribute::SanitizeHWAddress))

1835 continue;

1836

1837 if (F.hasPersonalityFn()) {

1838 PersonalityFns[F.getPersonalityFn()->stripPointerCasts()].push_back(&F);

1839 } else if (F.hasFnAttribute(Attribute::NoUnwind)) {

1840 PersonalityFns[nullptr].push_back(&F);

1841 }

1842 }

1843

1844 if (PersonalityFns.empty())

1845 return;

1846

1847 FunctionCallee HwasanPersonalityWrapper = M.getOrInsertFunction(

1849 PtrTy, PtrTy, PtrTy, PtrTy);

1850 FunctionCallee UnwindGetGR = M.getOrInsertFunction("_Unwind_GetGR", VoidTy);

1851 FunctionCallee UnwindGetCFA = M.getOrInsertFunction("_Unwind_GetCFA", VoidTy);

1852

1853 for (auto &P : PersonalityFns) {

1855 if (P.first)

1856 ThunkName += ("." + P.first->getName()).str();

1864 ThunkName, &M);

1865

1867 return F->hasFnAttribute("branch-target-enforcement");

1868 })) {

1869 ThunkFn->addFnAttr("branch-target-enforcement");

1870 }

1871 if (!IsLocal) {

1873 ThunkFn->setComdat(M.getOrInsertComdat(ThunkName));

1874 }

1875

1879 HwasanPersonalityWrapper,

1880 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),

1881 ThunkFn->getArg(3), ThunkFn->getArg(4),

1886

1888 F->setPersonalityFn(ThunkFn);

1889 }

1890}

1891

1892void HWAddressSanitizer::ShadowMapping::init(Triple &TargetTriple,

1893 bool InstrumentWithCalls,

1894 bool CompileKernel) {

1895

1897 Kind = OffsetKind::kTls;

1898 WithFrameRecord = true;

1899

1900

1902

1903

1904 SetFixed(0);

1905 } else if (CompileKernel || InstrumentWithCalls) {

1906 SetFixed(0);

1907 WithFrameRecord = false;

1908 }

1909

1910 WithFrameRecord = optOr(ClFrameRecords, WithFrameRecord);

1911

1912

1918 }

1919}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::desc("Use Stack Safety analysis results"))

static cl::opt< size_t > ClMaxLifetimes("stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional)

static cl::opt< StackTaggingRecordStackHistoryMode > ClRecordStackHistory("stack-tagging-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer")), cl::Hidden, cl::init(none))

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static const uint64_t kDefaultShadowScale

static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))

static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClInstrumentByval("asan-instrument-byval", cl::desc("instrument byval call arguments"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClUseAfterScope("asan-use-after-scope", cl::desc("Check stack-use-after-scope"), cl::Hidden, cl::init(false))

static const size_t kNumberOfAccessSizes

static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("asan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))

static cl::opt< uint64_t > ClMappingOffset("asan-mapping-offset", cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), cl::Hidden, cl::init(0))

Expand Atomic instructions

This file contains the simple types necessary to represent the attributes associated with functions a...

static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D)

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

Analysis containing CSE Info

#define clEnumValN(ENUMVAL, FLAGNAME, DESC)

#define clEnumVal(ENUMVAL, DESC)

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file contains constants used for implementing Dwarf debug support.

This is the interface for a simple mod/ref and alias analysis over globals.

static size_t TypeSizeToSizeIndex(uint32_t TypeSize)

Definition HWAddressSanitizer.cpp:943

static cl::opt< bool > ClInstrumentWrites("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))

static cl::opt< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden)

static cl::opt< RecordStackHistoryMode > ClRecordStackHistory("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr))

const char kHwasanModuleCtorName[]

Definition HWAddressSanitizer.cpp:73

static cl::opt< bool > ClFrameRecords("hwasan-with-frame-record", cl::desc("Use ring buffer for stack allocations"), cl::Hidden)

static cl::opt< int > ClMatchAllTag("hwasan-match-all-tag", cl::desc("don't report bad accesses via pointers with this tag"), cl::Hidden, cl::init(-1))

static cl::opt< bool > ClUseAfterScope("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(true))

const char kHwasanNoteName[]

Definition HWAddressSanitizer.cpp:74

static const unsigned kShadowBaseAlignment

Definition HWAddressSanitizer.cpp:86

static cl::opt< bool > ClGenerateTagsWithCalls("hwasan-generate-tags-with-calls", cl::desc("generate new tags with runtime library calls"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClInstrumentReads("hwasan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))

static cl::opt< float > ClRandomKeepRate("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function. " "Note: instrumentation can be skipped randomly " "OR because of the hot percentile cutoff, if " "both are supplied."))

static cl::opt< bool > ClInstrumentWithCalls("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional)

static cl::opt< bool > ClInstrumentAtomics("hwasan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClInstrumentStack("hwasan-instrument-stack", cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true))

static cl::opt< OffsetKind > ClMappingOffsetDynamic("hwasan-mapping-offset-dynamic", cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden, cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS")))

static cl::opt< bool > ClRecover("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))

static cl::opt< bool > ClEnableKhwasan("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClUsePageAliases("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false))

static cl::opt< std::string > ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_"))

static cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))

static const size_t kNumberOfAccessSizes

Definition HWAddressSanitizer.cpp:82

static cl::opt< bool > ClGlobals("hwasan-globals", cl::desc("Instrument globals"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("hwasan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClInstrumentByval("hwasan-instrument-byval", cl::desc("instrument byval arguments"), cl::Hidden, cl::init(true))

static cl::opt< bool > ClUseShortGranules("hwasan-use-short-granules", cl::desc("use short granules in allocas and outlined checks"), cl::Hidden, cl::init(false))

const char kHwasanShadowMemoryDynamicAddress[]

Definition HWAddressSanitizer.cpp:78

static unsigned getPointerOperandIndex(Instruction *I)

Definition HWAddressSanitizer.cpp:930

#define DEBUG_TYPE

Definition HWAddressSanitizer.cpp:71

static cl::opt< bool > ClInlineFastPathChecks("hwasan-inline-fast-path-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))

static cl::opt< bool > ClInstrumentPersonalityFunctions("hwasan-instrument-personality-functions", cl::desc("instrument personality functions"), cl::Hidden)

const char kHwasanInitName[]

Definition HWAddressSanitizer.cpp:75

static cl::opt< bool > ClAllGlobals("hwasan-all-globals", cl::desc("Instrument globals, even those within user-defined sections. Warning: " "This may break existing code which walks globals via linker-generated " "symbols, expects certain globals to be contiguous with each other, or " "makes other assumptions which are invalidated by HWASan " "instrumentation."), cl::Hidden, cl::init(false))

RecordStackHistoryMode

Definition HWAddressSanitizer.cpp:230

@ libcall

Definition HWAddressSanitizer.cpp:239

static cl::opt< bool > ClInstrumentLandingPads("hwasan-instrument-landing-pads", cl::desc("instrument landing pads"), cl::Hidden, cl::init(false))

static cl::opt< size_t > ClMaxLifetimes("hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional)

const char kHwasanPersonalityThunkName[]

Definition HWAddressSanitizer.cpp:76

static cl::opt< bool > ClStaticLinking("hwasan-static-linking", cl::desc("Don't use .note.hwasan.globals section to instrument globals " "from loadable libraries. " "Note: in static binaries, the global variables section can be " "accessed directly via linker-provided " "__start_hwasan_globals and __stop_hwasan_globals symbols"), cl::Hidden, cl::init(false))

static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)

Definition HWAddressSanitizer.cpp:1539

static cl::opt< int > ClHotPercentileCutoff("hwasan-percentile-cutoff-hot", cl::desc("Hot percentile cutoff."))

Module.h This file contains the declarations for the Module class.

Machine Check Debug Module

This file implements a map that provides insertion order iteration.

uint64_t IntrinsicInst * II

FunctionAnalysisManager FAM

ModuleAnalysisManager MAM

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

an instruction to allocate memory on the stack

PointerType * getType() const

Overload to return most specific pointer type.

const Value * getArraySize() const

Get the number of elements allocated.

PassT::Result * getCachedResult(IRUnitT &IR) const

Get the cached result of an analysis pass for a given IR unit.

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)

This static method is the primary way to construct an ArrayType.

An instruction that atomically checks whether a specified value is in a memory location,...

an instruction that atomically reads a memory location, combines it with another value,...

const Function * getParent() const

Return the enclosing method, or null if none.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

InstListType::iterator iterator

Instruction iterators...

Analysis pass which computes BlockFrequencyInfo.

This class represents a function call, abstracting a target machine's calling convention.

void setTailCall(bool IsTc=true)

static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)

get() constructor - Return a constant with array type with an element count and element type matching...

static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static LLVM_ABI Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)

static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static LLVM_ABI Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)

static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)

static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)

Return an anonymous struct that has the specified elements.

This is an important base class in LLVM.

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

A parsed version of the target data layout string in and methods for querying it.

Analysis pass which computes a DominatorTree.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

Class to represent function types.

static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)

This static method is the primary way of constructing a FunctionType.

static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)

void flush()

Apply all pending updates to available trees and flush all BasicBlocks awaiting deletion.

static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)

If a parent module is specified, the alias is automatically inserted into the end of the specified mo...

StringRef getSection() const

Get the custom section of this global if it has one.

LLVM_ABI void setComdat(Comdat *C)

bool hasSection() const

Check if this global has a custom object file section.

LLVM_ABI const SanitizerMetadata & getSanitizerMetadata() const

bool isThreadLocal() const

If the value is "Thread Local", its value isn't shared by the threads.

VisibilityTypes getVisibility() const

LinkageTypes getLinkage() const

bool isDeclarationForLinker() const

bool hasSanitizerMetadata() const

unsigned getAddressSpace() const

Module * getParent()

Get the module that this global value is contained inside of...

PointerType * getType() const

Global values are always pointers.

@ HiddenVisibility

The GV is hidden.

bool hasCommonLinkage() const

@ PrivateLinkage

Like Internal, but omit from symbol table.

@ InternalLinkage

Rename collisions when linking (static functions).

@ ExternalLinkage

Externally visible function.

@ LinkOnceODRLinkage

Same, but only replaced by something equivalent.

Type * getValueType() const

const Constant * getInitializer() const

getInitializer - Return the initializer for this global variable.

MaybeAlign getAlign() const

Returns the alignment of the given variable.

bool isConstant() const

If the value is a global constant, its value is immutable throughout the runtime execution of the pro...

LLVM_ABI void eraseFromParent()

eraseFromParent - This method unlinks 'this' from the containing module and deletes it.

Analysis pass providing a never-invalidated alias analysis result.

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)

Definition HWAddressSanitizer.cpp:506

LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)

Definition HWAddressSanitizer.cpp:534

Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")

Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")

Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")

Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

IntegerType * getInt32Ty()

Fetch the type representing a 32-bit integer.

Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())

ReturnInst * CreateRet(Value *V)

Create a 'ret ' instruction.

BasicBlock * GetInsertBlock() const

Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")

LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with Args, mangled using Types.

Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")

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)

CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())

Create and insert a memset to the specified pointer and the specified value.

Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)

Value * CreateAnd(Value *LHS, Value *RHS, 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)

PointerType * getPtrTy(unsigned AddrSpace=0)

Fetch the type representing a pointer.

LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)

Create an expression which evaluates to the number of units in Size at runtime.

Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")

void SetInsertPoint(BasicBlock *TheBB)

This specifies that created instructions should be appended to the end of the specified block.

Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)

Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)

InlineAsm::get - Return the specified uniqued inline asm string.

LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)

Update the specified successor to point at the provided block.

A wrapper class for inspecting calls to intrinsic functions.

An instruction for reading from memory.

Analysis pass that exposes the LoopInfo for a function.

LLVM_ABI void update(ArrayRef< uint8_t > Data)

Updates the hash for the byte stream provided.

LLVM_ABI void final(MD5Result &Result)

Finishes off the hash and puts the result in result.

LLVM_ABI MDNode * createUnlikelyBranchWeights()

Return metadata containing two branch weights, with significant bias towards false destination.

static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)

This class implements a map that also provides access to all stored values in a deterministic order.

This is the common base class for memset/memcpy/memmove.

This class wraps the llvm.memcpy/memmove intrinsics.

A Module instance is used to store all the information related to an LLVM module.

GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)

Look up the specified global in the module symbol table.

Analysis pass which computes a PostDominatorTree.

PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...

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.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

An analysis pass based on the new PM to deliver ProfileSummaryInfo.

Analysis providing profile information.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

This pass performs the global (interprocedural) stack safety analysis (new pass manager).

bool stackAccessIsSafe(const Instruction &I) const

An instruction for storing to memory.

StringRef - Represent a constant reference to a string, i.e.

std::string str() const

str - Get the contents as an std::string.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

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.

Analysis pass providing the TargetLibraryInfo.

Provides information about what library functions are available for the current target.

Triple - Helper class for working with autoconf configuration names.

bool isAndroidVersionLT(unsigned Major) const

bool isAndroid() const

Tests whether the target is Android.

ArchType getArch() const

Get the parsed architecture type of this triple.

bool isRISCV64() const

Tests whether the target is 64-bit RISC-V.

bool isAArch64() const

Tests whether the target is AArch64 (little and big endian).

bool isOSBinFormatELF() const

Tests whether the OS uses the ELF binary format.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM_ABI unsigned getPointerAddressSpace() const

Get the address space of this pointer or pointer vector type.

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

A Use represents the edge between a Value definition and its users.

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 void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)

Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...

LLVM_ABI bool isSwiftError() const

Return true if this value is a swifterror value.

LLVM_ABI StringRef getName() const

Return a constant reference to the value's name.

int getNumOccurrences() const

An efficient, type-erasing, non-owning reference to a callable.

const ParentTy * getParent() const

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

This class implements an extremely fast bulk output stream that can only output to a stream.

#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.

void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)

Get all the memory operands from the instruction that needs to be instrumented.

@ C

The default llvm calling convention, compatible with C.

ValuesClass values(OptsTy... Options)

Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...

initializer< Ty > init(const Ty &Val)

Value * getFP(IRBuilder<> &IRB)

bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)

bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)

uint64_t getAllocaSizeInBytes(const AllocaInst &AI)

Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)

Value * readRegister(IRBuilder<> &IRB, StringRef Name)

Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc)

void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)

void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)

Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)

DiagnosticInfoOptimizationBase::Argument NV

NodeAddr< NodeBase * > Node

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)

Returns unique alloca where the value comes from, or nullptr.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty

OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy

Provide the ModuleAnalysisManager to Function proxy.

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.

constexpr bool isPowerOf2_64(uint64_t Value)

Return true if the argument is a power of two > 0 (64 bit edition.)

int countr_zero(T Val)

Count number of 0's from the least significant bit to the most stopping at the first 1.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)

Creates sanitizer constructor function lazily.

LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)

Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)

Adds global values to the llvm.compiler.used list.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem)

Remove memory attributes that are incompatible with the instrumentation added by AddressSanitizer and...

LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)

Append F to the list of global ctors of module M with the given Priority.

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

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 ...

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)

This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....

LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)

Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...

LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)

Check if module has flag attached, if not add the flag.

std::string itostr(int64_t X)

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

This struct is a compact representation of a valid (non-zero power of two) alignment.

Align valueOrOne() const

For convenience, returns a valid alignment or 1 if undefined.

A CRTP mix-in to automatically provide informational APIs needed for passes.

MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument

SmallVector< Instruction *, 8 > RetVec