71#define DEBUG_TYPE "hwasan"
79 "__hwasan_shadow_memory_dynamic_address";
89enum class OffsetKind {
99 cl::desc(
"Prefix for memory access callbacks"),
103 "hwasan-kernel-mem-intrinsic-prefix",
108 "hwasan-instrument-with-calls",
113 cl::desc(
"instrument read instructions"),
122 "hwasan-instrument-atomics",
127 cl::desc(
"instrument byval arguments"),
132 cl::desc(
"Enable recovery mode (continue-after-error)."),
136 cl::desc(
"instrument stack (allocas)"),
147 cl::desc(
"How many lifetime ends to handle for a single alloca."),
152 cl::desc(
"detect use after scope within function"),
156 "hwasan-generate-tags-with-calls",
164 "hwasan-match-all-tag",
165 cl::desc(
"don't report bad accesses via pointers with this tag"),
170 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
179 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
183 "hwasan-mapping-offset-dynamic",
186 clEnumValN(OffsetKind::kIfunc,
"ifunc",
"Use ifunc global"),
187 clEnumValN(OffsetKind::kTls,
"tls",
"Use TLS")));
191 cl::desc(
"Use ring buffer for stack allocations"),
195 cl::desc(
"Hot percentile cutoff."));
199 cl::desc(
"Probability value in the range [0.0, 1.0] "
200 "to keep instrumentation of a function."));
203STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
204STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
221 "hwasan-record-stack-history",
222 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
226 "storing into the stack ring buffer directly"),
228 "storing into the stack ring buffer")),
233 cl::desc(
"instrument memory intrinsics"),
242 "hwasan-use-short-granules",
247 "hwasan-instrument-personality-functions",
260 cl::desc(
"Use page aliasing in HWASan"),
269bool shouldUsePageAliases(
const Triple &TargetTriple) {
273bool shouldInstrumentStack(
const Triple &TargetTriple) {
277bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
281bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
285bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
286 bool DisableOptimization) {
287 return shouldInstrumentStack(TargetTriple) &&
288 mightUseStackSafetyAnalysis(DisableOptimization);
291bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
297class HWAddressSanitizer {
299 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
302 this->Recover = optOr(
ClRecover, Recover);
313 struct ShadowTagCheckInfo {
315 Value *PtrLong =
nullptr;
316 Value *AddrLong =
nullptr;
317 Value *PtrTag =
nullptr;
318 Value *MemTag =
nullptr;
321 bool selectiveInstrumentationShouldSkip(
Function &
F,
323 void initializeModule();
324 void createHwasanCtorComdat();
327 void initializeCallbacks(
Module &M);
337 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
340 void instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
341 unsigned AccessSizeIndex,
344 void instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
345 unsigned AccessSizeIndex,
375 unsigned retagMask(
unsigned AllocaNo);
377 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
380 void instrumentGlobals();
385 void instrumentPersonalityFunctions();
391 std::unique_ptr<RandomNumberGenerator> Rng;
408 class ShadowMapping {
412 bool WithFrameRecord;
415 Kind = OffsetKind::kFixed;
420 void init(
Triple &TargetTriple,
bool InstrumentWithCalls);
421 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
422 bool isInGlobal()
const {
return Kind == OffsetKind::kGlobal; }
423 bool isInIfunc()
const {
return Kind == OffsetKind::kIfunc; }
424 bool isInTls()
const {
return Kind == OffsetKind::kTls; }
425 bool isFixed()
const {
return Kind == OffsetKind::kFixed; }
431 bool withFrameRecord()
const {
return WithFrameRecord; };
434 ShadowMapping Mapping;
437 Type *IntptrTy =
M.getDataLayout().getIntPtrType(
M.getContext());
438 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
447 bool UseShortGranules;
448 bool InstrumentLandingPads;
449 bool InstrumentWithCalls;
450 bool InstrumentStack;
451 bool InstrumentGlobals;
452 bool DetectUseAfterScope;
454 bool UseMatchAllCallback;
456 std::optional<uint8_t> MatchAllTag;
458 unsigned PointerTagShift;
475 Value *ShadowBase =
nullptr;
476 Value *StackBaseTag =
nullptr;
477 Value *CachedFP =
nullptr;
496 HWASan.sanitizeFunction(
F,
FAM);
514 OS, MapClassName2PassName);
523void HWAddressSanitizer::createHwasanCtorComdat() {
524 std::tie(HwasanCtorFunction, std::ignore) =
573 nullptr,
"__start_hwasan_globals");
577 nullptr,
"__stop_hwasan_globals");
589 Note->setSection(
".note.hwasan.globals");
590 Note->setComdat(NoteComdat);
602 {ConstantInt::get(Int32Ty, 8),
603 ConstantInt::get(Int32Ty, 8),
605 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
613 Dummy->setSection(
"hwasan_globals");
614 Dummy->setComdat(NoteComdat);
615 Dummy->setMetadata(LLVMContext::MD_associated,
620void HWAddressSanitizer::removeFnAttributes(
Function *
F) {
638 bool Changed =
false;
639 if (!
F->doesNotAccessMemory()) {
640 bool WritesMemory = !
F->onlyReadsMemory();
641 bool ReadsMemory = !
F->onlyWritesMemory();
642 if ((WritesMemory && !ReadsMemory) ||
F->onlyAccessesArgMemory()) {
643 F->removeFnAttr(Attribute::Memory);
648 if (
A.hasAttribute(Attribute::WriteOnly)) {
649 A.removeAttr(Attribute::WriteOnly);
656 F->addFnAttr(Attribute::NoBuiltin);
663void HWAddressSanitizer::initializeModule() {
665 TargetTriple =
Triple(
M.getTargetTriple());
668 removeFnAttributes(&
F);
674 UsePageAliases = shouldUsePageAliases(TargetTriple);
675 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
676 InstrumentStack = shouldInstrumentStack(TargetTriple);
677 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
678 PointerTagShift = IsX86_64 ? 57 : 56;
679 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
681 Mapping.init(TargetTriple, InstrumentWithCalls);
683 C = &(
M.getContext());
686 HwasanCtorFunction =
nullptr;
707 }
else if (CompileKernel) {
710 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
716 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
718 if (!CompileKernel) {
719 createHwasanCtorComdat();
721 if (InstrumentGlobals)
724 bool InstrumentPersonalityFunctions =
726 if (InstrumentPersonalityFunctions)
727 instrumentPersonalityFunctions();
731 Constant *
C =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
734 "__hwasan_tls",
nullptr,
739 ThreadPtrGlobal = cast<GlobalVariable>(
C);
743void HWAddressSanitizer::initializeCallbacks(
Module &M) {
745 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
747 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
749 if (UseMatchAllCallback) {
750 HwasanMemoryAccessCallbackSizedFnTy =
752 HwasanMemoryAccessCallbackFnTy =
754 HwasanMemTransferFnTy =
759 HwasanMemoryAccessCallbackSizedFnTy =
761 HwasanMemoryAccessCallbackFnTy =
763 HwasanMemTransferFnTy =
769 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
770 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
771 const std::string EndingStr = Recover ?
"_noabort" :
"";
773 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
775 HwasanMemoryAccessCallbackSizedFnTy);
779 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
781 itostr(1ULL << AccessSizeIndex) +
782 MatchAllStr + EndingStr,
783 HwasanMemoryAccessCallbackFnTy);
787 const std::string MemIntrinCallbackPrefix =
792 HwasanMemmove =
M.getOrInsertFunction(
793 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
794 HwasanMemcpy =
M.getOrInsertFunction(
795 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
796 HwasanMemset =
M.getOrInsertFunction(
797 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
799 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
800 PtrTy, Int8Ty, IntptrTy);
801 HwasanGenerateTagFunc =
802 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
804 HwasanRecordFrameRecordFunc =
805 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
811 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
823 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
827 return getOpaqueNoopCast(IRB, ShadowGlobal);
831 if (Mapping.isFixed()) {
832 return getOpaqueNoopCast(
834 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
837 if (Mapping.isInIfunc())
838 return getDynamicShadowIfunc(IRB);
840 Value *GlobalDynamicAddress =
843 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
846bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
850 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
858 if (
Ptr->isSwiftError())
862 if (!InstrumentStack)
869 if (!InstrumentGlobals)
879 bool Ignored = ignoreAccessWithoutRemark(Inst,
Ptr);
891void HWAddressSanitizer::getInterestingMemoryOperands(
896 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
903 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
906 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
907 LI->getType(), LI->getAlign());
908 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
912 SI->getValueOperand()->getType(),
SI->getAlign());
916 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
917 RMW->getValOperand()->getType(), std::nullopt);
921 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
922 XCHG->getCompareOperand()->getType(),
924 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
925 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
927 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
929 Type *Ty = CI->getParamByValType(ArgNo);
937 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
938 return LI->getPointerOperandIndex();
940 return SI->getPointerOperandIndex();
942 return RMW->getPointerOperandIndex();
944 return XCHG->getPointerOperandIndex();
970 if (Mapping.isFixed() && Mapping.offset() == 0)
976int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
977 unsigned AccessSizeIndex) {
986HWAddressSanitizer::ShadowTagCheckInfo
989 ShadowTagCheckInfo
R;
996 R.AddrLong = untagPointer(IRB,
R.PtrLong);
997 Value *Shadow = memToShadow(
R.AddrLong, IRB);
1001 if (MatchAllTag.has_value()) {
1003 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
1004 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
1008 TagMismatch, InsertBefore,
false,
1014void HWAddressSanitizer::instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
1015 unsigned AccessSizeIndex,
1020 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1024 insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
1027 bool UseFixedShadowIntrinsic =
false;
1035 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
1036 uint16_t OffsetShifted = Mapping.offset() >> 32;
1037 UseFixedShadowIntrinsic =
1038 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
1041 if (UseFixedShadowIntrinsic) {
1044 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
1045 : Intrinsic::hwasan_check_memaccess_fixedshadow,
1047 {
Ptr, ConstantInt::get(Int32Ty, AccessInfo),
1048 ConstantInt::get(Int64Ty, Mapping.offset())});
1051 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
1052 : Intrinsic::hwasan_check_memaccess,
1053 {}, {ShadowBase,
Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
1057void HWAddressSanitizer::instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
1058 unsigned AccessSizeIndex,
1063 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1065 ShadowTagCheckInfo TCI = insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI);
1068 Value *OutOfShortGranuleTagRange =
1069 IRB.
CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
1071 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1077 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1094 switch (TargetTriple.
getArch()) {
1118 "ebreak\naddiw x0, x11, " +
1128 cast<BranchInst>(CheckFailTerm)
1138 if (isa<MemSetInst>(
MI))
1143void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1145 if (isa<MemTransferInst>(
MI)) {
1147 MI->getOperand(0),
MI->getOperand(1),
1150 if (UseMatchAllCallback)
1151 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1152 IRB.
CreateCall(isa<MemMoveInst>(
MI) ? HwasanMemmove : HwasanMemcpy, Args);
1153 }
else if (isa<MemSetInst>(
MI)) {
1158 if (UseMatchAllCallback)
1159 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1162 MI->eraseFromParent();
1187 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1189 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1190 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1192 if (InstrumentWithCalls) {
1194 if (UseMatchAllCallback)
1195 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1196 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1198 }
else if (OutlinedChecks) {
1199 instrumentMemAccessOutline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1202 instrumentMemAccessInline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1209 ConstantInt::get(IntptrTy, 8))};
1210 if (UseMatchAllCallback)
1211 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1212 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1214 untagPointerOperand(
O.getInsn(),
Addr);
1221 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1222 if (!UseShortGranules)
1226 if (InstrumentWithCalls) {
1229 ConstantInt::get(IntptrTy, AlignedSize)});
1231 size_t ShadowSize =
Size >> Mapping.scale();
1233 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1242 if (
Size != AlignedSize) {
1243 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1244 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1253unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1255 return AllocaNo & TagMaskByte;
1267 static const unsigned FastMasks[] = {
1268 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1269 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1270 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1271 return FastMasks[AllocaNo % std::size(FastMasks)];
1275 if (TagMaskByte == 0xFF)
1278 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1289 return StackBaseTag;
1293 Value *FramePointerLong = getCachedFP(IRB);
1295 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1297 StackTag->
setName(
"hwasan.stack.base.tag");
1302 unsigned AllocaNo) {
1304 return getNextTagWithCall(IRB);
1306 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1310 Value *FramePointerLong = getCachedFP(IRB);
1312 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1314 UARTag->
setName(
"hwasan.uar.tag");
1322 Value *TaggedPtrLong;
1323 if (CompileKernel) {
1327 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1328 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1332 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1340 Value *UntaggedPtrLong;
1341 if (CompileKernel) {
1345 TagMaskByte << PointerTagShift));
1349 PtrLong, ConstantInt::get(PtrLong->
getType(),
1350 ~(TagMaskByte << PointerTagShift)));
1352 return UntaggedPtrLong;
1358 constexpr int SanitizerSlot = 6;
1361 return ThreadPtrGlobal;
1388void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1389 if (!Mapping.isInTls())
1390 ShadowBase = getShadowNonTls(IRB);
1391 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1392 ShadowBase = getDynamicShadowIfunc(IRB);
1394 if (!WithFrameRecord && ShadowBase)
1397 Value *SlotPtr =
nullptr;
1398 Value *ThreadLong =
nullptr;
1399 Value *ThreadLongMaybeUntagged =
nullptr;
1401 auto getThreadLongMaybeUntagged = [&]() {
1403 SlotPtr = getHwasanThreadSlotPtr(IRB);
1405 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1408 return TargetTriple.
isAArch64() ? ThreadLong
1409 : untagPointer(IRB, ThreadLong);
1412 if (WithFrameRecord) {
1417 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1418 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1422 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1424 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1427 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1437 "A stack history recording mode should've been selected.");
1443 if (!ThreadLongMaybeUntagged)
1444 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1451 ThreadLongMaybeUntagged,
1453 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1458bool HWAddressSanitizer::instrumentLandingPads(
1460 for (
auto *LP : LandingPadVec) {
1461 IRBuilder<> IRB(LP->getNextNonDebugInstruction());
1484 auto *AI = KV.first;
1489 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1491 Value *AINoTagLong = untagPointer(IRB, AILong);
1492 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1498 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1513 II->setArgOperand(0, ConstantInt::get(Int64Ty, AlignedSize));
1514 II->setArgOperand(1, AICast);
1520 auto *
User =
U.getUser();
1521 return User != AILong &&
User != AICast &&
1533 tagAlloca(IRB, AI, UARTag, AlignedSize);
1539 bool StandardLifetime =
1544 if (DetectUseAfterScope && StandardLifetime) {
1547 tagAlloca(IRB, AI,
Tag,
Size);
1550 for (
auto *
End :
Info.LifetimeEnd)
1551 End->eraseFromParent();
1554 tagAlloca(IRB, AI,
Tag,
Size);
1555 for (
auto *RI : SInfo.
RetVec)
1559 for (
auto &
II :
Info.LifetimeStart)
1560 II->eraseFromParent();
1561 for (
auto &
II :
Info.LifetimeEnd)
1562 II->eraseFromParent();
1567 I->eraseFromParent();
1576 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1581 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1586bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1588 auto SkipHot = [&]() {
1594 if (!PSI || !PSI->hasProfileSummary()) {
1595 ++NumNoProfileSummaryFuncs;
1598 return PSI->isFunctionHotInCallGraphNthPercentile(
1602 auto SkipRandom = [&]() {
1609 bool Skip = SkipRandom() || SkipHot();
1614void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1616 if (&
F == HwasanCtorFunction)
1620 if (
F.hasFnAttribute(Attribute::Naked))
1623 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1634 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1637 NumInstrumentedFuncs++;
1648 if (InstrumentStack) {
1649 SIB.visit(ORE, Inst);
1652 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1658 if (!ignoreMemIntrinsic(ORE,
MI))
1664 initializeCallbacks(*
F.getParent());
1666 if (!LandingPadVec.
empty())
1667 instrumentLandingPads(LandingPadVec);
1673 F.setPersonalityFn(
nullptr);
1677 IntrinToInstrument.
empty())
1684 emitPrologue(EntryIRB,
1686 Mapping.withFrameRecord() &&
1693 Value *StackTag = getStackBaseTag(EntryIRB);
1694 Value *UARTag = getUARTag(EntryIRB);
1695 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
1701 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1702 InsertPt =
F.getEntryBlock().begin();
1705 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
1707 I.moveBefore(
F.getEntryBlock(), InsertPt);
1714 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1716 for (
auto &Operand : OperandsToInstrument)
1717 instrumentMemAccess(Operand, DTU, LI,
DL);
1721 for (
auto *Inst : IntrinToInstrument)
1722 instrumentMemIntrinsic(Inst);
1725 ShadowBase =
nullptr;
1726 StackBaseTag =
nullptr;
1734 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1735 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1736 if (SizeInBytes != NewSize) {
1739 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1748 NewGV->copyAttributesFrom(GV);
1750 NewGV->copyMetadata(GV, 0);
1751 NewGV->setAlignment(
1771 const uint64_t MaxDescriptorSize = 0xfffff0;
1772 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1773 DescriptorPos += MaxDescriptorSize) {
1776 nullptr, GV->
getName() +
".hwasan.descriptor");
1782 ConstantInt::get(Int64Ty, DescriptorPos)),
1784 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1785 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (
uint32_t(
Tag) << 24));
1786 Descriptor->setComdat(NewGV->getComdat());
1788 Descriptor->setSection(
"hwasan_globals");
1789 Descriptor->setMetadata(LLVMContext::MD_associated,
1797 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1802 Alias->takeName(GV);
1807void HWAddressSanitizer::instrumentGlobals() {
1808 std::vector<GlobalVariable *> Globals;
1827 Globals.push_back(&GV);
1831 Hasher.
update(
M.getSourceFileName());
1836 assert(TagMaskByte >= 16);
1842 if (Tag < 16 || Tag > TagMaskByte)
1844 instrumentGlobal(GV,
Tag++);
1848void HWAddressSanitizer::instrumentPersonalityFunctions() {
1857 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1860 if (
F.hasPersonalityFn()) {
1861 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1862 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1863 PersonalityFns[
nullptr].push_back(&
F);
1867 if (PersonalityFns.
empty())
1871 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1872 PtrTy, PtrTy, PtrTy, PtrTy);
1873 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1874 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1876 for (
auto &
P : PersonalityFns) {
1879 ThunkName += (
"." +
P.first->getName()).str();
1881 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1882 bool IsLocal =
P.first && (!isa<GlobalValue>(
P.first) ||
1883 cast<GlobalValue>(
P.first)->hasLocalLinkage());
1890 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1896 HwasanPersonalityWrapper,
1897 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1898 ThunkFn->getArg(3), ThunkFn->getArg(4),
1905 F->setPersonalityFn(ThunkFn);
1909void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1910 bool InstrumentWithCalls) {
1913 Kind = OffsetKind::kTls;
1914 WithFrameRecord =
true;
1923 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))
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const uint64_t kDefaultShadowScale
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentByval("asan-instrument-byval", cl::desc("instrument byval call arguments"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("asan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
static cl::opt< uint64_t > ClMappingOffset("asan-mapping-offset", cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define clEnumVal(ENUMVAL, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
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< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden)
static cl::opt< RecordStackHistoryMode > ClRecordStackHistory("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr))
const char kHwasanModuleCtorName[]
static cl::opt< bool > ClFrameRecords("hwasan-with-frame-record", cl::desc("Use ring buffer for stack allocations"), cl::Hidden)
static cl::opt< int > ClMatchAllTag("hwasan-match-all-tag", cl::desc("don't report bad accesses via pointers with this tag"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClUseAfterScope("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(true))
const char kHwasanNoteName[]
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< OffsetKind > ClMappingOffsetDynamic("hwasan-mapping-offset-dynamic", cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden, cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS")))
static cl::opt< bool > ClRecover("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClEnableKhwasan("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClUsePageAliases("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_"))
static cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
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 void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
static cl::opt< int > ClHotPercentileCutoff("hwasan-percentile-cutoff-hot", cl::desc("Hot percentile cutoff."))
Module.h This file contains the declarations for the Module class.
This file implements a map that provides insertion order iteration.
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.
This class represents an incoming formal argument to a Function.
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.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
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="")
CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
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.
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.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Value * getFP(IRBuilder<> &IRB)
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
Value * readRegister(IRBuilder<> &IRB, StringRef Name)
Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc)
void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
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 computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
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