62#define DEBUG_TYPE "hwasan"
70 "__hwasan_shadow_memory_dynamic_address";
77 std::numeric_limits<uint64_t>::max();
83 cl::desc(
"Prefix for memory access callbacks"),
87 "hwasan-kernel-mem-intrinsic-prefix",
92 "hwasan-instrument-with-calls",
97 cl::desc(
"instrument read instructions"),
106 "hwasan-instrument-atomics",
111 cl::desc(
"instrument byval arguments"),
116 cl::desc(
"Enable recovery mode (continue-after-error)."),
120 cl::desc(
"instrument stack (allocas)"),
131 cl::desc(
"How many lifetime ends to handle for a single alloca."),
136 cl::desc(
"detect use after scope within function"),
140 "hwasan-uar-retag-to-zero",
141 cl::desc(
"Clear alloca tags before returning from the function to allow "
142 "non-instrumented and instrumented function calls mix. When set "
143 "to false, allocas are retagged before returning from the "
144 "function to detect use after return."),
148 "hwasan-generate-tags-with-calls",
156 "hwasan-match-all-tag",
157 cl::desc(
"don't report bad accesses via pointers with this tag"),
162 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
171 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
176 cl::desc(
"Access dynamic shadow through an ifunc global on "
177 "platforms that support this"),
182 cl::desc(
"Access dynamic shadow through an thread-local pointer on "
183 "platforms that support this"),
201 "hwasan-record-stack-history",
202 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
206 "storing into the stack ring buffer directly"),
208 "storing into the stack ring buffer")),
213 cl::desc(
"instrument memory intrinsics"),
222 "hwasan-use-short-granules",
227 "hwasan-instrument-personality-functions",
236 cl::desc(
"Use page aliasing in HWASan"),
241bool shouldUsePageAliases(
const Triple &TargetTriple) {
245bool shouldInstrumentStack(
const Triple &TargetTriple) {
249bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
253bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
255 : !DisableOptimization;
258bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
259 bool DisableOptimization) {
260 return shouldInstrumentStack(TargetTriple) &&
261 mightUseStackSafetyAnalysis(DisableOptimization);
264bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
270class HWAddressSanitizer {
272 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
286 void initializeModule();
287 void createHwasanCtorComdat();
289 void initializeCallbacks(
Module &M);
299 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
300 void instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
301 unsigned AccessSizeIndex,
303 void instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
304 unsigned AccessSizeIndex,
310 void getInterestingMemoryOperands(
329 unsigned retagMask(
unsigned AllocaNo);
331 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
334 void instrumentGlobals();
340 void instrumentPersonalityFunctions();
361 struct ShadowMapping {
366 bool WithFrameRecord;
368 void init(
Triple &TargetTriple,
bool InstrumentWithCalls);
369 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
372 ShadowMapping Mapping;
384 bool UseShortGranules;
385 bool InstrumentLandingPads;
386 bool InstrumentWithCalls;
387 bool InstrumentStack;
388 bool DetectUseAfterScope;
391 std::optional<uint8_t> MatchAllTag;
393 unsigned PointerTagShift;
407 Value *ShadowBase =
nullptr;
408 Value *StackBaseTag =
nullptr;
409 Value *CachedSP =
nullptr;
425 HWASan.sanitizeFunction(
F,
FAM);
437 OS, MapClassName2PassName);
446void HWAddressSanitizer::createHwasanCtorComdat() {
447 std::tie(HwasanCtorFunction, std::ignore) =
496 nullptr,
"__start_hwasan_globals");
500 nullptr,
"__stop_hwasan_globals");
512 Note->setSection(
".note.hwasan.globals");
513 Note->setComdat(NoteComdat);
528 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
536 Dummy->setSection(
"hwasan_globals");
537 Dummy->setComdat(NoteComdat);
538 Dummy->setMetadata(LLVMContext::MD_associated,
546void HWAddressSanitizer::initializeModule() {
548 auto &
DL =
M.getDataLayout();
550 TargetTriple =
Triple(
M.getTargetTriple());
556 UsePageAliases = shouldUsePageAliases(TargetTriple);
557 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
558 InstrumentStack = shouldInstrumentStack(TargetTriple);
559 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
560 PointerTagShift = IsX86_64 ? 57 : 56;
561 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
563 Mapping.init(TargetTriple, InstrumentWithCalls);
565 C = &(
M.getContext());
567 IntptrTy = IRB.getIntPtrTy(
DL);
568 Int8PtrTy = IRB.getInt8PtrTy();
569 Int8Ty = IRB.getInt8Ty();
572 HwasanCtorFunction =
nullptr;
591 }
else if (CompileKernel) {
600 if (!CompileKernel) {
601 createHwasanCtorComdat();
602 bool InstrumentGlobals =
605 if (InstrumentGlobals && !UsePageAliases)
608 bool InstrumentPersonalityFunctions =
612 if (InstrumentPersonalityFunctions)
613 instrumentPersonalityFunctions();
617 Constant *
C =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
620 "__hwasan_tls",
nullptr,
625 ThreadPtrGlobal = cast<GlobalVariable>(
C);
629void HWAddressSanitizer::initializeCallbacks(
Module &M) {
631 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
632 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
633 const std::string EndingStr = Recover ?
"_noabort" :
"";
635 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
641 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
642 M.getOrInsertFunction(
644 itostr(1ULL << AccessSizeIndex) + EndingStr,
649 HwasanTagMemoryFunc =
M.getOrInsertFunction(
650 "__hwasan_tag_memory", IRB.getVoidTy(), Int8PtrTy, Int8Ty, IntptrTy);
651 HwasanGenerateTagFunc =
652 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
654 HwasanRecordFrameRecordFunc =
M.getOrInsertFunction(
655 "__hwasan_add_frame_record", IRB.getVoidTy(), Int64Ty);
657 ShadowGlobal =
M.getOrInsertGlobal(
"__hwasan_shadow",
660 const std::string MemIntrinCallbackPrefix =
664 HWAsanMemmove =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memmove",
665 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
666 IRB.getInt8PtrTy(), IntptrTy);
667 HWAsanMemcpy =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memcpy",
668 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
669 IRB.getInt8PtrTy(), IntptrTy);
670 HWAsanMemset =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memset",
671 IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
672 IRB.getInt32Ty(), IntptrTy);
675 M.getOrInsertFunction(
"__hwasan_handle_vfork", IRB.getVoidTy(), IntptrTy);
687 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
691 return getOpaqueNoopCast(IRB, ShadowGlobal);
696 return getOpaqueNoopCast(
700 if (Mapping.InGlobal)
701 return getDynamicShadowIfunc(IRB);
703 Value *GlobalDynamicAddress =
706 return IRB.
CreateLoad(Int8PtrTy, GlobalDynamicAddress);
712 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
720 if (
Ptr->isSwiftError())
724 if (!InstrumentStack)
726 if (SSI && SSI->stackAccessIsSafe(*Inst))
732void HWAddressSanitizer::getInterestingMemoryOperands(
735 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
742 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
745 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
746 LI->getType(), LI->getAlign());
747 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
751 SI->getValueOperand()->getType(),
SI->getAlign());
755 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
756 RMW->getValOperand()->getType(), std::nullopt);
760 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
761 XCHG->getCompareOperand()->getType(),
763 }
else if (
auto *CI = dyn_cast<CallInst>(
I)) {
764 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
766 ignoreAccess(
I, CI->getArgOperand(ArgNo)))
768 Type *Ty = CI->getParamByValType(ArgNo);
775 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
776 return LI->getPointerOperandIndex();
778 return SI->getPointerOperandIndex();
780 return RMW->getPointerOperandIndex();
782 return XCHG->getPointerOperandIndex();
808 if (Mapping.Offset == 0)
811 return IRB.
CreateGEP(Int8Ty, ShadowBase, Shadow);
814int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
815 unsigned AccessSizeIndex) {
824void HWAddressSanitizer::instrumentMemAccessOutline(
Value *
Ptr,
bool IsWrite,
825 unsigned AccessSizeIndex,
828 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
834 ? Intrinsic::hwasan_check_memaccess_shortgranules
835 : Intrinsic::hwasan_check_memaccess),
839void HWAddressSanitizer::instrumentMemAccessInline(
Value *
Ptr,
bool IsWrite,
840 unsigned AccessSizeIndex,
843 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
849 Value *AddrLong = untagPointer(IRB, PtrLong);
850 Value *Shadow = memToShadow(AddrLong, IRB);
854 if (MatchAllTag.has_value()) {
857 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
865 Value *OutOfShortGranuleTagRange =
893 switch (TargetTriple.
getArch()) {
917 "ebreak\naddiw x0, x11, " +
935 if (isa<MemSetInst>(
MI))
940void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
942 if (isa<MemTransferInst>(
MI)) {
944 isa<MemMoveInst>(
MI) ? HWAsanMemmove : HWAsanMemcpy,
948 }
else if (isa<MemSetInst>(
MI)) {
955 MI->eraseFromParent();
969 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
970 *
O.Alignment >=
O.TypeStoreSize / 8)) {
972 if (InstrumentWithCalls) {
973 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
975 }
else if (OutlinedChecks) {
976 instrumentMemAccessOutline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn());
978 instrumentMemAccessInline(
Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn());
981 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite],
982 {IRB.CreatePointerCast(Addr, IntptrTy),
983 IRB.CreateUDiv(IRB.CreateTypeSize(IntptrTy,
985 ConstantInt::get(IntptrTy, 8))});
987 untagPointerOperand(
O.getInsn(),
Addr);
994 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
995 if (!UseShortGranules)
999 if (InstrumentWithCalls) {
1004 size_t ShadowSize =
Size >> Mapping.Scale;
1014 if (
Size != AlignedSize) {
1015 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1025unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1027 return AllocaNo & TagMaskByte;
1039 static unsigned FastMasks[] = {0, 128, 64, 192, 32, 96, 224, 112, 240,
1040 48, 16, 120, 248, 56, 24, 8, 124, 252,
1041 60, 28, 12, 4, 126, 254, 62, 30, 14,
1042 6, 2, 127, 63, 31, 15, 7, 3, 1};
1043 return FastMasks[AllocaNo % std::size(FastMasks)];
1062 return getNextTagWithCall(IRB);
1064 return StackBaseTag;
1068 Value *StackPointerLong = getSP(IRB);
1070 applyTagMask(IRB, IRB.
CreateXor(StackPointerLong,
1072 StackTag->
setName(
"hwasan.stack.base.tag");
1079 return getNextTagWithCall(IRB);
1088 return getNextTagWithCall(IRB);
1096 Value *TaggedPtrLong;
1097 if (CompileKernel) {
1102 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1106 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1114 Value *UntaggedPtrLong;
1115 if (CompileKernel) {
1119 0xFFULL << PointerTagShift));
1124 ~(0xFFULL << PointerTagShift)));
1126 return UntaggedPtrLong;
1142 if (ThreadPtrGlobal)
1143 return ThreadPtrGlobal;
1150 return readRegister(IRB,
"pc");
1161 M, Intrinsic::frameaddress,
1165 {Constant::getNullValue(IRB.getInt32Ty())}),
1173 Value *PC = getPC(IRB);
1174 Value *SP = getSP(IRB);
1186void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1188 ShadowBase = getShadowNonTls(IRB);
1189 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1190 ShadowBase = getDynamicShadowIfunc(IRB);
1192 if (!WithFrameRecord && ShadowBase)
1195 Value *SlotPtr =
nullptr;
1196 Value *ThreadLong =
nullptr;
1197 Value *ThreadLongMaybeUntagged =
nullptr;
1199 auto getThreadLongMaybeUntagged = [&]() {
1201 SlotPtr = getHwasanThreadSlotPtr(IRB, IntptrTy);
1203 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1206 return TargetTriple.
isAArch64() ? ThreadLong
1207 : untagPointer(IRB, ThreadLong);
1210 if (WithFrameRecord) {
1215 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1216 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1220 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1222 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1225 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1227 IntptrTy->getPointerTo(0));
1247 "A stack history recording mode should've been selected.");
1253 if (!ThreadLongMaybeUntagged)
1254 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1261 ThreadLongMaybeUntagged,
1277bool HWAddressSanitizer::instrumentLandingPads(
1279 for (
auto *LP : LandingPadVec) {
1290 auto *II = dyn_cast<IntrinsicInst>(V);
1291 return II && II->isLifetimeStartOrEnd();
1308 auto *AI = KV.first;
1313 Value *
Tag = getAllocaTag(IRB, StackTag, AI,
N);
1321 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1337 II->setArgOperand(1, AICast);
1343 auto *
User =
U.getUser();
1347 for (
auto *DDI :
Info.DbgVariableIntrinsics) {
1353 for (
size_t LocNo = 0; LocNo < DDI->getNumVariableLocationOps(); ++LocNo)
1354 if (DDI->getVariableLocationOp(LocNo) == AI)
1361 Value *UARTag = getUARTag(IRB, StackTag);
1366 tagAlloca(IRB, AI, UARTag, AlignedSize);
1372 bool StandardLifetime =
1377 if (DetectUseAfterScope && StandardLifetime) {
1380 tagAlloca(IRB, AI,
Tag,
Size);
1383 for (
auto *End :
Info.LifetimeEnd)
1384 End->eraseFromParent();
1387 tagAlloca(IRB, AI,
Tag,
Size);
1388 for (
auto *RI : SInfo.
RetVec)
1392 for (
auto &II :
Info.LifetimeStart)
1393 II->eraseFromParent();
1394 for (
auto &II :
Info.LifetimeEnd)
1395 II->eraseFromParent();
1400 I->eraseFromParent();
1404void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1406 if (&
F == HwasanCtorFunction)
1409 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1420 if (InstrumentStack) {
1424 if (InstrumentLandingPads && isa<LandingPadInst>(Inst))
1427 getInterestingMemoryOperands(&Inst, OperandsToInstrument);
1430 if (!ignoreMemIntrinsic(
MI))
1436 initializeCallbacks(*
F.getParent());
1438 if (!LandingPadVec.
empty())
1439 instrumentLandingPads(LandingPadVec);
1445 F.setPersonalityFn(
nullptr);
1449 IntrinToInstrument.
empty())
1456 emitPrologue(EntryIRB,
1458 Mapping.WithFrameRecord &&
1467 instrumentStack(SInfo, StackTag, DT, PDT, LI);
1473 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1474 InsertPt = &*
F.getEntryBlock().begin();
1477 if (
auto *AI = dyn_cast<AllocaInst>(&
I))
1479 I.moveBefore(InsertPt);
1483 for (
auto &Operand : OperandsToInstrument)
1484 instrumentMemAccess(Operand);
1487 for (
auto *Inst : IntrinToInstrument)
1488 instrumentMemIntrinsic(Inst);
1491 ShadowBase =
nullptr;
1492 StackBaseTag =
nullptr;
1500 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1501 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1502 if (SizeInBytes != NewSize) {
1505 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1514 NewGV->copyAttributesFrom(GV);
1516 NewGV->copyMetadata(GV, 0);
1517 NewGV->setAlignment(
1537 const uint64_t MaxDescriptorSize = 0xfffff0;
1538 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1539 DescriptorPos += MaxDescriptorSize) {
1542 nullptr, GV->
getName() +
".hwasan.descriptor");
1550 uint32_t Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1552 Descriptor->setComdat(NewGV->getComdat());
1554 Descriptor->setSection(
"hwasan_globals");
1555 Descriptor->setMetadata(LLVMContext::MD_associated,
1568 Alias->takeName(GV);
1573void HWAddressSanitizer::instrumentGlobals() {
1574 std::vector<GlobalVariable *>
Globals;
1597 Hasher.
update(
M.getSourceFileName());
1600 uint8_t
Tag = Hash[0];
1607 instrumentGlobal(GV,
Tag++);
1611void HWAddressSanitizer::instrumentPersonalityFunctions() {
1620 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1623 if (
F.hasPersonalityFn()) {
1624 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1625 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1626 PersonalityFns[
nullptr].push_back(&
F);
1630 if (PersonalityFns.
empty())
1635 Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy, Int8PtrTy);
1636 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1637 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1639 for (
auto &
P : PersonalityFns) {
1642 ThunkName += (
"." +
P.first->getName()).str();
1645 bool IsLocal =
P.first && (!isa<GlobalValue>(
P.first) ||
1646 cast<GlobalValue>(
P.first)->hasLocalLinkage());
1653 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1659 HwasanPersonalityWrapper,
1660 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1661 ThunkFn->getArg(3), ThunkFn->getArg(4),
1670 F->setPersonalityFn(ThunkFn);
1674void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1675 bool InstrumentWithCalls) {
1683 WithFrameRecord =
true;
1688 WithFrameRecord =
false;
1693 WithFrameRecord =
false;
1698 WithFrameRecord =
false;
1703 WithFrameRecord =
true;
1708 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))
const char kHwasanNoteName[]
static cl::opt< bool > ClUseAfterScope("hwasan-use-after-scope", cl::desc("detect use after scope within function"), cl::Hidden, cl::init(false))
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 > ClUARRetagToZero("hwasan-uar-retag-to-zero", cl::desc("Clear alloca tags before returning from the function to allow " "non-instrumented and instrumented function calls mix. When set " "to false, allocas are retagged before returning from the " "function to detect use after return."), cl::Hidden, cl::init(true))
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 > 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))
This file implements a map that provides insertion order iteration.
Module.h This file contains the declarations for the Module class.
print must be executed print the must be executed context for all instructions
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 * 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 * 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.
Type * getVoidTy()
Fetch the type representing void.
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)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
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, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DominatorTree *DT, 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