72#define DEBUG_TYPE "hwasan"
80 "__hwasan_shadow_memory_dynamic_address";
87 std::numeric_limits<uint64_t>::max();
93 cl::desc(
"Prefix for memory access callbacks"),
97 "hwasan-kernel-mem-intrinsic-prefix",
102 "hwasan-instrument-with-calls",
107 cl::desc(
"instrument read instructions"),
116 "hwasan-instrument-atomics",
121 cl::desc(
"instrument byval arguments"),
126 cl::desc(
"Enable recovery mode (continue-after-error)."),
130 cl::desc(
"instrument stack (allocas)"),
141 cl::desc(
"How many lifetime ends to handle for a single alloca."),
146 cl::desc(
"detect use after scope within function"),
150 "hwasan-generate-tags-with-calls",
158 "hwasan-match-all-tag",
159 cl::desc(
"don't report bad accesses via pointers with this tag"),
164 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
173 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
178 cl::desc(
"Access dynamic shadow through an ifunc global on "
179 "platforms that support this"),
184 cl::desc(
"Access dynamic shadow through an thread-local pointer on "
185 "platforms that support this"),
189 cl::desc(
"Hot percentile cuttoff."));
193 cl::desc(
"Probability value in the range [0.0, 1.0] "
194 "to keep instrumentation of a function."));
197STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
198STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
215 "hwasan-record-stack-history",
216 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
220 "storing into the stack ring buffer directly"),
222 "storing into the stack ring buffer")),
227 cl::desc(
"instrument memory intrinsics"),
236 "hwasan-use-short-granules",
241 "hwasan-instrument-personality-functions",
254 cl::desc(
"Use page aliasing in HWASan"),
263bool shouldUsePageAliases(
const Triple &TargetTriple) {
267bool shouldInstrumentStack(
const Triple &TargetTriple) {
271bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
275bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
279bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
280 bool DisableOptimization) {
281 return shouldInstrumentStack(TargetTriple) &&
282 mightUseStackSafetyAnalysis(DisableOptimization);
285bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
291class HWAddressSanitizer {
293 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
296 this->Recover = optOr(
ClRecover, Recover);
307 struct ShadowTagCheckInfo {
309 Value *PtrLong =
nullptr;
310 Value *AddrLong =
nullptr;
311 Value *PtrTag =
nullptr;
312 Value *MemTag =
nullptr;
315 bool selectiveInstrumentationShouldSkip(
Function &
F,
317 void initializeModule();
318 void createHwasanCtorComdat();
320 void initializeCallbacks(
Module &M);
330 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
333 void instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
334 unsigned AccessSizeIndex,
337 void instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
338 unsigned AccessSizeIndex,
368 unsigned retagMask(
unsigned AllocaNo);
370 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
373 void instrumentGlobals();
378 void instrumentPersonalityFunctions();
384 std::unique_ptr<RandomNumberGenerator> Rng;
397 struct ShadowMapping {
402 bool WithFrameRecord;
404 void init(
Triple &TargetTriple,
bool InstrumentWithCalls);
405 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
408 ShadowMapping Mapping;
411 Type *IntptrTy =
M.getDataLayout().getIntPtrType(
M.getContext());
412 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
421 bool UseShortGranules;
422 bool InstrumentLandingPads;
423 bool InstrumentWithCalls;
424 bool InstrumentStack;
425 bool InstrumentGlobals;
426 bool DetectUseAfterScope;
428 bool UseMatchAllCallback;
430 std::optional<uint8_t> MatchAllTag;
432 unsigned PointerTagShift;
449 Value *ShadowBase =
nullptr;
450 Value *StackBaseTag =
nullptr;
451 Value *CachedFP =
nullptr;
470 HWASan.sanitizeFunction(
F,
FAM);
488 OS, MapClassName2PassName);
497void HWAddressSanitizer::createHwasanCtorComdat() {
498 std::tie(HwasanCtorFunction, std::ignore) =
547 nullptr,
"__start_hwasan_globals");
551 nullptr,
"__stop_hwasan_globals");
563 Note->setSection(
".note.hwasan.globals");
564 Note->setComdat(NoteComdat);
576 {ConstantInt::get(Int32Ty, 8),
577 ConstantInt::get(Int32Ty, 8),
579 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
587 Dummy->setSection(
"hwasan_globals");
588 Dummy->setComdat(NoteComdat);
589 Dummy->setMetadata(LLVMContext::MD_associated,
597void HWAddressSanitizer::initializeModule() {
599 TargetTriple =
Triple(
M.getTargetTriple());
605 UsePageAliases = shouldUsePageAliases(TargetTriple);
606 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
607 InstrumentStack = shouldInstrumentStack(TargetTriple);
608 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
609 PointerTagShift = IsX86_64 ? 57 : 56;
610 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
612 Mapping.init(TargetTriple, InstrumentWithCalls);
614 C = &(
M.getContext());
617 HwasanCtorFunction =
nullptr;
638 }
else if (CompileKernel) {
641 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
647 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
649 if (!CompileKernel) {
650 createHwasanCtorComdat();
652 if (InstrumentGlobals)
655 bool InstrumentPersonalityFunctions =
657 if (InstrumentPersonalityFunctions)
658 instrumentPersonalityFunctions();
662 Constant *
C =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
665 "__hwasan_tls",
nullptr,
670 ThreadPtrGlobal = cast<GlobalVariable>(
C);
674void HWAddressSanitizer::initializeCallbacks(
Module &M) {
676 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
678 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
680 if (UseMatchAllCallback) {
681 HwasanMemoryAccessCallbackSizedFnTy =
683 HwasanMemoryAccessCallbackFnTy =
685 HwasanMemTransferFnTy =
690 HwasanMemoryAccessCallbackSizedFnTy =
692 HwasanMemoryAccessCallbackFnTy =
694 HwasanMemTransferFnTy =
700 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
701 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
702 const std::string EndingStr = Recover ?
"_noabort" :
"";
704 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
706 HwasanMemoryAccessCallbackSizedFnTy);
710 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
712 itostr(1ULL << AccessSizeIndex) +
713 MatchAllStr + EndingStr,
714 HwasanMemoryAccessCallbackFnTy);
718 const std::string MemIntrinCallbackPrefix =
723 HwasanMemmove =
M.getOrInsertFunction(
724 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
725 HwasanMemcpy =
M.getOrInsertFunction(
726 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
727 HwasanMemset =
M.getOrInsertFunction(
728 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
730 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
731 PtrTy, Int8Ty, IntptrTy);
732 HwasanGenerateTagFunc =
733 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
735 HwasanRecordFrameRecordFunc =
736 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
742 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
754 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
758 return getOpaqueNoopCast(IRB, ShadowGlobal);
763 return getOpaqueNoopCast(
765 ConstantInt::get(IntptrTy, Mapping.Offset), PtrTy));
767 if (Mapping.InGlobal)
768 return getDynamicShadowIfunc(IRB);
770 Value *GlobalDynamicAddress =
773 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
776bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
780 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
788 if (
Ptr->isSwiftError())
792 if (!InstrumentStack)
799 if (!InstrumentGlobals)
809 bool Ignored = ignoreAccessWithoutRemark(Inst,
Ptr);
821void HWAddressSanitizer::getInterestingMemoryOperands(
826 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
833 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
836 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
837 LI->getType(), LI->getAlign());
838 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
842 SI->getValueOperand()->getType(),
SI->getAlign());
846 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
847 RMW->getValOperand()->getType(), std::nullopt);
851 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
852 XCHG->getCompareOperand()->getType(),
854 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
855 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
857 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
859 Type *Ty = CI->getParamByValType(ArgNo);
867 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
868 return LI->getPointerOperandIndex();
870 return SI->getPointerOperandIndex();
872 return RMW->getPointerOperandIndex();
874 return XCHG->getPointerOperandIndex();
900 if (Mapping.Offset == 0)
906int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
907 unsigned AccessSizeIndex) {
916HWAddressSanitizer::ShadowTagCheckInfo
919 ShadowTagCheckInfo
R;
926 R.AddrLong = untagPointer(IRB,
R.PtrLong);
927 Value *Shadow = memToShadow(
R.AddrLong, IRB);
931 if (MatchAllTag.has_value()) {
933 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
934 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
938 TagMismatch, InsertBefore,
false,
944void HWAddressSanitizer::instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
945 unsigned AccessSizeIndex,
950 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
954 insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
958 bool useFixedShadowIntrinsic =
false;
967 uint16_t offset_shifted = Mapping.Offset >> 32;
968 useFixedShadowIntrinsic = (
uint64_t)offset_shifted << 32 == Mapping.Offset;
971 if (useFixedShadowIntrinsic)
975 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
976 : Intrinsic::hwasan_check_memaccess_fixedshadow),
977 {
Ptr, ConstantInt::get(Int32Ty, AccessInfo),
978 ConstantInt::get(Int64Ty, Mapping.Offset)});
982 ? Intrinsic::hwasan_check_memaccess_shortgranules
983 : Intrinsic::hwasan_check_memaccess),
984 {ShadowBase,
Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
987void HWAddressSanitizer::instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
988 unsigned AccessSizeIndex,
993 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
995 ShadowTagCheckInfo TCI = insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI);
998 Value *OutOfShortGranuleTagRange =
1001 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1007 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1024 switch (TargetTriple.
getArch()) {
1048 "ebreak\naddiw x0, x11, " +
1058 cast<BranchInst>(CheckFailTerm)
1068 if (isa<MemSetInst>(
MI))
1073void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1075 if (isa<MemTransferInst>(
MI)) {
1077 MI->getOperand(0),
MI->getOperand(1),
1080 if (UseMatchAllCallback)
1081 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1082 IRB.
CreateCall(isa<MemMoveInst>(
MI) ? HwasanMemmove : HwasanMemcpy, Args);
1083 }
else if (isa<MemSetInst>(
MI)) {
1088 if (UseMatchAllCallback)
1089 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1092 MI->eraseFromParent();
1106 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1108 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1109 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1111 if (InstrumentWithCalls) {
1113 if (UseMatchAllCallback)
1114 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1115 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1117 }
else if (OutlinedChecks) {
1118 instrumentMemAccessOutline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1121 instrumentMemAccessInline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1128 ConstantInt::get(IntptrTy, 8))};
1129 if (UseMatchAllCallback)
1130 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1131 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1133 untagPointerOperand(
O.getInsn(),
Addr);
1140 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1141 if (!UseShortGranules)
1145 if (InstrumentWithCalls) {
1148 ConstantInt::get(IntptrTy, AlignedSize)});
1150 size_t ShadowSize =
Size >> Mapping.Scale;
1152 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1161 if (
Size != AlignedSize) {
1162 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1163 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1172unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1174 return AllocaNo & TagMaskByte;
1186 static const unsigned FastMasks[] = {
1187 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1188 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1189 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1190 return FastMasks[AllocaNo % std::size(FastMasks)];
1194 if (TagMaskByte == 0xFF)
1197 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1208 return StackBaseTag;
1212 Value *FramePointerLong = getCachedFP(IRB);
1214 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1216 StackTag->
setName(
"hwasan.stack.base.tag");
1221 unsigned AllocaNo) {
1223 return getNextTagWithCall(IRB);
1225 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1229 Value *FramePointerLong = getCachedFP(IRB);
1231 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1233 UARTag->
setName(
"hwasan.uar.tag");
1241 Value *TaggedPtrLong;
1242 if (CompileKernel) {
1246 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1247 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1251 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1259 Value *UntaggedPtrLong;
1260 if (CompileKernel) {
1264 TagMaskByte << PointerTagShift));
1268 PtrLong, ConstantInt::get(PtrLong->
getType(),
1269 ~(TagMaskByte << PointerTagShift)));
1271 return UntaggedPtrLong;
1277 constexpr int SanitizerSlot = 6;
1280 return ThreadPtrGlobal;
1307void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1309 ShadowBase = getShadowNonTls(IRB);
1310 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1311 ShadowBase = getDynamicShadowIfunc(IRB);
1313 if (!WithFrameRecord && ShadowBase)
1316 Value *SlotPtr =
nullptr;
1317 Value *ThreadLong =
nullptr;
1318 Value *ThreadLongMaybeUntagged =
nullptr;
1320 auto getThreadLongMaybeUntagged = [&]() {
1322 SlotPtr = getHwasanThreadSlotPtr(IRB);
1324 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1327 return TargetTriple.
isAArch64() ? ThreadLong
1328 : untagPointer(IRB, ThreadLong);
1331 if (WithFrameRecord) {
1336 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1337 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1341 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1343 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1346 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1376 ConstantInt::get(IntptrTy, (
uint64_t)-1));
1378 IRB.
CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask);
1384 "A stack history recording mode should've been selected.");
1390 if (!ThreadLongMaybeUntagged)
1391 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1398 ThreadLongMaybeUntagged,
1400 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1405bool HWAddressSanitizer::instrumentLandingPads(
1407 for (
auto *LP : LandingPadVec) {
1408 IRBuilder<> IRB(LP->getNextNonDebugInstruction());
1431 auto *AI = KV.first;
1436 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1438 Value *AINoTagLong = untagPointer(IRB, AILong);
1439 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1445 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1460 II->setArgOperand(0, ConstantInt::get(Int64Ty, AlignedSize));
1461 II->setArgOperand(1, AICast);
1467 auto *
User =
U.getUser();
1468 return User != AILong &&
User != AICast &&
1480 tagAlloca(IRB, AI, UARTag, AlignedSize);
1486 bool StandardLifetime =
1491 if (DetectUseAfterScope && StandardLifetime) {
1494 tagAlloca(IRB, AI,
Tag,
Size);
1497 for (
auto *
End :
Info.LifetimeEnd)
1498 End->eraseFromParent();
1501 tagAlloca(IRB, AI,
Tag,
Size);
1502 for (
auto *RI : SInfo.
RetVec)
1506 for (
auto &
II :
Info.LifetimeStart)
1507 II->eraseFromParent();
1508 for (
auto &
II :
Info.LifetimeEnd)
1509 II->eraseFromParent();
1514 I->eraseFromParent();
1523 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1528 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1533bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1535 auto SkipHot = [&]() {
1541 if (!PSI || !PSI->hasProfileSummary()) {
1542 ++NumNoProfileSummaryFuncs;
1545 return PSI->isFunctionHotInCallGraphNthPercentile(
1549 auto SkipRandom = [&]() {
1556 bool Skip = SkipRandom() || SkipHot();
1561void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1563 if (&
F == HwasanCtorFunction)
1566 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1577 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1580 NumInstrumentedFuncs++;
1591 if (InstrumentStack) {
1595 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1601 if (!ignoreMemIntrinsic(ORE,
MI))
1607 initializeCallbacks(*
F.getParent());
1609 if (!LandingPadVec.
empty())
1610 instrumentLandingPads(LandingPadVec);
1616 F.setPersonalityFn(
nullptr);
1620 IntrinToInstrument.
empty())
1629 F.removeFnAttr(llvm::Attribute::Memory);
1630 for (
auto &
A :
F.args())
1631 A.removeAttr(llvm::Attribute::WriteOnly);
1635 emitPrologue(EntryIRB,
1637 Mapping.WithFrameRecord &&
1644 Value *StackTag = getStackBaseTag(EntryIRB);
1645 Value *UARTag = getUARTag(EntryIRB);
1646 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
1652 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1653 InsertPt =
F.getEntryBlock().begin();
1656 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
1658 I.moveBefore(
F.getEntryBlock(), InsertPt);
1665 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1666 for (
auto &Operand : OperandsToInstrument)
1667 instrumentMemAccess(Operand, DTU, LI);
1671 for (
auto *Inst : IntrinToInstrument)
1672 instrumentMemIntrinsic(Inst);
1675 ShadowBase =
nullptr;
1676 StackBaseTag =
nullptr;
1684 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1685 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1686 if (SizeInBytes != NewSize) {
1689 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1698 NewGV->copyAttributesFrom(GV);
1700 NewGV->copyMetadata(GV, 0);
1701 NewGV->setAlignment(
1721 const uint64_t MaxDescriptorSize = 0xfffff0;
1722 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1723 DescriptorPos += MaxDescriptorSize) {
1726 nullptr, GV->
getName() +
".hwasan.descriptor");
1732 ConstantInt::get(Int64Ty, DescriptorPos)),
1734 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1735 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (
uint32_t(
Tag) << 24));
1736 Descriptor->setComdat(NewGV->getComdat());
1738 Descriptor->setSection(
"hwasan_globals");
1739 Descriptor->setMetadata(LLVMContext::MD_associated,
1747 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1752 Alias->takeName(GV);
1757void HWAddressSanitizer::instrumentGlobals() {
1758 std::vector<GlobalVariable *> Globals;
1777 Globals.push_back(&GV);
1781 Hasher.
update(
M.getSourceFileName());
1784 uint8_t
Tag = Hash[0];
1786 assert(TagMaskByte >= 16);
1792 if (Tag < 16 || Tag > TagMaskByte)
1794 instrumentGlobal(GV,
Tag++);
1798void HWAddressSanitizer::instrumentPersonalityFunctions() {
1807 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1810 if (
F.hasPersonalityFn()) {
1811 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1812 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1813 PersonalityFns[
nullptr].push_back(&
F);
1817 if (PersonalityFns.
empty())
1821 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1822 PtrTy, PtrTy, PtrTy, PtrTy);
1823 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1824 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1826 for (
auto &
P : PersonalityFns) {
1829 ThunkName += (
"." +
P.first->getName()).str();
1831 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1832 bool IsLocal =
P.first && (!isa<GlobalValue>(
P.first) ||
1833 cast<GlobalValue>(
P.first)->hasLocalLinkage());
1840 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1846 HwasanPersonalityWrapper,
1847 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1848 ThunkFn->getArg(3), ThunkFn->getArg(4),
1855 F->setPersonalityFn(ThunkFn);
1859void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1860 bool InstrumentWithCalls) {
1868 WithFrameRecord =
true;
1873 WithFrameRecord =
false;
1878 WithFrameRecord =
false;
1883 WithFrameRecord =
false;
1888 WithFrameRecord =
true;
1893 WithFrameRecord =
false;
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))
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 const uint64_t kDynamicShadowSentinel
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
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 > ClWithIfunc("asan-with-ifunc", cl::desc("Access dynamic shadow through an ifunc global on " "platforms that support this"), 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 GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
#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.
std::optional< std::vector< StOtherPiece > > Other
This is the interface for a simple mod/ref and alias analysis over globals.
static cl::opt< float > ClRandomSkipRate("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function."))
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
static cl::opt< bool > ClInstrumentWrites("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static const size_t kDefaultShadowScale
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[]
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[]
static cl::opt< int > ClHotPercentileCutoff("hwasan-percentile-cutoff-hot", cl::desc("Hot percentile cuttoff."))
static const unsigned kShadowBaseAlignment
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< 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< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
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 const uint64_t kDynamicShadowSentinel
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
static cl::opt< bool > ClWithTls("hwasan-with-tls", cl::desc("Access dynamic shadow through an thread-local pointer on " "platforms that support this"), cl::Hidden, cl::init(true))
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[]
static unsigned getPointerOperandIndex(Instruction *I)
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[]
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[]
static cl::opt< bool > ClWithIfunc("hwasan-with-ifunc", cl::desc("Access dynamic shadow through an ifunc global on " "platforms that support this"), cl::Hidden, cl::init(false))
static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
This file implements a map that provides insertion order iteration.
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
A container for analyses that lazily runs them and caches their results.
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 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,...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Function * getParent() const
Return the enclosing method, or null if none.
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 Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static 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 Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
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...
static 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 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...
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
void setComdat(Comdat *C)
bool hasSection() const
Check if this global has a custom object file section.
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.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Analysis pass providing a never-invalidated alias analysis result.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memset to the specified pointer and the specified value.
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateTypeSize(Type *DstType, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
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 <val>' 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="")
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)
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)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
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.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static 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.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const Instruction * getNextNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the next non-debug instruction in the same basic block as 'this',...
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.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
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.
Constant * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
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.
void abandon()
Mark an analysis as abandoned.
void 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 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.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt8Ty(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
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.
void setName(const Twine &Name)
Change the name of the value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
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...
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
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 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.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
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)
void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
bool isLifetimeIntrinsic(Value *V)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
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...
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.
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.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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 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.
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 ...
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...
bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
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 *, 4 > UnrecognizedLifetimes
SmallVector< Instruction *, 8 > RetVec