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-strict-use-after-scope",
157 cl::desc(
"for complicated lifetimes, tag both on end and return"),
161 "hwasan-generate-tags-with-calls",
169 "hwasan-all-globals",
171 "Instrument globals, even those within user-defined sections. Warning: "
172 "This may break existing code which walks globals via linker-generated "
173 "symbols, expects certain globals to be contiguous with each other, or "
174 "makes other assumptions which are invalidated by HWASan "
179 "hwasan-match-all-tag",
180 cl::desc(
"don't report bad accesses via pointers with this tag"),
185 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
194 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
198 "hwasan-mapping-offset-dynamic",
201 clEnumValN(OffsetKind::kIfunc,
"ifunc",
"Use ifunc global"),
202 clEnumValN(OffsetKind::kTls,
"tls",
"Use TLS")));
206 cl::desc(
"Use ring buffer for stack allocations"),
210 cl::desc(
"Hot percentile cutoff."));
214 cl::desc(
"Probability value in the range [0.0, 1.0] "
215 "to keep instrumentation of a function. "
216 "Note: instrumentation can be skipped randomly "
217 "OR because of the hot percentile cutoff, if "
218 "both are supplied."));
221 "hwasan-static-linking",
222 cl::desc(
"Don't use .note.hwasan.globals section to instrument globals "
223 "from loadable libraries. "
224 "Note: in static binaries, the global variables section can be "
225 "accessed directly via linker-provided "
226 "__start_hwasan_globals and __stop_hwasan_globals symbols"),
230STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
231STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
248 "hwasan-record-stack-history",
249 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
253 "storing into the stack ring buffer directly"),
255 "storing into the stack ring buffer")),
260 cl::desc(
"instrument memory intrinsics"),
269 "hwasan-use-short-granules",
274 "hwasan-instrument-personality-functions",
287 cl::desc(
"Use page aliasing in HWASan"),
296bool shouldUsePageAliases(
const Triple &TargetTriple) {
300bool shouldInstrumentStack(
const Triple &TargetTriple) {
304bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
308bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
312bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
313 bool DisableOptimization) {
314 return shouldInstrumentStack(TargetTriple) &&
315 mightUseStackSafetyAnalysis(DisableOptimization);
318bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
324class HWAddressSanitizer {
326 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
327 const StackSafetyGlobalInfo *SSI)
329 this->Recover = optOr(
ClRecover, Recover);
340 struct ShadowTagCheckInfo {
342 Value *PtrLong =
nullptr;
343 Value *AddrLong =
nullptr;
344 Value *PtrTag =
nullptr;
345 Value *MemTag =
nullptr;
348 bool selectiveInstrumentationShouldSkip(Function &
F,
350 void initializeModule();
351 void createHwasanCtorComdat();
352 void createHwasanNote();
354 void initializeCallbacks(
Module &M);
361 void untagPointerOperand(Instruction *
I,
Value *Addr);
364 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
365 ShadowTagCheckInfo insertShadowTagCheck(
Value *Ptr, Instruction *InsertBefore,
366 DomTreeUpdater &DTU, LoopInfo *LI);
367 void instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
368 unsigned AccessSizeIndex,
369 Instruction *InsertBefore,
370 DomTreeUpdater &DTU, LoopInfo *LI);
371 void instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
372 unsigned AccessSizeIndex,
373 Instruction *InsertBefore, DomTreeUpdater &DTU,
375 bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *
MI);
376 void instrumentMemIntrinsic(MemIntrinsic *
MI);
377 bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
378 LoopInfo *LI,
const DataLayout &
DL);
379 bool ignoreAccessWithoutRemark(Instruction *Inst,
Value *Ptr);
380 bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
384 OptimizationRemarkEmitter &ORE, Instruction *
I,
385 const TargetLibraryInfo &TLI,
386 SmallVectorImpl<InterestingMemoryOperand> &Interesting);
391 void instrumentStack(memtag::StackInfo &Info,
Value *StackTag,
Value *UARTag,
392 const DominatorTree &DT,
const PostDominatorTree &PDT,
394 void instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
402 unsigned retagMask(
unsigned AllocaNo);
404 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
406 void instrumentGlobal(GlobalVariable *GV, uint8_t
Tag);
407 void instrumentGlobals();
412 void instrumentPersonalityFunctions();
416 const StackSafetyGlobalInfo *SSI;
418 std::unique_ptr<RandomNumberGenerator> Rng;
435 class ShadowMapping {
439 bool WithFrameRecord;
441 void SetFixed(uint64_t O) {
442 Kind = OffsetKind::kFixed;
447 void init(Triple &TargetTriple,
bool InstrumentWithCalls,
449 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
450 bool isInGlobal()
const {
return Kind == OffsetKind::kGlobal; }
451 bool isInIfunc()
const {
return Kind == OffsetKind::kIfunc; }
452 bool isInTls()
const {
return Kind == OffsetKind::kTls; }
453 bool isFixed()
const {
return Kind == OffsetKind::kFixed; }
454 uint8_t
scale()
const {
return Scale; };
455 uint64_t offset()
const {
459 bool withFrameRecord()
const {
return WithFrameRecord; };
462 ShadowMapping Mapping;
464 Type *VoidTy = Type::getVoidTy(M.getContext());
465 Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());
466 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
467 Type *Int8Ty = Type::getInt8Ty(M.getContext());
468 Type *Int32Ty = Type::getInt32Ty(M.getContext());
469 Type *Int64Ty = Type::getInt64Ty(M.getContext());
475 bool UseShortGranules;
476 bool InstrumentLandingPads;
477 bool InstrumentWithCalls;
478 bool InstrumentStack;
479 bool InstrumentGlobals;
480 bool DetectUseAfterScope;
482 bool UseMatchAllCallback;
484 std::optional<uint8_t> MatchAllTag;
486 unsigned PointerTagShift;
487 uint64_t TagMaskByte;
492 FunctionCallee HwasanMemoryAccessCallbackSized[2];
494 FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;
495 FunctionCallee HwasanHandleVfork;
497 FunctionCallee HwasanTagMemoryFunc;
498 FunctionCallee HwasanGenerateTagFunc;
499 FunctionCallee HwasanRecordFrameRecordFunc;
503 Value *ShadowBase =
nullptr;
504 Value *StackBaseTag =
nullptr;
505 Value *CachedFP =
nullptr;
506 GlobalValue *ThreadPtrGlobal =
nullptr;
517 const Triple &TargetTriple = M.getTargetTriple();
518 if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
521 HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);
524 HWASan.sanitizeFunction(
F,
FAM);
542 OS, MapClassName2PassName);
544 if (Options.CompileKernel)
551void HWAddressSanitizer::createHwasanNote() {
588 nullptr,
"__start_hwasan_globals");
592 nullptr,
"__stop_hwasan_globals");
604 Note->setSection(
".note.hwasan.globals");
605 Note->setComdat(NoteComdat);
610 auto CreateRelPtr = [&](
Constant *Ptr) {
620 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
628 Dummy->setSection(
"hwasan_globals");
629 Dummy->setComdat(NoteComdat);
630 Dummy->setMetadata(LLVMContext::MD_associated,
635void HWAddressSanitizer::createHwasanCtorComdat() {
636 std::tie(HwasanCtorFunction, std::ignore) =
661void HWAddressSanitizer::initializeModule() {
663 TargetTriple =
M.getTargetTriple();
674 UsePageAliases = shouldUsePageAliases(TargetTriple);
675 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
676 InstrumentStack = shouldInstrumentStack(TargetTriple);
677 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
678 PointerTagShift = IsX86_64 ? 57 : 56;
679 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
681 Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
683 C = &(
M.getContext());
686 HwasanCtorFunction =
nullptr;
707 }
else if (CompileKernel) {
710 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
716 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
718 if (!CompileKernel) {
719 if (InstrumentGlobals)
722 createHwasanCtorComdat();
724 bool InstrumentPersonalityFunctions =
726 if (InstrumentPersonalityFunctions)
727 instrumentPersonalityFunctions();
731 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
734 "__hwasan_tls",
nullptr,
742void HWAddressSanitizer::initializeCallbacks(
Module &M) {
744 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
746 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
748 if (UseMatchAllCallback) {
749 HwasanMemoryAccessCallbackSizedFnTy =
751 HwasanMemoryAccessCallbackFnTy =
753 HwasanMemTransferFnTy =
758 HwasanMemoryAccessCallbackSizedFnTy =
760 HwasanMemoryAccessCallbackFnTy =
762 HwasanMemTransferFnTy =
768 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
769 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
770 const std::string EndingStr = Recover ?
"_noabort" :
"";
772 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
774 HwasanMemoryAccessCallbackSizedFnTy);
778 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
780 itostr(1ULL << AccessSizeIndex) +
781 MatchAllStr + EndingStr,
782 HwasanMemoryAccessCallbackFnTy);
786 const std::string MemIntrinCallbackPrefix =
791 HwasanMemmove =
M.getOrInsertFunction(
792 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
793 HwasanMemcpy =
M.getOrInsertFunction(
794 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
795 HwasanMemset =
M.getOrInsertFunction(
796 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
798 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
799 PtrTy, Int8Ty, IntptrTy);
800 HwasanGenerateTagFunc =
801 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
803 HwasanRecordFrameRecordFunc =
804 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
810 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
822 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
826 return getOpaqueNoopCast(IRB, ShadowGlobal);
830 if (Mapping.isFixed()) {
831 return getOpaqueNoopCast(
833 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
836 if (Mapping.isInIfunc())
837 return getDynamicShadowIfunc(IRB);
839 Value *GlobalDynamicAddress =
842 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
845bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
861 if (!InstrumentStack)
868 if (!InstrumentGlobals)
878 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
890void HWAddressSanitizer::getInterestingMemoryOperands(
895 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
905 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
906 LI->getType(), LI->getAlign());
911 SI->getValueOperand()->getType(),
SI->getAlign());
915 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
916 RMW->getValOperand()->getType(), std::nullopt);
920 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
921 XCHG->getCompareOperand()->getType(),
924 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
926 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
928 Type *Ty = CI->getParamByValType(ArgNo);
937 return LI->getPointerOperandIndex();
939 return SI->getPointerOperandIndex();
941 return RMW->getPointerOperandIndex();
943 return XCHG->getPointerOperandIndex();
969 if (Mapping.isFixed() && Mapping.offset() == 0)
975int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
976 unsigned AccessSizeIndex) {
985HWAddressSanitizer::ShadowTagCheckInfo
986HWAddressSanitizer::insertShadowTagCheck(
Value *Ptr,
Instruction *InsertBefore,
988 ShadowTagCheckInfo
R;
995 R.AddrLong = untagPointer(IRB,
R.PtrLong);
996 Value *Shadow = memToShadow(
R.AddrLong, IRB);
1000 if (MatchAllTag.has_value()) {
1002 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
1003 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
1007 TagMismatch, InsertBefore,
false,
1013void HWAddressSanitizer::instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
1014 unsigned AccessSizeIndex,
1019 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1023 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
1026 bool UseFixedShadowIntrinsic =
false;
1034 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
1035 uint16_t OffsetShifted = Mapping.offset() >> 32;
1036 UseFixedShadowIntrinsic =
1037 static_cast<uint64_t
>(OffsetShifted) << 32 == Mapping.offset();
1040 if (UseFixedShadowIntrinsic) {
1043 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
1044 : Intrinsic::hwasan_check_memaccess_fixedshadow,
1045 {Ptr, ConstantInt::get(
Int32Ty, AccessInfo),
1046 ConstantInt::get(Int64Ty, Mapping.offset())});
1049 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
1050 : Intrinsic::hwasan_check_memaccess,
1051 {ShadowBase, Ptr, ConstantInt::get(
Int32Ty, AccessInfo)});
1055void HWAddressSanitizer::instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
1056 unsigned AccessSizeIndex,
1061 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1063 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
1066 Value *OutOfShortGranuleTagRange =
1067 IRB.
CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
1069 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1075 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1092 switch (TargetTriple.
getArch()) {
1116 "ebreak\naddiw x0, x11, " +
1141void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1145 MI->getOperand(0),
MI->getOperand(1),
1148 if (UseMatchAllCallback)
1149 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1156 if (UseMatchAllCallback)
1157 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1160 MI->eraseFromParent();
1166 Value *Addr =
O.getPtr();
1185 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1187 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1188 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1190 if (InstrumentWithCalls) {
1192 if (UseMatchAllCallback)
1193 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1194 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1196 }
else if (OutlinedChecks) {
1197 instrumentMemAccessOutline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1200 instrumentMemAccessInline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1207 ConstantInt::get(IntptrTy, 8))};
1208 if (UseMatchAllCallback)
1209 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1210 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1212 untagPointerOperand(
O.getInsn(), Addr);
1219 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1220 if (!UseShortGranules)
1224 if (InstrumentWithCalls) {
1227 ConstantInt::get(IntptrTy, AlignedSize)});
1229 size_t ShadowSize =
Size >> Mapping.scale();
1231 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1240 if (
Size != AlignedSize) {
1241 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1242 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1251unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1253 return AllocaNo & TagMaskByte;
1265 static const unsigned FastMasks[] = {
1266 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1267 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1268 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1269 return FastMasks[AllocaNo % std::size(FastMasks)];
1273 if (TagMaskByte == 0xFF)
1276 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1287 return StackBaseTag;
1291 Value *FramePointerLong = getCachedFP(IRB);
1293 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1295 StackTag->
setName(
"hwasan.stack.base.tag");
1300 unsigned AllocaNo) {
1302 return getNextTagWithCall(IRB);
1304 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1308 Value *FramePointerLong = getCachedFP(IRB);
1310 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1312 UARTag->
setName(
"hwasan.uar.tag");
1320 Value *TaggedPtrLong;
1321 if (CompileKernel) {
1325 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1326 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1330 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1338 Value *UntaggedPtrLong;
1339 if (CompileKernel) {
1343 TagMaskByte << PointerTagShift));
1347 PtrLong, ConstantInt::get(PtrLong->
getType(),
1348 ~(TagMaskByte << PointerTagShift)));
1350 return UntaggedPtrLong;
1356 constexpr int SanitizerSlot = 6;
1359 return ThreadPtrGlobal;
1386void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1387 if (!Mapping.isInTls())
1388 ShadowBase = getShadowNonTls(IRB);
1389 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1390 ShadowBase = getDynamicShadowIfunc(IRB);
1392 if (!WithFrameRecord && ShadowBase)
1395 Value *SlotPtr =
nullptr;
1396 Value *ThreadLong =
nullptr;
1397 Value *ThreadLongMaybeUntagged =
nullptr;
1399 auto getThreadLongMaybeUntagged = [&]() {
1401 SlotPtr = getHwasanThreadSlotPtr(IRB);
1403 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1406 return TargetTriple.
isAArch64() ? ThreadLong
1407 : untagPointer(IRB, ThreadLong);
1410 if (WithFrameRecord) {
1415 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1416 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1420 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1422 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1425 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1435 "A stack history recording mode should've been selected.");
1441 if (!ThreadLongMaybeUntagged)
1442 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1449 ThreadLongMaybeUntagged,
1451 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1456void HWAddressSanitizer::instrumentLandingPads(
1458 for (
auto *LP : LandingPadVec) {
1481 auto *AI = KV.first;
1486 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1488 Value *AINoTagLong = untagPointer(IRB, AILong);
1489 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1492 Replacement->
setName(Name +
".hwasan");
1495 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1498 auto *
User =
U.getUser();
1504 auto TagStarts = [&]() {
1507 tagAlloca(IRB, AI,
Tag,
Size);
1516 tagAlloca(IRB, AI, UARTag, AlignedSize);
1518 auto EraseLifetimes = [&]() {
1519 for (
auto &
II :
Info.LifetimeStart)
1520 II->eraseFromParent();
1521 for (
auto &
II :
Info.LifetimeEnd)
1522 II->eraseFromParent();
1533 for (
auto *End :
Info.LifetimeEnd)
1534 End->eraseFromParent();
1538 tagAlloca(IRB, AI,
Tag,
Size);
1544 tagAlloca(IRB, AI,
Tag,
Size);
1557 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1562 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1567bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1569 auto SkipHot = [&]() {
1575 if (!PSI || !PSI->hasProfileSummary()) {
1576 ++NumNoProfileSummaryFuncs;
1579 return PSI->isFunctionHotInCallGraphNthPercentile(
1583 auto SkipRandom = [&]() {
1590 bool Skip = SkipRandom() || SkipHot();
1595void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1597 if (&
F == HwasanCtorFunction)
1601 if (
F.hasFnAttribute(Attribute::Naked))
1604 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1610 if (
F.isPresplitCoroutine())
1618 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1621 NumInstrumentedFuncs++;
1632 if (InstrumentStack) {
1633 SIB.visit(ORE, Inst);
1642 if (!ignoreMemIntrinsic(ORE,
MI))
1648 initializeCallbacks(*
F.getParent());
1650 if (!LandingPadVec.
empty())
1651 instrumentLandingPads(LandingPadVec);
1657 F.setPersonalityFn(
nullptr);
1661 IntrinToInstrument.
empty())
1668 emitPrologue(EntryIRB,
1670 Mapping.withFrameRecord() &&
1677 Value *StackTag = getStackBaseTag(EntryIRB);
1678 Value *UARTag = getUARTag(EntryIRB);
1679 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
1685 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1686 InsertPt =
F.getEntryBlock().begin();
1691 I.moveBefore(
F.getEntryBlock(), InsertPt);
1698 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1700 for (
auto &Operand : OperandsToInstrument)
1701 instrumentMemAccess(Operand, DTU, LI,
DL);
1705 for (
auto *Inst : IntrinToInstrument)
1706 instrumentMemIntrinsic(Inst);
1709 ShadowBase =
nullptr;
1710 StackBaseTag =
nullptr;
1717 uint64_t SizeInBytes =
1718 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1719 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1720 if (SizeInBytes != NewSize) {
1723 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1732 NewGV->copyAttributesFrom(GV);
1734 NewGV->copyMetadata(GV, 0);
1735 NewGV->setAlignment(
1755 const uint64_t MaxDescriptorSize = 0xfffff0;
1756 for (uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1757 DescriptorPos += MaxDescriptorSize) {
1760 nullptr, GV->
getName() +
".hwasan.descriptor");
1766 ConstantInt::get(Int64Ty, DescriptorPos)),
1768 uint32_t
Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1769 auto *SizeAndTag = ConstantInt::get(
Int32Ty,
Size | (uint32_t(
Tag) << 24));
1770 Descriptor->setComdat(NewGV->getComdat());
1772 Descriptor->setSection(
"hwasan_globals");
1773 Descriptor->setMetadata(LLVMContext::MD_associated,
1781 ConstantInt::get(Int64Ty, uint64_t(
Tag) << PointerTagShift)),
1786 Alias->takeName(GV);
1791void HWAddressSanitizer::instrumentGlobals() {
1792 std::vector<GlobalVariable *> Globals;
1817 Globals.push_back(&GV);
1821 Hasher.
update(
M.getSourceFileName());
1824 uint8_t
Tag = Hash[0];
1826 assert(TagMaskByte >= 16);
1834 instrumentGlobal(GV,
Tag++);
1838void HWAddressSanitizer::instrumentPersonalityFunctions() {
1847 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1850 if (
F.hasPersonalityFn()) {
1851 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1852 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1853 PersonalityFns[
nullptr].push_back(&
F);
1857 if (PersonalityFns.
empty())
1862 PtrTy, PtrTy, PtrTy, PtrTy);
1863 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1864 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1866 for (
auto &
P : PersonalityFns) {
1869 ThunkName += (
"." +
P.first->getName()).str();
1880 return F->hasFnAttribute(
"branch-target-enforcement");
1882 ThunkFn->addFnAttr(
"branch-target-enforcement");
1886 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1892 HwasanPersonalityWrapper,
1893 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1894 ThunkFn->getArg(3), ThunkFn->getArg(4),
1901 F->setPersonalityFn(ThunkFn);
1905void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1906 bool InstrumentWithCalls,
1907 bool CompileKernel) {
1910 Kind = OffsetKind::kTls;
1911 WithFrameRecord =
true;
1917 Kind = OffsetKind::kGlobal;
1918 }
else if (CompileKernel || InstrumentWithCalls) {
1920 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< 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 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< 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< 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.
Machine Check Debug Module
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="")
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.
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).
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.
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.
@ 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 isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, const LoopInfo *LI)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
Value * readRegister(IRBuilder<> &IRB, StringRef Name)
void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc, bool IsMemtagDarwin=false)
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
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.
FunctionAddr VTableAddr Value
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
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.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
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...
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.)
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)
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.
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.
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 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.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
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