61#define DEBUG_TYPE "hwasan"
69 "__hwasan_shadow_memory_dynamic_address";
76 std::numeric_limits<uint64_t>::max();
82 cl::desc(
"Prefix for memory access callbacks"),
86 "hwasan-kernel-mem-intrinsic-prefix",
91 "hwasan-instrument-with-calls",
96 cl::desc(
"instrument read instructions"),
105 "hwasan-instrument-atomics",
110 cl::desc(
"instrument byval arguments"),
115 cl::desc(
"Enable recovery mode (continue-after-error)."),
119 cl::desc(
"instrument stack (allocas)"),
130 cl::desc(
"How many lifetime ends to handle for a single alloca."),
135 cl::desc(
"detect use after scope within function"),
139 "hwasan-generate-tags-with-calls",
147 "hwasan-match-all-tag",
148 cl::desc(
"don't report bad accesses via pointers with this tag"),
153 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
162 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
167 cl::desc(
"Access dynamic shadow through an ifunc global on "
168 "platforms that support this"),
173 cl::desc(
"Access dynamic shadow through an thread-local pointer on "
174 "platforms that support this"),
192 "hwasan-record-stack-history",
193 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
197 "storing into the stack ring buffer directly"),
199 "storing into the stack ring buffer")),
204 cl::desc(
"instrument memory intrinsics"),
213 "hwasan-use-short-granules",
218 "hwasan-instrument-personality-functions",
231 cl::desc(
"Use page aliasing in HWASan"),
236bool shouldUsePageAliases(
const Triple &TargetTriple) {
240bool shouldInstrumentStack(
const Triple &TargetTriple) {
244bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
250bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
252 : !DisableOptimization;
255bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
256 bool DisableOptimization) {
257 return shouldInstrumentStack(TargetTriple) &&
258 mightUseStackSafetyAnalysis(DisableOptimization);
261bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
267class HWAddressSanitizer {
269 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
283 struct ShadowTagCheckInfo {
285 Value *PtrLong =
nullptr;
286 Value *AddrLong =
nullptr;
287 Value *PtrTag =
nullptr;
288 Value *MemTag =
nullptr;
292 void initializeModule();
293 void createHwasanCtorComdat();
295 void initializeCallbacks(
Module &M);
305 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
306 ShadowTagCheckInfo insertShadowTagCheck(
Value *
Ptr,
308 void instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
309 unsigned AccessSizeIndex,
311 void instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
312 unsigned AccessSizeIndex,
318 void getInterestingMemoryOperands(
336 unsigned retagMask(
unsigned AllocaNo);
338 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
341 void instrumentGlobals();
347 void instrumentPersonalityFunctions();
365 struct ShadowMapping {
370 bool WithFrameRecord;
372 void init(
Triple &TargetTriple,
bool InstrumentWithCalls);
373 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
376 ShadowMapping Mapping;
389 bool UseShortGranules;
390 bool InstrumentLandingPads;
391 bool InstrumentWithCalls;
392 bool InstrumentStack;
393 bool DetectUseAfterScope;
395 bool UseMatchAllCallback;
397 std::optional<uint8_t> MatchAllTag;
399 unsigned PointerTagShift;
416 Value *ShadowBase =
nullptr;
417 Value *StackBaseTag =
nullptr;
418 Value *CachedSP =
nullptr;
434 HWASan.sanitizeFunction(
F,
FAM);
446 OS, MapClassName2PassName);
455void HWAddressSanitizer::createHwasanCtorComdat() {
456 std::tie(HwasanCtorFunction, std::ignore) =
505 nullptr,
"__start_hwasan_globals");
509 nullptr,
"__stop_hwasan_globals");
521 Note->setSection(
".note.hwasan.globals");
522 Note->setComdat(NoteComdat);
537 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
545 Dummy->setSection(
"hwasan_globals");
546 Dummy->setComdat(NoteComdat);
547 Dummy->setMetadata(LLVMContext::MD_associated,
555void HWAddressSanitizer::initializeModule() {
557 auto &
DL =
M.getDataLayout();
559 TargetTriple =
Triple(
M.getTargetTriple());
565 UsePageAliases = shouldUsePageAliases(TargetTriple);
566 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
567 InstrumentStack = shouldInstrumentStack(TargetTriple);
568 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
569 PointerTagShift = IsX86_64 ? 57 : 56;
570 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
572 Mapping.init(TargetTriple, InstrumentWithCalls);
574 C = &(
M.getContext());
576 IntptrTy = IRB.getIntPtrTy(
DL);
577 Int8PtrTy = IRB.getInt8PtrTy();
578 Int8Ty = IRB.getInt8Ty();
581 HwasanCtorFunction =
nullptr;
607 }
else if (CompileKernel) {
610 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
617 if (!CompileKernel) {
618 createHwasanCtorComdat();
619 bool InstrumentGlobals =
622 if (InstrumentGlobals && !UsePageAliases)
625 bool InstrumentPersonalityFunctions =
629 if (InstrumentPersonalityFunctions)
630 instrumentPersonalityFunctions();
634 Constant *
C =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
637 "__hwasan_tls",
nullptr,
642 ThreadPtrGlobal = cast<GlobalVariable>(
C);
646void HWAddressSanitizer::initializeCallbacks(
Module &M) {
648 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
650 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
652 if (UseMatchAllCallback) {
653 HwasanMemoryAccessCallbackSizedFnTy =
655 HwasanMemoryAccessCallbackFnTy =
658 Int8PtrTy, {Int8PtrTy, Int8PtrTy, IntptrTy, Int8Ty},
false);
660 Int8PtrTy, {Int8PtrTy,
Int32Ty, IntptrTy, Int8Ty},
false);
662 HwasanMemoryAccessCallbackSizedFnTy =
664 HwasanMemoryAccessCallbackFnTy =
666 HwasanMemTransferFnTy =
672 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
673 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
674 const std::string EndingStr = Recover ?
"_noabort" :
"";
676 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
678 HwasanMemoryAccessCallbackSizedFnTy);
682 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
684 itostr(1ULL << AccessSizeIndex) +
685 MatchAllStr + EndingStr,
686 HwasanMemoryAccessCallbackFnTy);
690 const std::string MemIntrinCallbackPrefix =
695 HwasanMemmove =
M.getOrInsertFunction(
696 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
697 HwasanMemcpy =
M.getOrInsertFunction(
698 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
699 HwasanMemset =
M.getOrInsertFunction(
700 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
702 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
703 Int8PtrTy, Int8Ty, IntptrTy);
704 HwasanGenerateTagFunc =
705 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
707 HwasanRecordFrameRecordFunc =
708 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
714 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
726 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
730 return getOpaqueNoopCast(IRB, ShadowGlobal);
735 return getOpaqueNoopCast(
739 if (Mapping.InGlobal)
740 return getDynamicShadowIfunc(IRB);
742 Value *GlobalDynamicAddress =
745 return IRB.
CreateLoad(Int8PtrTy, GlobalDynamicAddress);
751 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
759 if (
Ptr->isSwiftError())
763 if (!InstrumentStack)
765 if (SSI && SSI->stackAccessIsSafe(*Inst))
771void HWAddressSanitizer::getInterestingMemoryOperands(
774 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
781 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
784 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
785 LI->getType(), LI->getAlign());
786 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
790 SI->getValueOperand()->getType(),
SI->getAlign());
794 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
795 RMW->getValOperand()->getType(), std::nullopt);
799 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
800 XCHG->getCompareOperand()->getType(),
802 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
803 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
805 ignoreAccess(
I, CI->getArgOperand(ArgNo)))
807 Type *Ty = CI->getParamByValType(ArgNo);
814 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
815 return LI->getPointerOperandIndex();
817 return SI->getPointerOperandIndex();
819 return RMW->getPointerOperandIndex();
821 return XCHG->getPointerOperandIndex();
847 if (Mapping.Offset == 0)
850 return IRB.
CreateGEP(Int8Ty, ShadowBase, Shadow);
853int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
854 unsigned AccessSizeIndex) {
863HWAddressSanitizer::ShadowTagCheckInfo
864HWAddressSanitizer::insertShadowTagCheck(
Value *
Ptr,
866 ShadowTagCheckInfo
R;
873 R.AddrLong = untagPointer(IRB,
R.PtrLong);
874 Value *Shadow = memToShadow(
R.AddrLong, IRB);
878 if (MatchAllTag.has_value()) {
881 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
891void HWAddressSanitizer::instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
892 unsigned AccessSizeIndex,
895 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
898 InsertBefore = insertShadowTagCheck(
Ptr, InsertBefore).TagMismatchTerm;
905 ? Intrinsic::hwasan_check_memaccess_shortgranules
906 : Intrinsic::hwasan_check_memaccess),
910void HWAddressSanitizer::instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
911 unsigned AccessSizeIndex,
914 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
916 ShadowTagCheckInfo TCI = insertShadowTagCheck(
Ptr, InsertBefore);
919 Value *OutOfShortGranuleTagRange =
922 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
947 switch (TargetTriple.
getArch()) {
971 "ebreak\naddiw x0, x11, " +
981 cast<BranchInst>(CheckFailTerm)
990 if (isa<MemSetInst>(
MI))
995void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
997 if (isa<MemTransferInst>(
MI)) {
1003 if (UseMatchAllCallback)
1005 IRB.
CreateCall(isa<MemMoveInst>(
MI) ? HwasanMemmove : HwasanMemcpy, Args);
1006 }
else if (isa<MemSetInst>(
MI)) {
1011 if (UseMatchAllCallback)
1015 MI->eraseFromParent();
1027 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1029 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1030 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1032 if (InstrumentWithCalls) {
1034 if (UseMatchAllCallback)
1036 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1038 }
else if (OutlinedChecks) {
1039 instrumentMemAccessOutline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn());
1041 instrumentMemAccessInline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn());
1048 if (UseMatchAllCallback)
1050 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1052 untagPointerOperand(
O.getInsn(),
Addr);
1059 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1060 if (!UseShortGranules)
1064 if (InstrumentWithCalls) {
1069 size_t ShadowSize =
Size >> Mapping.Scale;
1071 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1080 if (
Size != AlignedSize) {
1081 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1091unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1093 return AllocaNo & TagMaskByte;
1105 static const unsigned FastMasks[] = {
1106 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1107 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1108 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1109 return FastMasks[AllocaNo % std::size(FastMasks)];
1113 if (TagMaskByte == 0xFF)
1127 return StackBaseTag;
1131 Value *StackPointerLong = getSP(IRB);
1133 applyTagMask(IRB, IRB.
CreateXor(StackPointerLong,
1135 StackTag->
setName(
"hwasan.stack.base.tag");
1140 unsigned AllocaNo) {
1142 return getNextTagWithCall(IRB);
1148 Value *StackPointerLong = getSP(IRB);
1150 applyTagMask(IRB, IRB.
CreateLShr(StackPointerLong, PointerTagShift));
1152 UARTag->
setName(
"hwasan.uar.tag");
1160 Value *TaggedPtrLong;
1161 if (CompileKernel) {
1166 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1170 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1178 Value *UntaggedPtrLong;
1179 if (CompileKernel) {
1183 TagMaskByte << PointerTagShift));
1188 ~(TagMaskByte << PointerTagShift)));
1190 return UntaggedPtrLong;
1205 if (ThreadPtrGlobal)
1206 return ThreadPtrGlobal;
1213 return readRegister(IRB,
"pc");
1224 M, Intrinsic::frameaddress,
1227 IRB.
CreateCall(GetStackPointerFn, {Constant::getNullValue(Int32Ty)}),
1235 Value *PC = getPC(IRB);
1236 Value *SP = getSP(IRB);
1248void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1250 ShadowBase = getShadowNonTls(IRB);
1251 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1252 ShadowBase = getDynamicShadowIfunc(IRB);
1254 if (!WithFrameRecord && ShadowBase)
1257 Value *SlotPtr =
nullptr;
1258 Value *ThreadLong =
nullptr;
1259 Value *ThreadLongMaybeUntagged =
nullptr;
1261 auto getThreadLongMaybeUntagged = [&]() {
1263 SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
1265 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1268 return TargetTriple.
isAArch64() ? ThreadLong
1269 : untagPointer(IRB, ThreadLong);
1272 if (WithFrameRecord) {
1277 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1278 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1282 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1284 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1287 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1289 IntptrTy->getPointerTo(0));
1309 "A stack history recording mode should've been selected.");
1315 if (!ThreadLongMaybeUntagged)
1316 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1323 ThreadLongMaybeUntagged,
1339bool HWAddressSanitizer::instrumentLandingPads(
1341 for (
auto *LP : LandingPadVec) {
1352 auto *II = dyn_cast<IntrinsicInst>(V);
1353 return II && II->isLifetimeStartOrEnd();
1370 auto *AI = KV.first;
1375 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1377 Value *AINoTagLong = untagPointer(IRB, AILong);
1378 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1384 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1400 II->setArgOperand(1, AICast);
1406 auto *
User =
U.getUser();
1410 for (
auto *DDI :
Info.DbgVariableIntrinsics) {
1416 for (
size_t LocNo = 0; LocNo < DDI->getNumVariableLocationOps(); ++LocNo)
1417 if (DDI->getVariableLocationOp(LocNo) == AI)
1428 tagAlloca(IRB, AI, UARTag, AlignedSize);
1434 bool StandardLifetime =
1439 if (DetectUseAfterScope && StandardLifetime) {
1442 tagAlloca(IRB, AI,
Tag,
Size);
1445 for (
auto *
End :
Info.LifetimeEnd)
1446 End->eraseFromParent();
1449 tagAlloca(IRB, AI,
Tag,
Size);
1450 for (
auto *RI : SInfo.
RetVec)
1454 for (
auto &II :
Info.LifetimeStart)
1455 II->eraseFromParent();
1456 for (
auto &II :
Info.LifetimeEnd)
1457 II->eraseFromParent();
1462 I->eraseFromParent();
1466void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1468 if (&
F == HwasanCtorFunction)
1471 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1482 if (InstrumentStack) {
1486 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1489 getInterestingMemoryOperands(&Inst, OperandsToInstrument);
1492 if (!ignoreMemIntrinsic(
MI))
1498 initializeCallbacks(*
F.getParent());
1500 if (!LandingPadVec.
empty())
1501 instrumentLandingPads(LandingPadVec);
1507 F.setPersonalityFn(
nullptr);
1511 IntrinToInstrument.
empty())
1518 emitPrologue(EntryIRB,
1520 Mapping.WithFrameRecord &&
1527 Value *StackTag = getStackBaseTag(EntryIRB);
1528 Value *UARTag = getUARTag(EntryIRB);
1529 instrumentStack(SInfo, StackTag, UARTag, DT, PDT, LI);
1535 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1536 InsertPt = &*
F.getEntryBlock().begin();
1539 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
1541 I.moveBefore(InsertPt);
1545 for (
auto &Operand : OperandsToInstrument)
1546 instrumentMemAccess(Operand);
1549 for (
auto *Inst : IntrinToInstrument)
1550 instrumentMemIntrinsic(Inst);
1553 ShadowBase =
nullptr;
1554 StackBaseTag =
nullptr;
1562 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1563 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1564 if (SizeInBytes != NewSize) {
1567 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1576 NewGV->copyAttributesFrom(GV);
1578 NewGV->copyMetadata(GV, 0);
1579 NewGV->setAlignment(
1599 const uint64_t MaxDescriptorSize = 0xfffff0;
1600 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1601 DescriptorPos += MaxDescriptorSize) {
1604 nullptr, GV->
getName() +
".hwasan.descriptor");
1612 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1614 Descriptor->setComdat(NewGV->getComdat());
1616 Descriptor->setSection(
"hwasan_globals");
1617 Descriptor->setMetadata(LLVMContext::MD_associated,
1630 Alias->takeName(GV);
1635void HWAddressSanitizer::instrumentGlobals() {
1636 std::vector<GlobalVariable *> Globals;
1655 Globals.push_back(&GV);
1659 Hasher.
update(
M.getSourceFileName());
1662 uint8_t
Tag = Hash[0];
1664 assert(TagMaskByte >= 16);
1670 if (Tag < 16 || Tag > TagMaskByte)
1672 instrumentGlobal(GV,
Tag++);
1676void HWAddressSanitizer::instrumentPersonalityFunctions() {
1685 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1688 if (
F.hasPersonalityFn()) {
1689 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1690 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1691 PersonalityFns[
nullptr].push_back(&
F);
1695 if (PersonalityFns.
empty())
1700 Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy);
1701 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1702 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1704 for (
auto &
P : PersonalityFns) {
1707 ThunkName += (
"." +
P.first->getName()).str();
1710 bool IsLocal =
P.first && (!isa<GlobalValue>(
P.first) ||
1711 cast<GlobalValue>(
P.first)->hasLocalLinkage());
1718 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1724 HwasanPersonalityWrapper,
1725 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1726 ThunkFn->getArg(3), ThunkFn->getArg(4),
1735 F->setPersonalityFn(ThunkFn);
1739void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1740 bool InstrumentWithCalls) {
1748 WithFrameRecord =
true;
1753 WithFrameRecord =
false;
1758 WithFrameRecord =
false;
1763 WithFrameRecord =
false;
1768 WithFrameRecord =
true;
1773 WithFrameRecord =
false;
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< size_t > ClMaxLifetimes("stack-tagging-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional)
static const uint64_t kDefaultShadowScale
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentByval("asan-instrument-byval", cl::desc("instrument byval call arguments"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))
static const uint64_t kDynamicShadowSentinel
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClWithIfunc("asan-with-ifunc", cl::desc("Access dynamic shadow through an ifunc global on " "platforms that support this"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("asan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
static cl::opt< uint64_t > ClMappingOffset("asan-mapping-offset", cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
This file contains the simple types necessary to represent the attributes associated with functions a...
Analysis containing CSE Info
#define clEnumVal(ENUMVAL, DESC)
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file contains constants used for implementing Dwarf debug support.
This is the interface for a simple mod/ref and alias analysis over globals.
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
static cl::opt< bool > ClInstrumentWrites("hwasan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static const size_t kDefaultShadowScale
static cl::opt< RecordStackHistoryMode > ClRecordStackHistory("hwasan-record-stack-history", cl::desc("Record stack frames with tagged allocations in a thread-local " "ring buffer"), cl::values(clEnumVal(none, "Do not record stack ring history"), clEnumVal(instr, "Insert instructions into the prologue for " "storing into the stack ring buffer directly"), clEnumVal(libcall, "Add a call to __hwasan_add_frame_record for " "storing into the stack ring buffer")), cl::Hidden, cl::init(instr))
const char kHwasanModuleCtorName[]
static cl::opt< int > ClMatchAllTag("hwasan-match-all-tag", cl::desc("don't report bad accesses via pointers with this tag"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClUseAfterScope("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(true))
const char kHwasanNoteName[]
static const unsigned kShadowBaseAlignment
static cl::opt< bool > ClGenerateTagsWithCalls("hwasan-generate-tags-with-calls", cl::desc("generate new tags with runtime library calls"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentReads("hwasan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentWithCalls("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClUseStackSafety("hwasan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional)
static cl::opt< bool > ClInstrumentAtomics("hwasan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClInstrumentStack("hwasan-instrument-stack", cl::desc("instrument stack (allocas)"), cl::Hidden, cl::init(true))
static cl::opt< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClRecover("hwasan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClEnableKhwasan("hwasan-kernel", cl::desc("Enable KernelHWAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInlineAllChecks("hwasan-inline-all-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
static const uint64_t kDynamicShadowSentinel
static cl::opt< bool > ClUsePageAliases("hwasan-experimental-use-page-aliases", cl::desc("Use page aliasing in HWASan"), cl::Hidden, cl::init(false))
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("hwasan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__hwasan_"))
static cl::opt< bool > ClInstrumentMemIntrinsics("hwasan-instrument-mem-intrinsics", cl::desc("instrument memory intrinsics"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
static cl::opt< bool > ClWithTls("hwasan-with-tls", cl::desc("Access dynamic shadow through an thread-local pointer on " "platforms that support this"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClGlobals("hwasan-globals", cl::desc("Instrument globals"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("hwasan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentByval("hwasan-instrument-byval", cl::desc("instrument byval arguments"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClUseShortGranules("hwasan-use-short-granules", cl::desc("use short granules in allocas and outlined checks"), cl::Hidden, cl::init(false))
const char kHwasanShadowMemoryDynamicAddress[]
static unsigned getPointerOperandIndex(Instruction *I)
static cl::opt< bool > ClInlineFastPathChecks("hwasan-inline-fast-path-checks", cl::desc("inline all checks"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentPersonalityFunctions("hwasan-instrument-personality-functions", cl::desc("instrument personality functions"), cl::Hidden)
const char kHwasanInitName[]
static cl::opt< bool > ClInstrumentLandingPads("hwasan-instrument-landing-pads", cl::desc("instrument landing pads"), cl::Hidden, cl::init(false))
static cl::opt< size_t > ClMaxLifetimes("hwasan-max-lifetimes-for-alloca", cl::Hidden, cl::init(3), cl::ReallyHidden, cl::desc("How many lifetime ends to handle for a single alloca."), cl::Optional)
const char kHwasanPersonalityThunkName[]
static cl::opt< bool > ClWithIfunc("hwasan-with-ifunc", cl::desc("Access dynamic shadow through an ifunc global on " "platforms that support this"), cl::Hidden, cl::init(false))
Select target instructions out of generic instructions
This file implements a map that provides insertion order iteration.
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
an instruction to allocate memory on the stack
PointerType * getType() const
Overload to return most specific pointer type.
const Value * getArraySize() const
Get the number of elements allocated.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Function * getParent() const
Return the enclosing method, or null if none.
This class represents a function call, abstracting a target machine's calling convention.
void setTailCall(bool IsTc=true)
static Constant * get(LLVMContext &Context, ArrayRef< ElementTy > Elts)
get() constructor - Return a constant with array type with an element count and element type matching...
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getSub(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getAdd(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
static Constant * getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static Constant * getAnon(ArrayRef< Constant * > V, bool Packed=false)
Return an anonymous struct that has the specified elements.
This is an important base class in LLVM.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
static DIExpression * appendOpsToArg(const DIExpression *Expr, ArrayRef< uint64_t > Ops, unsigned ArgNo, bool StackValue=false)
Create a copy of Expr by appending the given list of Ops to each instance of the operand DW_OP_LLVM_a...
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
static GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
MaybeAlign getAlign() const
Returns the alignment of the given variable or function.
void setComdat(Comdat *C)
bool hasSection() const
Check if this global has a custom object file section.
const SanitizerMetadata & getSanitizerMetadata() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
LinkageTypes getLinkage() const
bool isDeclarationForLinker() const
bool hasSanitizerMetadata() const
unsigned getAddressSpace() const
Module * getParent()
Get the module that this global value is contained inside of...
PointerType * getType() const
Global values are always pointers.
@ HiddenVisibility
The GV is hidden.
bool hasCommonLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ InternalLinkage
Rename collisions when linking (static functions).
@ ExternalLinkage
Externally visible function.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool isConstant() const
If the value is a global constant, its value is immutable throughout the runtime execution of the pro...
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Analysis pass providing a never-invalidated alias analysis result.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name="")
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memset to the specified pointer and the specified value.
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateTypeSize(Type *DstType, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
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 * CreateZExt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateBitCast(Value *V, Type *DestTy, 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)
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", bool IsInBounds=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
const BasicBlock * getParent() const
void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDString * get(LLVMContext &Context, StringRef Str)
This class implements a map that also provides access to all stored values in a deterministic order.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
Constant * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
void abandon()
Mark an analysis as abandoned.
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).
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 startswith(StringRef Prefix) const
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
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.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt32Ty(LLVMContext &C)
static IntegerType * getInt64Ty(LLVMContext &C)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void setName(const Twine &Name)
Change the name of the value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
void replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
@ DW_OP_LLVM_tag_offset
Only used in LLVM metadata.
bool isStandardLifetime(const SmallVectorImpl< IntrinsicInst * > &LifetimeStart, const SmallVectorImpl< IntrinsicInst * > &LifetimeEnd, const DominatorTree *DT, const LoopInfo *LI, size_t MaxLifetimes)
bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const Instruction *Start, const SmallVectorImpl< IntrinsicInst * > &Ends, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
static bool isLifetimeIntrinsic(Intrinsic::ID ID)
Check if ID corresponds to a lifetime intrinsic.
std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
This struct is a compact representation of a valid (non-zero power of two) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
A CRTP mix-in to automatically provide informational APIs needed for passes.
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 4 > UnrecognizedLifetimes
SmallVector< Instruction *, 8 > RetVec