70#define DEBUG_TYPE "hwasan"
78 "__hwasan_shadow_memory_dynamic_address";
85 std::numeric_limits<uint64_t>::max();
91 cl::desc(
"Prefix for memory access callbacks"),
95 "hwasan-kernel-mem-intrinsic-prefix",
100 "hwasan-instrument-with-calls",
105 cl::desc(
"instrument read instructions"),
114 "hwasan-instrument-atomics",
119 cl::desc(
"instrument byval arguments"),
124 cl::desc(
"Enable recovery mode (continue-after-error)."),
128 cl::desc(
"instrument stack (allocas)"),
139 cl::desc(
"How many lifetime ends to handle for a single alloca."),
144 cl::desc(
"detect use after scope within function"),
148 "hwasan-generate-tags-with-calls",
156 "hwasan-match-all-tag",
157 cl::desc(
"don't report bad accesses via pointers with this tag"),
162 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
171 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
176 cl::desc(
"Access dynamic shadow through an ifunc global on "
177 "platforms that support this"),
182 cl::desc(
"Access dynamic shadow through an thread-local pointer on "
183 "platforms that support this"),
187 cl::desc(
"Hot percentile cuttoff."));
191 cl::desc(
"Probability value in the range [0.0, 1.0] "
192 "to keep instrumentation of a function."));
195STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
196STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
213 "hwasan-record-stack-history",
214 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
218 "storing into the stack ring buffer directly"),
220 "storing into the stack ring buffer")),
225 cl::desc(
"instrument memory intrinsics"),
234 "hwasan-use-short-granules",
239 "hwasan-instrument-personality-functions",
252 cl::desc(
"Use page aliasing in HWASan"),
261bool shouldUsePageAliases(
const Triple &TargetTriple) {
265bool shouldInstrumentStack(
const Triple &TargetTriple) {
269bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
273bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
277bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
278 bool DisableOptimization) {
279 return shouldInstrumentStack(TargetTriple) &&
280 mightUseStackSafetyAnalysis(DisableOptimization);
283bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
289class HWAddressSanitizer {
291 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
294 this->Recover = optOr(
ClRecover, Recover);
305 struct ShadowTagCheckInfo {
307 Value *PtrLong =
nullptr;
308 Value *AddrLong =
nullptr;
309 Value *PtrTag =
nullptr;
310 Value *MemTag =
nullptr;
313 bool selectiveInstrumentationShouldSkip(
Function &
F,
315 void initializeModule();
316 void createHwasanCtorComdat();
318 void initializeCallbacks(
Module &M);
328 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
331 void instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
332 unsigned AccessSizeIndex,
335 void instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
336 unsigned AccessSizeIndex,
344 void getInterestingMemoryOperands(
362 unsigned retagMask(
unsigned AllocaNo);
364 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
367 void instrumentGlobals();
372 void instrumentPersonalityFunctions();
378 std::unique_ptr<RandomNumberGenerator> Rng;
391 struct ShadowMapping {
396 bool WithFrameRecord;
398 void init(
Triple &TargetTriple,
bool InstrumentWithCalls);
399 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
402 ShadowMapping Mapping;
405 Type *IntptrTy =
M.getDataLayout().getIntPtrType(
M.getContext());
406 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
415 bool UseShortGranules;
416 bool InstrumentLandingPads;
417 bool InstrumentWithCalls;
418 bool InstrumentStack;
419 bool InstrumentGlobals;
420 bool DetectUseAfterScope;
422 bool UseMatchAllCallback;
424 std::optional<uint8_t> MatchAllTag;
426 unsigned PointerTagShift;
443 Value *ShadowBase =
nullptr;
444 Value *StackBaseTag =
nullptr;
445 Value *CachedFP =
nullptr;
461 HWASan.sanitizeFunction(
F,
FAM);
479 OS, MapClassName2PassName);
488void HWAddressSanitizer::createHwasanCtorComdat() {
489 std::tie(HwasanCtorFunction, std::ignore) =
538 nullptr,
"__start_hwasan_globals");
542 nullptr,
"__stop_hwasan_globals");
554 Note->setSection(
".note.hwasan.globals");
555 Note->setComdat(NoteComdat);
570 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
578 Dummy->setSection(
"hwasan_globals");
579 Dummy->setComdat(NoteComdat);
580 Dummy->setMetadata(LLVMContext::MD_associated,
588void HWAddressSanitizer::initializeModule() {
590 TargetTriple =
Triple(
M.getTargetTriple());
596 UsePageAliases = shouldUsePageAliases(TargetTriple);
597 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
598 InstrumentStack = shouldInstrumentStack(TargetTriple);
599 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
600 PointerTagShift = IsX86_64 ? 57 : 56;
601 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
603 Mapping.init(TargetTriple, InstrumentWithCalls);
605 C = &(
M.getContext());
608 HwasanCtorFunction =
nullptr;
629 }
else if (CompileKernel) {
632 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
638 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
640 if (!CompileKernel) {
641 createHwasanCtorComdat();
643 if (InstrumentGlobals)
646 bool InstrumentPersonalityFunctions =
648 if (InstrumentPersonalityFunctions)
649 instrumentPersonalityFunctions();
653 Constant *
C =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
656 "__hwasan_tls",
nullptr,
661 ThreadPtrGlobal = cast<GlobalVariable>(
C);
665void HWAddressSanitizer::initializeCallbacks(
Module &M) {
667 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
669 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
671 if (UseMatchAllCallback) {
672 HwasanMemoryAccessCallbackSizedFnTy =
674 HwasanMemoryAccessCallbackFnTy =
676 HwasanMemTransferFnTy =
681 HwasanMemoryAccessCallbackSizedFnTy =
683 HwasanMemoryAccessCallbackFnTy =
685 HwasanMemTransferFnTy =
691 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
692 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
693 const std::string EndingStr = Recover ?
"_noabort" :
"";
695 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
697 HwasanMemoryAccessCallbackSizedFnTy);
701 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
703 itostr(1ULL << AccessSizeIndex) +
704 MatchAllStr + EndingStr,
705 HwasanMemoryAccessCallbackFnTy);
709 const std::string MemIntrinCallbackPrefix =
714 HwasanMemmove =
M.getOrInsertFunction(
715 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
716 HwasanMemcpy =
M.getOrInsertFunction(
717 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
718 HwasanMemset =
M.getOrInsertFunction(
719 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
721 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
722 PtrTy, Int8Ty, IntptrTy);
723 HwasanGenerateTagFunc =
724 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
726 HwasanRecordFrameRecordFunc =
727 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
733 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
745 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
749 return getOpaqueNoopCast(IRB, ShadowGlobal);
754 return getOpaqueNoopCast(
756 ConstantInt::get(IntptrTy, Mapping.Offset), PtrTy));
758 if (Mapping.InGlobal)
759 return getDynamicShadowIfunc(IRB);
761 Value *GlobalDynamicAddress =
764 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
770 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
778 if (
Ptr->isSwiftError())
782 if (!InstrumentStack)
789 if (!InstrumentGlobals)
797void HWAddressSanitizer::getInterestingMemoryOperands(
801 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
808 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
811 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
812 LI->getType(), LI->getAlign());
813 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
817 SI->getValueOperand()->getType(),
SI->getAlign());
821 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
822 RMW->getValOperand()->getType(), std::nullopt);
826 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
827 XCHG->getCompareOperand()->getType(),
829 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
830 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
832 ignoreAccess(
I, CI->getArgOperand(ArgNo)))
834 Type *Ty = CI->getParamByValType(ArgNo);
842 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
843 return LI->getPointerOperandIndex();
845 return SI->getPointerOperandIndex();
847 return RMW->getPointerOperandIndex();
849 return XCHG->getPointerOperandIndex();
875 if (Mapping.Offset == 0)
881int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
882 unsigned AccessSizeIndex) {
891HWAddressSanitizer::ShadowTagCheckInfo
894 ShadowTagCheckInfo
R;
901 R.AddrLong = untagPointer(IRB,
R.PtrLong);
902 Value *Shadow = memToShadow(
R.AddrLong, IRB);
906 if (MatchAllTag.has_value()) {
908 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
909 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
913 TagMismatch, InsertBefore,
false,
919void HWAddressSanitizer::instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
920 unsigned AccessSizeIndex,
925 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
929 insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
935 ? Intrinsic::hwasan_check_memaccess_shortgranules
936 : Intrinsic::hwasan_check_memaccess),
937 {ShadowBase,
Ptr, ConstantInt::get(
Int32Ty, AccessInfo)});
940void HWAddressSanitizer::instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
941 unsigned AccessSizeIndex,
946 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
948 ShadowTagCheckInfo TCI = insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI);
951 Value *OutOfShortGranuleTagRange =
954 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
960 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
977 switch (TargetTriple.
getArch()) {
1001 "ebreak\naddiw x0, x11, " +
1011 cast<BranchInst>(CheckFailTerm)
1020 if (isa<MemSetInst>(
MI))
1025void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1027 if (isa<MemTransferInst>(
MI)) {
1029 MI->getOperand(0),
MI->getOperand(1),
1032 if (UseMatchAllCallback)
1033 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1034 IRB.
CreateCall(isa<MemMoveInst>(
MI) ? HwasanMemmove : HwasanMemcpy, Args);
1035 }
else if (isa<MemSetInst>(
MI)) {
1040 if (UseMatchAllCallback)
1041 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1044 MI->eraseFromParent();
1058 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1060 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1061 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1063 if (InstrumentWithCalls) {
1065 if (UseMatchAllCallback)
1066 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1067 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1069 }
else if (OutlinedChecks) {
1070 instrumentMemAccessOutline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1073 instrumentMemAccessInline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1080 ConstantInt::get(IntptrTy, 8))};
1081 if (UseMatchAllCallback)
1082 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1083 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1085 untagPointerOperand(
O.getInsn(),
Addr);
1092 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1093 if (!UseShortGranules)
1097 if (InstrumentWithCalls) {
1100 ConstantInt::get(IntptrTy, AlignedSize)});
1102 size_t ShadowSize =
Size >> Mapping.Scale;
1104 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1113 if (
Size != AlignedSize) {
1114 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1115 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1124unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1126 return AllocaNo & TagMaskByte;
1138 static const unsigned FastMasks[] = {
1139 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1140 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1141 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1142 return FastMasks[AllocaNo % std::size(FastMasks)];
1146 if (TagMaskByte == 0xFF)
1149 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1160 return StackBaseTag;
1164 Value *FramePointerLong = getCachedFP(IRB);
1166 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1168 StackTag->
setName(
"hwasan.stack.base.tag");
1173 unsigned AllocaNo) {
1175 return getNextTagWithCall(IRB);
1177 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1181 Value *FramePointerLong = getCachedFP(IRB);
1183 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1185 UARTag->
setName(
"hwasan.uar.tag");
1193 Value *TaggedPtrLong;
1194 if (CompileKernel) {
1198 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1199 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1203 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1211 Value *UntaggedPtrLong;
1212 if (CompileKernel) {
1216 TagMaskByte << PointerTagShift));
1220 PtrLong, ConstantInt::get(PtrLong->
getType(),
1221 ~(TagMaskByte << PointerTagShift)));
1223 return UntaggedPtrLong;
1229 constexpr int SanitizerSlot = 6;
1232 return ThreadPtrGlobal;
1256void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1258 ShadowBase = getShadowNonTls(IRB);
1259 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1260 ShadowBase = getDynamicShadowIfunc(IRB);
1262 if (!WithFrameRecord && ShadowBase)
1265 Value *SlotPtr =
nullptr;
1266 Value *ThreadLong =
nullptr;
1267 Value *ThreadLongMaybeUntagged =
nullptr;
1269 auto getThreadLongMaybeUntagged = [&]() {
1271 SlotPtr = getHwasanThreadSlotPtr(IRB);
1273 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1276 return TargetTriple.
isAArch64() ? ThreadLong
1277 : untagPointer(IRB, ThreadLong);
1280 if (WithFrameRecord) {
1285 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1286 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1290 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1292 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1295 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1325 ConstantInt::get(IntptrTy, (
uint64_t)-1));
1327 IRB.
CreateAdd(ThreadLong, ConstantInt::get(IntptrTy, 8)), WrapMask);
1333 "A stack history recording mode should've been selected.");
1339 if (!ThreadLongMaybeUntagged)
1340 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1347 ThreadLongMaybeUntagged,
1349 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1354bool HWAddressSanitizer::instrumentLandingPads(
1356 for (
auto *LP : LandingPadVec) {
1357 IRBuilder<> IRB(LP->getNextNonDebugInstruction());
1367 return dyn_cast<DbgAssignIntrinsic>(DVI);
1388 auto *AI = KV.first;
1393 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1395 Value *AINoTagLong = untagPointer(IRB, AILong);
1396 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1402 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1417 II->setArgOperand(0, ConstantInt::get(Int64Ty, AlignedSize));
1418 II->setArgOperand(1, AICast);
1424 auto *
User =
U.getUser();
1425 return User != AILong &&
User != AICast &&
1432 auto AnnotateDbgRecord = [&](
auto *DPtr) {
1438 for (
size_t LocNo = 0; LocNo < DPtr->getNumVariableLocationOps(); ++LocNo)
1439 if (DPtr->getVariableLocationOp(LocNo) == AI)
1441 DPtr->getExpression(), NewOps, LocNo));
1443 if (DAI->getAddress() == AI)
1445 DAI->getAddressExpression(), NewOps));
1458 tagAlloca(IRB, AI, UARTag, AlignedSize);
1464 bool StandardLifetime =
1469 if (DetectUseAfterScope && StandardLifetime) {
1472 tagAlloca(IRB, AI,
Tag,
Size);
1475 for (
auto *
End :
Info.LifetimeEnd)
1476 End->eraseFromParent();
1479 tagAlloca(IRB, AI,
Tag,
Size);
1480 for (
auto *RI : SInfo.
RetVec)
1484 for (
auto &II :
Info.LifetimeStart)
1485 II->eraseFromParent();
1486 for (
auto &II :
Info.LifetimeEnd)
1487 II->eraseFromParent();
1492 I->eraseFromParent();
1501 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1506 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1511bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1523 if (!PSI || !PSI->hasProfileSummary()) {
1524 ++NumNoProfileSummaryFuncs;
1527 return PSI->isFunctionHotInCallGraphNthPercentile(
1534void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1536 if (&
F == HwasanCtorFunction)
1539 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1547 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1550 NumInstrumentedFuncs++;
1561 if (InstrumentStack) {
1565 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1568 getInterestingMemoryOperands(&Inst, TLI, OperandsToInstrument);
1571 if (!ignoreMemIntrinsic(
MI))
1577 initializeCallbacks(*
F.getParent());
1579 if (!LandingPadVec.
empty())
1580 instrumentLandingPads(LandingPadVec);
1586 F.setPersonalityFn(
nullptr);
1590 IntrinToInstrument.
empty())
1597 emitPrologue(EntryIRB,
1599 Mapping.WithFrameRecord &&
1606 Value *StackTag = getStackBaseTag(EntryIRB);
1607 Value *UARTag = getUARTag(EntryIRB);
1608 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
1614 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1615 InsertPt =
F.getEntryBlock().begin();
1618 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
1620 I.moveBefore(
F.getEntryBlock(), InsertPt);
1628 for (
auto &Operand : OperandsToInstrument)
1629 instrumentMemAccess(Operand, DTU, LI);
1633 for (
auto *Inst : IntrinToInstrument)
1634 instrumentMemIntrinsic(Inst);
1637 ShadowBase =
nullptr;
1638 StackBaseTag =
nullptr;
1646 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1647 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1648 if (SizeInBytes != NewSize) {
1651 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1660 NewGV->copyAttributesFrom(GV);
1662 NewGV->copyMetadata(GV, 0);
1663 NewGV->setAlignment(
1683 const uint64_t MaxDescriptorSize = 0xfffff0;
1684 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1685 DescriptorPos += MaxDescriptorSize) {
1688 nullptr, GV->
getName() +
".hwasan.descriptor");
1694 ConstantInt::get(Int64Ty, DescriptorPos)),
1696 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1698 Descriptor->setComdat(NewGV->getComdat());
1700 Descriptor->setSection(
"hwasan_globals");
1701 Descriptor->setMetadata(LLVMContext::MD_associated,
1709 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1714 Alias->takeName(GV);
1719void HWAddressSanitizer::instrumentGlobals() {
1720 std::vector<GlobalVariable *> Globals;
1739 Globals.push_back(&GV);
1743 Hasher.
update(
M.getSourceFileName());
1746 uint8_t
Tag = Hash[0];
1748 assert(TagMaskByte >= 16);
1754 if (Tag < 16 || Tag > TagMaskByte)
1756 instrumentGlobal(GV,
Tag++);
1760void HWAddressSanitizer::instrumentPersonalityFunctions() {
1769 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1772 if (
F.hasPersonalityFn()) {
1773 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1774 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1775 PersonalityFns[
nullptr].push_back(&
F);
1779 if (PersonalityFns.
empty())
1784 PtrTy, PtrTy, PtrTy, PtrTy);
1785 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1786 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1788 for (
auto &
P : PersonalityFns) {
1791 ThunkName += (
"." +
P.first->getName()).str();
1794 bool IsLocal =
P.first && (!isa<GlobalValue>(
P.first) ||
1795 cast<GlobalValue>(
P.first)->hasLocalLinkage());
1802 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1808 HwasanPersonalityWrapper,
1809 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1810 ThunkFn->getArg(3), ThunkFn->getArg(4),
1817 F->setPersonalityFn(ThunkFn);
1821void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1822 bool InstrumentWithCalls) {
1830 WithFrameRecord =
true;
1835 WithFrameRecord =
false;
1840 WithFrameRecord =
false;
1845 WithFrameRecord =
false;
1850 WithFrameRecord =
true;
1855 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 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< 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 DbgAssignIntrinsic * DynCastToDbgAssign(DbgVariableIntrinsic *DVI)
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.
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.
static DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
static DIExpression * prependOpcodes(const DIExpression *Expr, SmallVectorImpl< uint64_t > &Ops, bool StackValue=false, bool EntryValue=false)
Prepend DIExpr with the given opcodes and optionally turn it into a stack value.
This represents the llvm.dbg.assign instruction.
This is the common base class for debug info intrinsics for variables.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
void flush()
Apply all pending updates to available trees and flush all BasicBlocks awaiting deletion.
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)
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 * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", bool IsInBounds=false)
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.
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 BasicBlock * getParent() const
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 * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
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.
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.
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.
@ 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)
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
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 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 and pointer casts from the specified value,...
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...
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