71#define DEBUG_TYPE "hwasan"
79 "__hwasan_shadow_memory_dynamic_address";
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-all-globals",
166 "Instrument globals, even those within user-defined sections. Warning: "
167 "This may break existing code which walks globals via linker-generated "
168 "symbols, expects certain globals to be contiguous with each other, or "
169 "makes other assumptions which are invalidated by HWASan "
174 "hwasan-match-all-tag",
175 cl::desc(
"don't report bad accesses via pointers with this tag"),
180 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
189 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
193 "hwasan-mapping-offset-dynamic",
196 clEnumValN(OffsetKind::kIfunc,
"ifunc",
"Use ifunc global"),
197 clEnumValN(OffsetKind::kTls,
"tls",
"Use TLS")));
201 cl::desc(
"Use ring buffer for stack allocations"),
205 cl::desc(
"Hot percentile cutoff."));
209 cl::desc(
"Probability value in the range [0.0, 1.0] "
210 "to keep instrumentation of a function. "
211 "Note: instrumentation can be skipped randomly "
212 "OR because of the hot percentile cutoff, if "
213 "both are supplied."));
216 "hwasan-static-linking",
217 cl::desc(
"Don't use .note.hwasan.globals section to instrument globals "
218 "from loadable libraries. "
219 "Note: in static binaries, the global variables section can be "
220 "accessed directly via linker-provided "
221 "__start_hwasan_globals and __stop_hwasan_globals symbols"),
225STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
226STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
243 "hwasan-record-stack-history",
244 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
248 "storing into the stack ring buffer directly"),
250 "storing into the stack ring buffer")),
255 cl::desc(
"instrument memory intrinsics"),
264 "hwasan-use-short-granules",
269 "hwasan-instrument-personality-functions",
282 cl::desc(
"Use page aliasing in HWASan"),
291bool shouldUsePageAliases(
const Triple &TargetTriple) {
295bool shouldInstrumentStack(
const Triple &TargetTriple) {
299bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
303bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
307bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
308 bool DisableOptimization) {
309 return shouldInstrumentStack(TargetTriple) &&
310 mightUseStackSafetyAnalysis(DisableOptimization);
313bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
319class HWAddressSanitizer {
321 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
324 this->Recover = optOr(
ClRecover, Recover);
335 struct ShadowTagCheckInfo {
337 Value *PtrLong =
nullptr;
338 Value *AddrLong =
nullptr;
339 Value *PtrTag =
nullptr;
340 Value *MemTag =
nullptr;
343 bool selectiveInstrumentationShouldSkip(
Function &
F,
345 void initializeModule();
346 void createHwasanCtorComdat();
347 void createHwasanNote();
349 void initializeCallbacks(
Module &M);
359 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
362 void instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
363 unsigned AccessSizeIndex,
366 void instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
367 unsigned AccessSizeIndex,
397 unsigned retagMask(
unsigned AllocaNo);
399 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
402 void instrumentGlobals();
407 void instrumentPersonalityFunctions();
413 std::unique_ptr<RandomNumberGenerator> Rng;
430 class ShadowMapping {
434 bool WithFrameRecord;
437 Kind = OffsetKind::kFixed;
442 void init(
Triple &TargetTriple,
bool InstrumentWithCalls,
444 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
445 bool isInGlobal()
const {
return Kind == OffsetKind::kGlobal; }
446 bool isInIfunc()
const {
return Kind == OffsetKind::kIfunc; }
447 bool isInTls()
const {
return Kind == OffsetKind::kTls; }
448 bool isFixed()
const {
return Kind == OffsetKind::kFixed; }
454 bool withFrameRecord()
const {
return WithFrameRecord; };
457 ShadowMapping Mapping;
460 Type *IntptrTy =
M.getDataLayout().getIntPtrType(
M.getContext());
461 PointerType *PtrTy = PointerType::getUnqual(
M.getContext());
470 bool UseShortGranules;
471 bool InstrumentLandingPads;
472 bool InstrumentWithCalls;
473 bool InstrumentStack;
474 bool InstrumentGlobals;
475 bool DetectUseAfterScope;
477 bool UseMatchAllCallback;
479 std::optional<uint8_t> MatchAllTag;
481 unsigned PointerTagShift;
498 Value *ShadowBase =
nullptr;
499 Value *StackBaseTag =
nullptr;
500 Value *CachedFP =
nullptr;
512 const Triple &TargetTriple = M.getTargetTriple();
519 HWASan.sanitizeFunction(
F,
FAM);
537 OS, MapClassName2PassName);
546void HWAddressSanitizer::createHwasanNote() {
583 nullptr,
"__start_hwasan_globals");
587 nullptr,
"__stop_hwasan_globals");
599 Note->setSection(
".note.hwasan.globals");
600 Note->setComdat(NoteComdat);
612 {ConstantInt::get(Int32Ty, 8),
613 ConstantInt::get(Int32Ty, 8),
615 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
623 Dummy->setSection(
"hwasan_globals");
624 Dummy->setComdat(NoteComdat);
625 Dummy->setMetadata(LLVMContext::MD_associated,
630void HWAddressSanitizer::createHwasanCtorComdat() {
631 std::tie(HwasanCtorFunction, std::ignore) =
656void HWAddressSanitizer::initializeModule() {
658 TargetTriple =
M.getTargetTriple();
669 UsePageAliases = shouldUsePageAliases(TargetTriple);
670 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
671 InstrumentStack = shouldInstrumentStack(TargetTriple);
672 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
673 PointerTagShift = IsX86_64 ? 57 : 56;
674 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
676 Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
678 C = &(
M.getContext());
681 HwasanCtorFunction =
nullptr;
702 }
else if (CompileKernel) {
705 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
711 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
713 if (!CompileKernel) {
714 if (InstrumentGlobals)
717 createHwasanCtorComdat();
719 bool InstrumentPersonalityFunctions =
721 if (InstrumentPersonalityFunctions)
722 instrumentPersonalityFunctions();
726 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
729 "__hwasan_tls",
nullptr,
737void HWAddressSanitizer::initializeCallbacks(
Module &M) {
739 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
741 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
743 if (UseMatchAllCallback) {
744 HwasanMemoryAccessCallbackSizedFnTy =
746 HwasanMemoryAccessCallbackFnTy =
748 HwasanMemTransferFnTy =
753 HwasanMemoryAccessCallbackSizedFnTy =
755 HwasanMemoryAccessCallbackFnTy =
757 HwasanMemTransferFnTy =
763 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
764 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
765 const std::string EndingStr = Recover ?
"_noabort" :
"";
767 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
769 HwasanMemoryAccessCallbackSizedFnTy);
773 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
775 itostr(1ULL << AccessSizeIndex) +
776 MatchAllStr + EndingStr,
777 HwasanMemoryAccessCallbackFnTy);
781 const std::string MemIntrinCallbackPrefix =
786 HwasanMemmove =
M.getOrInsertFunction(
787 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
788 HwasanMemcpy =
M.getOrInsertFunction(
789 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
790 HwasanMemset =
M.getOrInsertFunction(
791 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
793 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
794 PtrTy, Int8Ty, IntptrTy);
795 HwasanGenerateTagFunc =
796 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
798 HwasanRecordFrameRecordFunc =
799 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
805 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
817 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
821 return getOpaqueNoopCast(IRB, ShadowGlobal);
825 if (Mapping.isFixed()) {
826 return getOpaqueNoopCast(
828 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
831 if (Mapping.isInIfunc())
832 return getDynamicShadowIfunc(IRB);
834 Value *GlobalDynamicAddress =
837 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
840bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
844 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
852 if (
Ptr->isSwiftError())
856 if (!InstrumentStack)
863 if (!InstrumentGlobals)
873 bool Ignored = ignoreAccessWithoutRemark(Inst,
Ptr);
885void HWAddressSanitizer::getInterestingMemoryOperands(
890 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
897 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
900 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
901 LI->getType(), LI->getAlign());
902 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
906 SI->getValueOperand()->getType(),
SI->getAlign());
910 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
911 RMW->getValOperand()->getType(), std::nullopt);
915 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
916 XCHG->getCompareOperand()->getType(),
918 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
919 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
921 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
923 Type *Ty = CI->getParamByValType(ArgNo);
931 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
932 return LI->getPointerOperandIndex();
934 return SI->getPointerOperandIndex();
936 return RMW->getPointerOperandIndex();
938 return XCHG->getPointerOperandIndex();
964 if (Mapping.isFixed() && Mapping.offset() == 0)
970int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
971 unsigned AccessSizeIndex) {
980HWAddressSanitizer::ShadowTagCheckInfo
983 ShadowTagCheckInfo
R;
990 R.AddrLong = untagPointer(IRB,
R.PtrLong);
991 Value *Shadow = memToShadow(
R.AddrLong, IRB);
995 if (MatchAllTag.has_value()) {
997 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
998 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
1002 TagMismatch, InsertBefore,
false,
1008void HWAddressSanitizer::instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
1009 unsigned AccessSizeIndex,
1014 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1018 insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
1021 bool UseFixedShadowIntrinsic =
false;
1029 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
1030 uint16_t OffsetShifted = Mapping.offset() >> 32;
1031 UseFixedShadowIntrinsic =
1032 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
1035 if (UseFixedShadowIntrinsic) {
1038 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
1039 : Intrinsic::hwasan_check_memaccess_fixedshadow,
1040 {
Ptr, ConstantInt::get(Int32Ty, AccessInfo),
1041 ConstantInt::get(Int64Ty, Mapping.offset())});
1044 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
1045 : Intrinsic::hwasan_check_memaccess,
1046 {ShadowBase,
Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
1050void HWAddressSanitizer::instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
1051 unsigned AccessSizeIndex,
1056 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1058 ShadowTagCheckInfo TCI = insertShadowTagCheck(
Ptr, InsertBefore, DTU, LI);
1061 Value *OutOfShortGranuleTagRange =
1062 IRB.
CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
1064 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1070 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1087 switch (TargetTriple.
getArch()) {
1111 "ebreak\naddiw x0, x11, " +
1121 cast<BranchInst>(CheckFailTerm)
1131 if (isa<MemSetInst>(
MI))
1136void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1138 if (isa<MemTransferInst>(
MI)) {
1140 MI->getOperand(0),
MI->getOperand(1),
1143 if (UseMatchAllCallback)
1144 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1145 IRB.
CreateCall(isa<MemMoveInst>(
MI) ? HwasanMemmove : HwasanMemcpy, Args);
1146 }
else if (isa<MemSetInst>(
MI)) {
1151 if (UseMatchAllCallback)
1152 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1155 MI->eraseFromParent();
1180 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1182 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1183 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1185 if (InstrumentWithCalls) {
1187 if (UseMatchAllCallback)
1188 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1189 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1191 }
else if (OutlinedChecks) {
1192 instrumentMemAccessOutline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1195 instrumentMemAccessInline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1202 ConstantInt::get(IntptrTy, 8))};
1203 if (UseMatchAllCallback)
1204 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1205 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1207 untagPointerOperand(
O.getInsn(),
Addr);
1214 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1215 if (!UseShortGranules)
1219 if (InstrumentWithCalls) {
1222 ConstantInt::get(IntptrTy, AlignedSize)});
1224 size_t ShadowSize =
Size >> Mapping.scale();
1226 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1235 if (
Size != AlignedSize) {
1236 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1237 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1246unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1248 return AllocaNo & TagMaskByte;
1260 static const unsigned FastMasks[] = {
1261 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1262 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1263 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1264 return FastMasks[AllocaNo % std::size(FastMasks)];
1268 if (TagMaskByte == 0xFF)
1271 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1282 return StackBaseTag;
1286 Value *FramePointerLong = getCachedFP(IRB);
1288 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1290 StackTag->
setName(
"hwasan.stack.base.tag");
1295 unsigned AllocaNo) {
1297 return getNextTagWithCall(IRB);
1299 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1303 Value *FramePointerLong = getCachedFP(IRB);
1305 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1307 UARTag->
setName(
"hwasan.uar.tag");
1315 Value *TaggedPtrLong;
1316 if (CompileKernel) {
1320 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1321 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1325 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1333 Value *UntaggedPtrLong;
1334 if (CompileKernel) {
1338 TagMaskByte << PointerTagShift));
1342 PtrLong, ConstantInt::get(PtrLong->
getType(),
1343 ~(TagMaskByte << PointerTagShift)));
1345 return UntaggedPtrLong;
1351 constexpr int SanitizerSlot = 6;
1354 return ThreadPtrGlobal;
1381void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1382 if (!Mapping.isInTls())
1383 ShadowBase = getShadowNonTls(IRB);
1384 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1385 ShadowBase = getDynamicShadowIfunc(IRB);
1387 if (!WithFrameRecord && ShadowBase)
1390 Value *SlotPtr =
nullptr;
1391 Value *ThreadLong =
nullptr;
1392 Value *ThreadLongMaybeUntagged =
nullptr;
1394 auto getThreadLongMaybeUntagged = [&]() {
1396 SlotPtr = getHwasanThreadSlotPtr(IRB);
1398 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1401 return TargetTriple.
isAArch64() ? ThreadLong
1402 : untagPointer(IRB, ThreadLong);
1405 if (WithFrameRecord) {
1410 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1411 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1415 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1417 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1420 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1430 "A stack history recording mode should've been selected.");
1436 if (!ThreadLongMaybeUntagged)
1437 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1444 ThreadLongMaybeUntagged,
1446 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1451void HWAddressSanitizer::instrumentLandingPads(
1453 for (
auto *LP : LandingPadVec) {
1476 auto *AI = KV.first;
1481 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1483 Value *AINoTagLong = untagPointer(IRB, AILong);
1484 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1490 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1493 auto *
User =
U.getUser();
1494 return User != AILong && !isa<LifetimeIntrinsic>(
User);
1505 tagAlloca(IRB, AI, UARTag, AlignedSize);
1511 bool StandardLifetime =
1515 if (DetectUseAfterScope && StandardLifetime) {
1518 tagAlloca(IRB, AI,
Tag,
Size);
1521 for (
auto *
End :
Info.LifetimeEnd)
1522 End->eraseFromParent();
1525 tagAlloca(IRB, AI,
Tag,
Size);
1526 for (
auto *RI : SInfo.
RetVec)
1530 for (
auto &
II :
Info.LifetimeStart)
1531 II->eraseFromParent();
1532 for (
auto &
II :
Info.LifetimeEnd)
1533 II->eraseFromParent();
1544 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1549 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1554bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1556 auto SkipHot = [&]() {
1562 if (!PSI || !PSI->hasProfileSummary()) {
1563 ++NumNoProfileSummaryFuncs;
1566 return PSI->isFunctionHotInCallGraphNthPercentile(
1570 auto SkipRandom = [&]() {
1577 bool Skip = SkipRandom() || SkipHot();
1582void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1584 if (&
F == HwasanCtorFunction)
1588 if (
F.hasFnAttribute(Attribute::Naked))
1591 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1597 if (
F.isPresplitCoroutine())
1605 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1608 NumInstrumentedFuncs++;
1619 if (InstrumentStack) {
1620 SIB.visit(ORE, Inst);
1623 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1629 if (!ignoreMemIntrinsic(ORE,
MI))
1635 initializeCallbacks(*
F.getParent());
1637 if (!LandingPadVec.
empty())
1638 instrumentLandingPads(LandingPadVec);
1644 F.setPersonalityFn(
nullptr);
1648 IntrinToInstrument.
empty())
1655 emitPrologue(EntryIRB,
1657 Mapping.withFrameRecord() &&
1664 Value *StackTag = getStackBaseTag(EntryIRB);
1665 Value *UARTag = getUARTag(EntryIRB);
1666 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
1672 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1673 InsertPt =
F.getEntryBlock().begin();
1676 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
1678 I.moveBefore(
F.getEntryBlock(), InsertPt);
1685 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1687 for (
auto &Operand : OperandsToInstrument)
1688 instrumentMemAccess(Operand, DTU, LI,
DL);
1692 for (
auto *Inst : IntrinToInstrument)
1693 instrumentMemIntrinsic(Inst);
1696 ShadowBase =
nullptr;
1697 StackBaseTag =
nullptr;
1705 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1706 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1707 if (SizeInBytes != NewSize) {
1710 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1719 NewGV->copyAttributesFrom(GV);
1721 NewGV->copyMetadata(GV, 0);
1722 NewGV->setAlignment(
1742 const uint64_t MaxDescriptorSize = 0xfffff0;
1743 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1744 DescriptorPos += MaxDescriptorSize) {
1747 nullptr, GV->
getName() +
".hwasan.descriptor");
1753 ConstantInt::get(Int64Ty, DescriptorPos)),
1755 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1756 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (
uint32_t(
Tag) << 24));
1757 Descriptor->setComdat(NewGV->getComdat());
1759 Descriptor->setSection(
"hwasan_globals");
1760 Descriptor->setMetadata(LLVMContext::MD_associated,
1768 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1773 Alias->takeName(GV);
1778void HWAddressSanitizer::instrumentGlobals() {
1779 std::vector<GlobalVariable *> Globals;
1804 Globals.push_back(&GV);
1808 Hasher.
update(
M.getSourceFileName());
1813 assert(TagMaskByte >= 16);
1819 if (Tag < 16 || Tag > TagMaskByte)
1821 instrumentGlobal(GV,
Tag++);
1825void HWAddressSanitizer::instrumentPersonalityFunctions() {
1834 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1837 if (
F.hasPersonalityFn()) {
1838 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1839 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1840 PersonalityFns[
nullptr].push_back(&
F);
1844 if (PersonalityFns.
empty())
1848 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1849 PtrTy, PtrTy, PtrTy, PtrTy);
1850 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1851 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1853 for (
auto &
P : PersonalityFns) {
1856 ThunkName += (
"." +
P.first->getName()).str();
1858 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1859 bool IsLocal =
P.first && (!isa<GlobalValue>(
P.first) ||
1860 cast<GlobalValue>(
P.first)->hasLocalLinkage());
1867 return F->hasFnAttribute(
"branch-target-enforcement");
1869 ThunkFn->addFnAttr(
"branch-target-enforcement");
1873 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1879 HwasanPersonalityWrapper,
1880 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1881 ThunkFn->getArg(3), ThunkFn->getArg(4),
1888 F->setPersonalityFn(ThunkFn);
1892void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1893 bool InstrumentWithCalls,
1894 bool CompileKernel) {
1897 Kind = OffsetKind::kTls;
1898 WithFrameRecord =
true;
1905 }
else if (CompileKernel || InstrumentWithCalls) {
1907 WithFrameRecord =
false;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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< 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 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< float > ClRandomKeepRate("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function. " "Note: instrumentation can be skipped randomly " "OR because of the hot percentile cutoff, if " "both are supplied."))
static cl::opt< bool > ClInstrumentWithCalls("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional)
static cl::opt< bool > ClInstrumentAtomics("hwasan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentStack("hwasan-instrument-stack", cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true))
static cl::opt< OffsetKind > ClMappingOffsetDynamic("hwasan-mapping-offset-dynamic", cl::desc("HWASan shadow mapping dynamic offset location"), cl::Hidden, cl::values(clEnumValN(OffsetKind::kGlobal, "global", "Use global"), clEnumValN(OffsetKind::kIfunc, "ifunc", "Use ifunc global"), clEnumValN(OffsetKind::kTls, "tls", "Use TLS")))
static cl::opt< bool > ClRecover("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClEnableKhwasan("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClUsePageAliases("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_"))
static cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
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 > ClAllGlobals("hwasan-all-globals", cl::desc("Instrument globals, even those within user-defined sections. Warning: " "This may break existing code which walks globals via linker-generated " "symbols, expects certain globals to be contiguous with each other, or " "makes other assumptions which are invalidated by HWASan " "instrumentation."), cl::Hidden, cl::init(false))
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 > ClStaticLinking("hwasan-static-linking", cl::desc("Don't use .note.hwasan.globals section to instrument globals " "from loadable libraries. " "Note: in static binaries, the global variables section can be " "accessed directly via linker-provided " "__start_hwasan_globals and __stop_hwasan_globals symbols"), cl::Hidden, cl::init(false))
static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
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
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 LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
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 LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void flush()
Apply all pending updates to available trees and flush all BasicBlocks awaiting deletion.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
StringRef getSection() const
Get the custom section of this global if it has one.
LLVM_ABI void setComdat(Comdat *C)
bool hasSection() const
Check if this global has a custom object file section.
LLVM_ABI const SanitizerMetadata & getSanitizerMetadata() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
LinkageTypes getLinkage() const
bool isDeclarationForLinker() const
bool hasSanitizerMetadata() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
bool hasCommonLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Analysis pass providing a never-invalidated alias analysis result.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
LLVM_ABI 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="")
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
ReturnInst * CreateRet(Value *V)
Create a 'ret <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="")
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
A wrapper class for inspecting calls to intrinsic functions.
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.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
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.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
bool stackAccessIsSafe(const Instruction &I) const
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
bool isAndroidVersionLT(unsigned Major) const
bool isAndroid() const
Tests whether the target is Android.
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
int getNumOccurrences() const
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)
Get all the memory operands from the instruction that needs to be instrumented.
@ C
The default llvm calling convention, compatible with C.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
Value * getFP(IRBuilder<> &IRB)
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
Value * readRegister(IRBuilder<> &IRB, StringRef Name)
Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc)
void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
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.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem)
Remove memory attributes that are incompatible with the instrumentation added by AddressSanitizer and...
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
A CRTP mix-in to automatically provide informational APIs needed for passes.
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 8 > RetVec