72#define DEBUG_TYPE "hwasan"
80 "__hwasan_shadow_memory_dynamic_address";
100 cl::desc(
"Prefix for memory access callbacks"),
104 "hwasan-kernel-mem-intrinsic-prefix",
109 "hwasan-instrument-with-calls",
114 cl::desc(
"instrument read instructions"),
123 "hwasan-instrument-atomics",
128 cl::desc(
"instrument byval arguments"),
133 cl::desc(
"Enable recovery mode (continue-after-error)."),
137 cl::desc(
"instrument stack (allocas)"),
147 cl::desc(
"How many lifetime ends to handle for a single alloca."));
151 cl::desc(
"detect use after scope within function"),
155 "hwasan-strict-use-after-scope",
156 cl::desc(
"for complicated lifetimes, tag both on end and return"),
160 "hwasan-generate-tags-with-calls",
168 "hwasan-all-globals",
170 "Instrument globals, even those within user-defined sections. Warning: "
171 "This may break existing code which walks globals via linker-generated "
172 "symbols, expects certain globals to be contiguous with each other, or "
173 "makes other assumptions which are invalidated by HWASan "
178 "hwasan-match-all-tag",
179 cl::desc(
"don't report bad accesses via pointers with this tag"),
184 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
193 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
197 "hwasan-mapping-offset-dynamic",
200 clEnumValN(OffsetKind::kIfunc,
"ifunc",
"Use ifunc global"),
201 clEnumValN(OffsetKind::kTls,
"tls",
"Use TLS")));
205 cl::desc(
"Use ring buffer for stack allocations"),
209 cl::desc(
"Hot percentile cutoff."));
213 cl::desc(
"Probability value in the range [0.0, 1.0] "
214 "to keep instrumentation of a function. "
215 "Note: instrumentation can be skipped randomly "
216 "OR because of the hot percentile cutoff, if "
217 "both are supplied."));
220 "hwasan-static-linking",
221 cl::desc(
"Don't use .note.hwasan.globals section to instrument globals "
222 "from loadable libraries. "
223 "Note: in static binaries, the global variables section can be "
224 "accessed directly via linker-provided "
225 "__start_hwasan_globals and __stop_hwasan_globals symbols"),
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"),
287 cl::desc(
"Restrict tag to at most N bits. Needs to be > 4."),
291STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
292STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
300bool shouldUsePageAliases(
const Triple &TargetTriple) {
304bool shouldInstrumentStack(
const Triple &TargetTriple) {
308bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
312bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
316bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
317 bool DisableOptimization) {
318 return shouldInstrumentStack(TargetTriple) &&
319 mightUseStackSafetyAnalysis(DisableOptimization);
322bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
328class HWAddressSanitizer {
330 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
331 const StackSafetyGlobalInfo *SSI)
333 this->Recover = optOr(
ClRecover, Recover);
344 struct ShadowTagCheckInfo {
346 Value *PtrLong =
nullptr;
347 Value *AddrLong =
nullptr;
348 Value *PtrTag =
nullptr;
349 Value *MemTag =
nullptr;
352 bool selectiveInstrumentationShouldSkip(
Function &
F,
354 void initializeModule();
355 void createHwasanCtorComdat();
356 void createHwasanNote();
358 void initializeCallbacks(
Module &M);
365 void untagPointerOperand(Instruction *
I,
Value *Addr);
368 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
369 ShadowTagCheckInfo insertShadowTagCheck(
Value *Ptr, Instruction *InsertBefore,
370 DomTreeUpdater &DTU, LoopInfo *LI);
371 void instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
372 unsigned AccessSizeIndex,
373 Instruction *InsertBefore,
374 DomTreeUpdater &DTU, LoopInfo *LI);
375 void instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
376 unsigned AccessSizeIndex,
377 Instruction *InsertBefore, DomTreeUpdater &DTU,
379 bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *
MI);
380 void instrumentMemIntrinsic(MemIntrinsic *
MI);
381 bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
382 LoopInfo *LI,
const DataLayout &
DL);
383 bool ignoreAccessWithoutRemark(Instruction *Inst,
Value *Ptr);
384 bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
388 OptimizationRemarkEmitter &ORE, Instruction *
I,
389 const TargetLibraryInfo &TLI,
390 SmallVectorImpl<InterestingMemoryOperand> &Interesting);
395 void instrumentStack(OptimizationRemarkEmitter &ORE, memtag::StackInfo &Info,
396 Value *StackTag,
Value *UARTag,
const DominatorTree &DT,
397 const PostDominatorTree &PDT,
const LoopInfo &LI);
398 void instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
406 unsigned retagMask(
unsigned AllocaNo);
408 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
410 void instrumentGlobal(GlobalVariable *GV, uint8_t
Tag);
411 void instrumentGlobals();
416 void instrumentPersonalityFunctions();
420 const StackSafetyGlobalInfo *SSI;
422 std::unique_ptr<RandomNumberGenerator> Rng;
439 class ShadowMapping {
443 bool WithFrameRecord;
446 Kind = OffsetKind::kFixed;
451 void init(Triple &TargetTriple,
bool InstrumentWithCalls,
453 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
454 bool isInGlobal()
const {
return Kind == OffsetKind::kGlobal; }
455 bool isInIfunc()
const {
return Kind == OffsetKind::kIfunc; }
456 bool isInTls()
const {
return Kind == OffsetKind::kTls; }
457 bool isFixed()
const {
return Kind == OffsetKind::kFixed; }
458 uint8_t
scale()
const {
return Scale; };
463 bool withFrameRecord()
const {
return WithFrameRecord; };
466 ShadowMapping Mapping;
468 Type *VoidTy = Type::getVoidTy(M.getContext());
469 Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());
470 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
471 Type *Int8Ty = Type::getInt8Ty(M.getContext());
472 Type *Int32Ty = Type::getInt32Ty(M.getContext());
473 Type *Int64Ty = Type::getInt64Ty(M.getContext());
479 bool UseShortGranules;
480 bool InstrumentLandingPads;
481 bool InstrumentWithCalls;
482 bool InstrumentStack;
483 bool InstrumentGlobals;
484 bool DetectUseAfterScope;
486 bool UseMatchAllCallback;
488 std::optional<uint8_t> MatchAllTag;
490 unsigned PointerTagShift;
496 FunctionCallee HwasanMemoryAccessCallbackSized[2];
498 FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;
499 FunctionCallee HwasanHandleVfork;
501 FunctionCallee HwasanTagMemoryFunc;
502 FunctionCallee HwasanGenerateTagFunc;
503 FunctionCallee HwasanRecordFrameRecordFunc;
507 Value *ShadowBase =
nullptr;
508 Value *StackBaseTag =
nullptr;
509 Value *CachedFP =
nullptr;
510 GlobalValue *ThreadPtrGlobal =
nullptr;
521 const Triple &TargetTriple = M.getTargetTriple();
522 if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
525 HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);
528 HWASan.sanitizeFunction(
F,
FAM);
545 static_cast<PassInfoMixin<HWAddressSanitizerPass> *
>(
this)->
printPipeline(
546 OS, MapClassName2PassName);
548 if (Options.CompileKernel)
555void HWAddressSanitizer::createHwasanNote() {
592 nullptr,
"__start_hwasan_globals");
596 nullptr,
"__stop_hwasan_globals");
603 auto *NoteTy =
StructType::get(Int32Ty, Int32Ty, Int32Ty, Name->getType(),
608 Note->setSection(
".note.hwasan.globals");
609 Note->setComdat(NoteComdat);
614 auto CreateRelPtr = [&](
Constant *Ptr) {
621 {ConstantInt::get(Int32Ty, 8),
622 ConstantInt::get(Int32Ty, 8),
624 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
632 Dummy->setSection(
"hwasan_globals");
633 Dummy->setComdat(NoteComdat);
634 Dummy->setMetadata(LLVMContext::MD_associated,
639void HWAddressSanitizer::createHwasanCtorComdat() {
640 std::tie(HwasanCtorFunction, std::ignore) =
665void HWAddressSanitizer::initializeModule() {
667 TargetTriple =
M.getTargetTriple();
678 UsePageAliases = shouldUsePageAliases(TargetTriple);
679 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
680 InstrumentStack = shouldInstrumentStack(TargetTriple);
681 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
682 PointerTagShift = IsX86_64 ? 57 : 56;
683 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
687 "need more than 4 bits of tag to have non-short-granule tags");
691 Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
693 C = &(
M.getContext());
696 HwasanCtorFunction =
nullptr;
717 }
else if (CompileKernel) {
720 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
726 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
728 if (!CompileKernel) {
729 if (InstrumentGlobals)
732 createHwasanCtorComdat();
734 bool InstrumentPersonalityFunctions =
736 if (InstrumentPersonalityFunctions)
737 instrumentPersonalityFunctions();
741 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
744 "__hwasan_tls",
nullptr,
752void HWAddressSanitizer::initializeCallbacks(
Module &M) {
754 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
756 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
758 if (UseMatchAllCallback) {
759 HwasanMemoryAccessCallbackSizedFnTy =
761 HwasanMemoryAccessCallbackFnTy =
763 HwasanMemTransferFnTy =
768 HwasanMemoryAccessCallbackSizedFnTy =
770 HwasanMemoryAccessCallbackFnTy =
772 HwasanMemTransferFnTy =
778 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
779 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
780 const std::string EndingStr = Recover ?
"_noabort" :
"";
782 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
784 HwasanMemoryAccessCallbackSizedFnTy);
788 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
790 itostr(1ULL << AccessSizeIndex) +
791 MatchAllStr + EndingStr,
792 HwasanMemoryAccessCallbackFnTy);
796 const std::string MemIntrinCallbackPrefix =
801 HwasanMemmove =
M.getOrInsertFunction(
802 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
803 HwasanMemcpy =
M.getOrInsertFunction(
804 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
805 HwasanMemset =
M.getOrInsertFunction(
806 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
808 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
809 PtrTy, Int8Ty, IntptrTy);
810 HwasanGenerateTagFunc =
811 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
813 HwasanRecordFrameRecordFunc =
814 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
820 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
832 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
836 return getOpaqueNoopCast(IRB, ShadowGlobal);
840 if (Mapping.isFixed()) {
841 return getOpaqueNoopCast(
843 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
846 if (Mapping.isInIfunc())
847 return getDynamicShadowIfunc(IRB);
849 Value *GlobalDynamicAddress =
852 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
855bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
871 if (!InstrumentStack)
878 if (!InstrumentGlobals)
888 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
900void HWAddressSanitizer::getInterestingMemoryOperands(
905 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
915 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
916 LI->getType(), LI->getAlign());
921 SI->getValueOperand()->getType(),
SI->getAlign());
925 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
926 RMW->getValOperand()->getType(), std::nullopt);
930 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
931 XCHG->getCompareOperand()->getType(),
934 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
936 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
938 Type *Ty = CI->getParamByValType(ArgNo);
947 return LI->getPointerOperandIndex();
949 return SI->getPointerOperandIndex();
951 return RMW->getPointerOperandIndex();
953 return XCHG->getPointerOperandIndex();
979 if (Mapping.isFixed() && Mapping.offset() == 0)
985int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
986 unsigned AccessSizeIndex) {
995HWAddressSanitizer::ShadowTagCheckInfo
996HWAddressSanitizer::insertShadowTagCheck(
Value *Ptr,
Instruction *InsertBefore,
998 ShadowTagCheckInfo
R;
1005 R.AddrLong = untagPointer(IRB,
R.PtrLong);
1006 Value *Shadow = memToShadow(
R.AddrLong, IRB);
1010 if (MatchAllTag.has_value()) {
1012 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
1013 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
1017 TagMismatch, InsertBefore,
false,
1023void HWAddressSanitizer::instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
1024 unsigned AccessSizeIndex,
1029 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1033 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
1036 bool UseFixedShadowIntrinsic =
false;
1044 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
1045 uint16_t OffsetShifted = Mapping.offset() >> 32;
1046 UseFixedShadowIntrinsic =
1047 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
1050 if (UseFixedShadowIntrinsic) {
1053 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
1054 : Intrinsic::hwasan_check_memaccess_fixedshadow,
1055 {Ptr, ConstantInt::get(Int32Ty, AccessInfo),
1056 ConstantInt::get(Int64Ty, Mapping.offset())});
1059 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
1060 : Intrinsic::hwasan_check_memaccess,
1061 {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
1065void HWAddressSanitizer::instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
1066 unsigned AccessSizeIndex,
1071 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1073 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
1076 Value *OutOfShortGranuleTagRange =
1077 IRB.
CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
1079 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1085 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1102 switch (TargetTriple.
getArch()) {
1126 "ebreak\naddiw x0, x11, " +
1151void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1155 MI->getOperand(0),
MI->getOperand(1),
1158 if (UseMatchAllCallback)
1159 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1166 if (UseMatchAllCallback)
1167 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1170 MI->eraseFromParent();
1176 Value *Addr =
O.getPtr();
1195 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1197 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1198 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1200 if (InstrumentWithCalls) {
1202 if (UseMatchAllCallback)
1203 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1204 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1206 }
else if (OutlinedChecks) {
1207 instrumentMemAccessOutline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1210 instrumentMemAccessInline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1217 ConstantInt::get(IntptrTy, 8))};
1218 if (UseMatchAllCallback)
1219 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1220 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1222 untagPointerOperand(
O.getInsn(), Addr);
1229 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1230 if (!UseShortGranules)
1234 if (InstrumentWithCalls) {
1237 ConstantInt::get(IntptrTy, AlignedSize)});
1239 size_t ShadowSize =
Size >> Mapping.scale();
1241 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1250 if (
Size != AlignedSize) {
1251 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1252 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1261unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1263 return AllocaNo & TagMaskByte;
1275 static const unsigned FastMasks[] = {
1276 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1277 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1278 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1279 return FastMasks[AllocaNo % std::size(FastMasks)];
1283 if (TagMaskByte == 0xFF)
1286 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1297 return StackBaseTag;
1301 Value *FramePointerLong = getCachedFP(IRB);
1303 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1305 StackTag->
setName(
"hwasan.stack.base.tag");
1310 unsigned AllocaNo) {
1312 return getNextTagWithCall(IRB);
1314 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1318 Value *FramePointerLong = getCachedFP(IRB);
1320 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1322 UARTag->
setName(
"hwasan.uar.tag");
1330 Value *TaggedPtrLong;
1331 if (CompileKernel) {
1335 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1336 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1340 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1348 Value *UntaggedPtrLong;
1349 if (CompileKernel) {
1353 TagMaskByte << PointerTagShift));
1357 PtrLong, ConstantInt::get(PtrLong->
getType(),
1358 ~(TagMaskByte << PointerTagShift)));
1360 return UntaggedPtrLong;
1366 constexpr int SanitizerSlot = 6;
1369 return ThreadPtrGlobal;
1396void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1397 if (!Mapping.isInTls())
1398 ShadowBase = getShadowNonTls(IRB);
1399 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1400 ShadowBase = getDynamicShadowIfunc(IRB);
1402 if (!WithFrameRecord && ShadowBase)
1405 Value *SlotPtr =
nullptr;
1406 Value *ThreadLong =
nullptr;
1407 Value *ThreadLongMaybeUntagged =
nullptr;
1409 auto getThreadLongMaybeUntagged = [&]() {
1411 SlotPtr = getHwasanThreadSlotPtr(IRB);
1413 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1416 return TargetTriple.
isAArch64() ? ThreadLong
1417 : untagPointer(IRB, ThreadLong);
1420 if (WithFrameRecord) {
1425 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1426 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1430 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1432 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1435 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1445 "A stack history recording mode should've been selected.");
1451 if (!ThreadLongMaybeUntagged)
1452 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1459 ThreadLongMaybeUntagged,
1461 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1466void HWAddressSanitizer::instrumentLandingPads(
1468 for (
auto *LP : LandingPadVec) {
1492 auto *AI = KV.first;
1497 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1499 Value *AINoTagLong = untagPointer(IRB, AILong);
1500 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1503 Replacement->
setName(Name +
".hwasan");
1506 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1509 auto *
User =
U.getUser();
1515 auto TagStarts = [&]() {
1518 tagAlloca(IRB, AI,
Tag,
Size);
1527 tagAlloca(IRB, AI, UARTag, AlignedSize);
1529 auto EraseLifetimes = [&]() {
1530 for (
auto &
II :
Info.LifetimeStart)
1531 II->eraseFromParent();
1532 for (
auto &
II :
Info.LifetimeEnd)
1533 II->eraseFromParent();
1552 tagAlloca(IRB, AI,
Tag,
Size);
1558 tagAlloca(IRB, AI,
Tag,
Size);
1571 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1576 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1581bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1583 auto SkipHot = [&]() {
1589 if (!PSI || !PSI->hasProfileSummary()) {
1590 ++NumNoProfileSummaryFuncs;
1593 return PSI->isFunctionHotInCallGraphNthPercentile(
1597 auto SkipRandom = [&]() {
1604 bool Skip = SkipRandom() || SkipHot();
1609void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1611 if (&
F == HwasanCtorFunction)
1615 if (
F.hasFnAttribute(Attribute::Naked))
1618 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1624 if (
F.isPresplitCoroutine())
1632 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1635 NumInstrumentedFuncs++;
1646 if (InstrumentStack) {
1647 SIB.visit(ORE, Inst);
1656 if (!ignoreMemIntrinsic(ORE,
MI))
1662 initializeCallbacks(*
F.getParent());
1664 if (!LandingPadVec.
empty())
1665 instrumentLandingPads(LandingPadVec);
1671 F.setPersonalityFn(
nullptr);
1675 IntrinToInstrument.
empty())
1682 emitPrologue(EntryIRB,
1684 Mapping.withFrameRecord() &&
1691 Value *StackTag = getStackBaseTag(EntryIRB);
1692 Value *UARTag = getUARTag(EntryIRB);
1693 instrumentStack(ORE, SInfo, StackTag, UARTag, DT, PDT, LI);
1699 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1700 InsertPt =
F.getEntryBlock().begin();
1705 I.moveBefore(
F.getEntryBlock(), InsertPt);
1712 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1714 for (
auto &Operand : OperandsToInstrument)
1715 instrumentMemAccess(Operand, DTU, LI,
DL);
1719 for (
auto *Inst : IntrinToInstrument)
1720 instrumentMemIntrinsic(Inst);
1723 ShadowBase =
nullptr;
1724 StackBaseTag =
nullptr;
1732 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1733 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1734 if (SizeInBytes != NewSize) {
1737 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1746 NewGV->copyAttributesFrom(GV);
1748 NewGV->copyMetadata(GV, 0);
1749 NewGV->setAlignment(
1769 const uint64_t MaxDescriptorSize = 0xfffff0;
1770 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1771 DescriptorPos += MaxDescriptorSize) {
1774 nullptr, GV->
getName() +
".hwasan.descriptor");
1780 ConstantInt::get(Int64Ty, DescriptorPos)),
1782 uint32_t
Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1783 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (uint32_t(
Tag) << 24));
1784 Descriptor->setComdat(NewGV->getComdat());
1786 Descriptor->setSection(
"hwasan_globals");
1787 Descriptor->setMetadata(LLVMContext::MD_associated,
1795 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1800 Alias->takeName(GV);
1805void HWAddressSanitizer::instrumentGlobals() {
1806 std::vector<GlobalVariable *> Globals;
1831 Globals.push_back(&GV);
1835 Hasher.
update(
M.getSourceFileName());
1838 uint8_t
Tag = Hash[0];
1840 assert(TagMaskByte >= 16);
1848 instrumentGlobal(GV,
Tag++);
1852void HWAddressSanitizer::instrumentPersonalityFunctions() {
1861 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1864 if (
F.hasPersonalityFn()) {
1865 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1866 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1867 PersonalityFns[
nullptr].push_back(&
F);
1871 if (PersonalityFns.
empty())
1875 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1876 PtrTy, PtrTy, PtrTy, PtrTy);
1877 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1878 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1880 for (
auto &
P : PersonalityFns) {
1883 ThunkName += (
"." +
P.first->getName()).str();
1885 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1894 return F->hasFnAttribute(
"branch-target-enforcement");
1896 ThunkFn->addFnAttr(
"branch-target-enforcement");
1900 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1906 HwasanPersonalityWrapper,
1907 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1908 ThunkFn->getArg(3), ThunkFn->getArg(4),
1915 F->setPersonalityFn(ThunkFn);
1919void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1920 bool InstrumentWithCalls,
1921 bool CompileKernel) {
1924 Kind = OffsetKind::kTls;
1925 WithFrameRecord =
true;
1931 Kind = OffsetKind::kGlobal;
1932 }
else if (CompileKernel || InstrumentWithCalls) {
1934 WithFrameRecord =
false;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::desc("Use Stack Safety analysis results"))
static cl::opt< StackTaggingRecordStackHistoryMode > ClRecordStackHistory("stack-tagging-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer")), cl::Hidden, cl::init(none))
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const uint64_t kDefaultShadowScale
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentByval("asan-instrument-byval", cl::desc("instrument byval call arguments"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClUseAfterScope("asan-use-after-scope", cl::desc("Check stack-use-after-scope"), cl::Hidden, cl::init(false))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("asan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
static cl::opt< uint64_t > ClMappingOffset("asan-mapping-offset", cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define clEnumVal(ENUMVAL, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
static cl::opt< bool > ClInstrumentWrites("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden)
static cl::opt< RecordStackHistoryMode > ClRecordStackHistory("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr))
const char kHwasanModuleCtorName[]
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 cl::opt< uint64_t > ClTagBits("hwasan-tag-bits", cl::desc("Restrict tag to at most N bits. Needs to be > 4."), cl::Hidden, cl::init(0))
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 > 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< bool > ClStrictUseAfterScope("hwasan-strict-use-after-scope", cl::desc("for complicated lifetimes, tag both on end and return"), 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< 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."))
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))
static cl::opt< bool > ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"))
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))
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.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::iterator iterator
Instruction iterators...
Analysis pass which computes BlockFrequencyInfo.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCall(bool IsTc=true)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static LLVM_ABI Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static LLVM_ABI Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
This is an important base class in LLVM.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void flush()
Apply all pending updates to available trees and flush all BasicBlocks awaiting deletion.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
StringRef getSection() const
Get the custom section of this global if it has one.
LLVM_ABI void setComdat(Comdat *C)
bool hasSection() const
Check if this global has a custom object file section.
LLVM_ABI const SanitizerMetadata & getSanitizerMetadata() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
LinkageTypes getLinkage() const
bool isDeclarationForLinker() const
bool hasSanitizerMetadata() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
bool hasCommonLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
MaybeAlign getAlign() const
Returns the alignment of the given variable.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
LLVM_ABI void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Analysis pass providing a never-invalidated alias analysis result.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
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="")
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="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
LLVM_ABI bool stackAccessIsSafe(const Instruction &I) const
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
bool isAndroidVersionLT(unsigned Major) const
bool isAndroid() const
Tests whether the target is Android.
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI bool isSwiftError() const
Return true if this value is a swifterror value.
LLVM_ABI bool 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 Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)
Get all the memory operands from the instruction that needs to be instrumented.
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)
LLVM_ABI Value * getFP(IRBuilder<> &IRB)
LLVM_ABI void forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
LLVM_ABI bool isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, const LoopInfo *LI)
LLVM_ABI uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
LLVM_ABI Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
LLVM_ABI Value * readRegister(IRBuilder<> &IRB, StringRef Name)
LLVM_ABI void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
LLVM_ABI void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
LLVM_ABI Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
LLVM_ABI Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc, bool IsMemtagDarwin=false)
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
@ Known
Known to have no common set bits.
LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=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...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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 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)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
LLVM_ABI void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem)
Remove memory attributes that are incompatible with the instrumentation added by AddressSanitizer and...
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
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.
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 8 > RetVec