72#define DEBUG_TYPE "hwasan"
80 "__hwasan_shadow_memory_dynamic_address";
100 cl::desc(
"Prefix for memory access callbacks"),
104 "hwasan-kernel-mem-intrinsic-prefix",
109 "hwasan-instrument-with-calls",
114 cl::desc(
"instrument read instructions"),
123 "hwasan-instrument-atomics",
128 cl::desc(
"instrument byval arguments"),
133 cl::desc(
"Enable recovery mode (continue-after-error)."),
137 cl::desc(
"instrument stack (allocas)"),
148 cl::desc(
"How many lifetime ends to handle for a single alloca."),
153 cl::desc(
"detect use after scope within function"),
157 "hwasan-strict-use-after-scope",
158 cl::desc(
"for complicated lifetimes, tag both on end and return"),
162 "hwasan-generate-tags-with-calls",
170 "hwasan-all-globals",
172 "Instrument globals, even those within user-defined sections. Warning: "
173 "This may break existing code which walks globals via linker-generated "
174 "symbols, expects certain globals to be contiguous with each other, or "
175 "makes other assumptions which are invalidated by HWASan "
180 "hwasan-match-all-tag",
181 cl::desc(
"don't report bad accesses via pointers with this tag"),
186 cl::desc(
"Enable KernelHWAddressSanitizer instrumentation"),
195 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
199 "hwasan-mapping-offset-dynamic",
202 clEnumValN(OffsetKind::kIfunc,
"ifunc",
"Use ifunc global"),
203 clEnumValN(OffsetKind::kTls,
"tls",
"Use TLS")));
207 cl::desc(
"Use ring buffer for stack allocations"),
211 cl::desc(
"Hot percentile cutoff."));
215 cl::desc(
"Probability value in the range [0.0, 1.0] "
216 "to keep instrumentation of a function. "
217 "Note: instrumentation can be skipped randomly "
218 "OR because of the hot percentile cutoff, if "
219 "both are supplied."));
222 "hwasan-static-linking",
223 cl::desc(
"Don't use .note.hwasan.globals section to instrument globals "
224 "from loadable libraries. "
225 "Note: in static binaries, the global variables section can be "
226 "accessed directly via linker-provided "
227 "__start_hwasan_globals and __stop_hwasan_globals symbols"),
245 "hwasan-record-stack-history",
246 cl::desc(
"Record stack frames with tagged allocations in a thread-local "
250 "storing into the stack ring buffer directly"),
252 "storing into the stack ring buffer")),
257 cl::desc(
"instrument memory intrinsics"),
266 "hwasan-use-short-granules",
271 "hwasan-instrument-personality-functions",
284 cl::desc(
"Use page aliasing in HWASan"),
289 cl::desc(
"Restrict tag to at most N bits. Needs to be > 4."),
293STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
294STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
302bool shouldUsePageAliases(
const Triple &TargetTriple) {
306bool shouldInstrumentStack(
const Triple &TargetTriple) {
310bool shouldInstrumentWithCalls(
const Triple &TargetTriple) {
314bool mightUseStackSafetyAnalysis(
bool DisableOptimization) {
318bool shouldUseStackSafetyAnalysis(
const Triple &TargetTriple,
319 bool DisableOptimization) {
320 return shouldInstrumentStack(TargetTriple) &&
321 mightUseStackSafetyAnalysis(DisableOptimization);
324bool shouldDetectUseAfterScope(
const Triple &TargetTriple) {
330class HWAddressSanitizer {
332 HWAddressSanitizer(
Module &M,
bool CompileKernel,
bool Recover,
333 const StackSafetyGlobalInfo *SSI)
335 this->Recover = optOr(
ClRecover, Recover);
346 struct ShadowTagCheckInfo {
348 Value *PtrLong =
nullptr;
349 Value *AddrLong =
nullptr;
350 Value *PtrTag =
nullptr;
351 Value *MemTag =
nullptr;
354 bool selectiveInstrumentationShouldSkip(Function &
F,
356 void initializeModule();
357 void createHwasanCtorComdat();
358 void createHwasanNote();
360 void initializeCallbacks(
Module &M);
367 void untagPointerOperand(Instruction *
I,
Value *Addr);
370 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
371 ShadowTagCheckInfo insertShadowTagCheck(
Value *Ptr, Instruction *InsertBefore,
372 DomTreeUpdater &DTU, LoopInfo *LI);
373 void instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
374 unsigned AccessSizeIndex,
375 Instruction *InsertBefore,
376 DomTreeUpdater &DTU, LoopInfo *LI);
377 void instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
378 unsigned AccessSizeIndex,
379 Instruction *InsertBefore, DomTreeUpdater &DTU,
381 bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *
MI);
382 void instrumentMemIntrinsic(MemIntrinsic *
MI);
383 bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
384 LoopInfo *LI,
const DataLayout &
DL);
385 bool ignoreAccessWithoutRemark(Instruction *Inst,
Value *Ptr);
386 bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
390 OptimizationRemarkEmitter &ORE, Instruction *
I,
391 const TargetLibraryInfo &TLI,
392 SmallVectorImpl<InterestingMemoryOperand> &Interesting);
397 void instrumentStack(OptimizationRemarkEmitter &ORE, memtag::StackInfo &Info,
398 Value *StackTag,
Value *UARTag,
const DominatorTree &DT,
399 const PostDominatorTree &PDT,
const LoopInfo &LI);
400 void instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
408 unsigned retagMask(
unsigned AllocaNo);
410 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
412 void instrumentGlobal(GlobalVariable *GV, uint8_t
Tag);
413 void instrumentGlobals();
418 void instrumentPersonalityFunctions();
422 const StackSafetyGlobalInfo *SSI;
424 std::unique_ptr<RandomNumberGenerator> Rng;
441 class ShadowMapping {
445 bool WithFrameRecord;
447 void SetFixed(uint64_t O) {
448 Kind = OffsetKind::kFixed;
453 void init(Triple &TargetTriple,
bool InstrumentWithCalls,
455 Align getObjectAlignment()
const {
return Align(1ULL << Scale); }
456 bool isInGlobal()
const {
return Kind == OffsetKind::kGlobal; }
457 bool isInIfunc()
const {
return Kind == OffsetKind::kIfunc; }
458 bool isInTls()
const {
return Kind == OffsetKind::kTls; }
459 bool isFixed()
const {
return Kind == OffsetKind::kFixed; }
460 uint8_t
scale()
const {
return Scale; };
461 uint64_t offset()
const {
465 bool withFrameRecord()
const {
return WithFrameRecord; };
468 ShadowMapping Mapping;
470 Type *VoidTy = Type::getVoidTy(M.getContext());
471 Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());
472 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
473 Type *Int8Ty = Type::getInt8Ty(M.getContext());
474 Type *Int32Ty = Type::getInt32Ty(M.getContext());
475 Type *Int64Ty = Type::getInt64Ty(M.getContext());
481 bool UseShortGranules;
482 bool InstrumentLandingPads;
483 bool InstrumentWithCalls;
484 bool InstrumentStack;
485 bool InstrumentGlobals;
486 bool DetectUseAfterScope;
488 bool UseMatchAllCallback;
490 std::optional<uint8_t> MatchAllTag;
492 unsigned PointerTagShift;
493 uint64_t TagMaskByte;
498 FunctionCallee HwasanMemoryAccessCallbackSized[2];
500 FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;
501 FunctionCallee HwasanHandleVfork;
503 FunctionCallee HwasanTagMemoryFunc;
504 FunctionCallee HwasanGenerateTagFunc;
505 FunctionCallee HwasanRecordFrameRecordFunc;
509 Value *ShadowBase =
nullptr;
510 Value *StackBaseTag =
nullptr;
511 Value *CachedFP =
nullptr;
512 GlobalValue *ThreadPtrGlobal =
nullptr;
523 const Triple &TargetTriple = M.getTargetTriple();
524 if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))
527 HWAddressSanitizer HWASan(M, Options.CompileKernel, Options.Recover, SSI);
530 HWASan.sanitizeFunction(
F,
FAM);
548 OS, MapClassName2PassName);
550 if (Options.CompileKernel)
557void HWAddressSanitizer::createHwasanNote() {
594 nullptr,
"__start_hwasan_globals");
598 nullptr,
"__stop_hwasan_globals");
610 Note->setSection(
".note.hwasan.globals");
611 Note->setComdat(NoteComdat);
616 auto CreateRelPtr = [&](
Constant *Ptr) {
626 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
634 Dummy->setSection(
"hwasan_globals");
635 Dummy->setComdat(NoteComdat);
636 Dummy->setMetadata(LLVMContext::MD_associated,
641void HWAddressSanitizer::createHwasanCtorComdat() {
642 std::tie(HwasanCtorFunction, std::ignore) =
667void HWAddressSanitizer::initializeModule() {
669 TargetTriple =
M.getTargetTriple();
680 UsePageAliases = shouldUsePageAliases(TargetTriple);
681 InstrumentWithCalls = shouldInstrumentWithCalls(TargetTriple);
682 InstrumentStack = shouldInstrumentStack(TargetTriple);
683 DetectUseAfterScope = shouldDetectUseAfterScope(TargetTriple);
684 PointerTagShift = IsX86_64 ? 57 : 56;
685 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
689 "need more than 4 bits of tag to have non-short-granule tags");
693 Mapping.init(TargetTriple, InstrumentWithCalls, CompileKernel);
695 C = &(
M.getContext());
698 HwasanCtorFunction =
nullptr;
719 }
else if (CompileKernel) {
722 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
728 !CompileKernel && !UsePageAliases && optOr(
ClGlobals, NewRuntime);
730 if (!CompileKernel) {
731 if (InstrumentGlobals)
734 createHwasanCtorComdat();
736 bool InstrumentPersonalityFunctions =
738 if (InstrumentPersonalityFunctions)
739 instrumentPersonalityFunctions();
743 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
746 "__hwasan_tls",
nullptr,
754void HWAddressSanitizer::initializeCallbacks(
Module &M) {
756 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
758 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
760 if (UseMatchAllCallback) {
761 HwasanMemoryAccessCallbackSizedFnTy =
763 HwasanMemoryAccessCallbackFnTy =
765 HwasanMemTransferFnTy =
770 HwasanMemoryAccessCallbackSizedFnTy =
772 HwasanMemoryAccessCallbackFnTy =
774 HwasanMemTransferFnTy =
780 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
781 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
782 const std::string EndingStr = Recover ?
"_noabort" :
"";
784 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
M.getOrInsertFunction(
786 HwasanMemoryAccessCallbackSizedFnTy);
790 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
792 itostr(1ULL << AccessSizeIndex) +
793 MatchAllStr + EndingStr,
794 HwasanMemoryAccessCallbackFnTy);
798 const std::string MemIntrinCallbackPrefix =
803 HwasanMemmove =
M.getOrInsertFunction(
804 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
805 HwasanMemcpy =
M.getOrInsertFunction(
806 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
807 HwasanMemset =
M.getOrInsertFunction(
808 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
810 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
811 PtrTy, Int8Ty, IntptrTy);
812 HwasanGenerateTagFunc =
813 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
815 HwasanRecordFrameRecordFunc =
816 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
822 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
834 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
838 return getOpaqueNoopCast(IRB, ShadowGlobal);
842 if (Mapping.isFixed()) {
843 return getOpaqueNoopCast(
845 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
848 if (Mapping.isInIfunc())
849 return getDynamicShadowIfunc(IRB);
851 Value *GlobalDynamicAddress =
854 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
857bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
873 if (!InstrumentStack)
880 if (!InstrumentGlobals)
890 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
902void HWAddressSanitizer::getInterestingMemoryOperands(
907 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
917 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
918 LI->getType(), LI->getAlign());
923 SI->getValueOperand()->getType(),
SI->getAlign());
927 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
928 RMW->getValOperand()->getType(), std::nullopt);
932 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
933 XCHG->getCompareOperand()->getType(),
936 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
938 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
940 Type *Ty = CI->getParamByValType(ArgNo);
949 return LI->getPointerOperandIndex();
951 return SI->getPointerOperandIndex();
953 return RMW->getPointerOperandIndex();
955 return XCHG->getPointerOperandIndex();
981 if (Mapping.isFixed() && Mapping.offset() == 0)
987int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
988 unsigned AccessSizeIndex) {
997HWAddressSanitizer::ShadowTagCheckInfo
998HWAddressSanitizer::insertShadowTagCheck(
Value *Ptr,
Instruction *InsertBefore,
1000 ShadowTagCheckInfo
R;
1007 R.AddrLong = untagPointer(IRB,
R.PtrLong);
1008 Value *Shadow = memToShadow(
R.AddrLong, IRB);
1012 if (MatchAllTag.has_value()) {
1014 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
1015 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
1019 TagMismatch, InsertBefore,
false,
1025void HWAddressSanitizer::instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
1026 unsigned AccessSizeIndex,
1031 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1035 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
1038 bool UseFixedShadowIntrinsic =
false;
1046 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
1047 uint16_t OffsetShifted = Mapping.offset() >> 32;
1048 UseFixedShadowIntrinsic =
1049 static_cast<uint64_t
>(OffsetShifted) << 32 == Mapping.offset();
1052 if (UseFixedShadowIntrinsic) {
1055 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
1056 : Intrinsic::hwasan_check_memaccess_fixedshadow,
1057 {Ptr, ConstantInt::get(
Int32Ty, AccessInfo),
1058 ConstantInt::get(Int64Ty, Mapping.offset())});
1061 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
1062 : Intrinsic::hwasan_check_memaccess,
1063 {ShadowBase, Ptr, ConstantInt::get(
Int32Ty, AccessInfo)});
1067void HWAddressSanitizer::instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
1068 unsigned AccessSizeIndex,
1073 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
1075 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
1078 Value *OutOfShortGranuleTagRange =
1079 IRB.
CreateICmpUGT(TCI.MemTag, ConstantInt::get(Int8Ty, 15));
1081 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
1087 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
1104 switch (TargetTriple.
getArch()) {
1128 "ebreak\naddiw x0, x11, " +
1153void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1157 MI->getOperand(0),
MI->getOperand(1),
1160 if (UseMatchAllCallback)
1161 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1168 if (UseMatchAllCallback)
1169 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1172 MI->eraseFromParent();
1178 Value *Addr =
O.getPtr();
1197 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1199 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1200 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1202 if (InstrumentWithCalls) {
1204 if (UseMatchAllCallback)
1205 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1206 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1208 }
else if (OutlinedChecks) {
1209 instrumentMemAccessOutline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1212 instrumentMemAccessInline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1219 ConstantInt::get(IntptrTy, 8))};
1220 if (UseMatchAllCallback)
1221 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1222 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1224 untagPointerOperand(
O.getInsn(), Addr);
1231 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1232 if (!UseShortGranules)
1236 if (InstrumentWithCalls) {
1239 ConstantInt::get(IntptrTy, AlignedSize)});
1241 size_t ShadowSize =
Size >> Mapping.scale();
1243 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1252 if (
Size != AlignedSize) {
1253 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1254 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1263unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1265 return AllocaNo & TagMaskByte;
1277 static const unsigned FastMasks[] = {
1278 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1279 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1280 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1281 return FastMasks[AllocaNo % std::size(FastMasks)];
1285 if (TagMaskByte == 0xFF)
1288 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1299 return StackBaseTag;
1303 Value *FramePointerLong = getCachedFP(IRB);
1305 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1307 StackTag->
setName(
"hwasan.stack.base.tag");
1312 unsigned AllocaNo) {
1314 return getNextTagWithCall(IRB);
1316 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1320 Value *FramePointerLong = getCachedFP(IRB);
1322 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1324 UARTag->
setName(
"hwasan.uar.tag");
1332 Value *TaggedPtrLong;
1333 if (CompileKernel) {
1337 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1338 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1342 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1350 Value *UntaggedPtrLong;
1351 if (CompileKernel) {
1355 TagMaskByte << PointerTagShift));
1359 PtrLong, ConstantInt::get(PtrLong->
getType(),
1360 ~(TagMaskByte << PointerTagShift)));
1362 return UntaggedPtrLong;
1368 constexpr int SanitizerSlot = 6;
1371 return ThreadPtrGlobal;
1398void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1399 if (!Mapping.isInTls())
1400 ShadowBase = getShadowNonTls(IRB);
1401 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1402 ShadowBase = getDynamicShadowIfunc(IRB);
1404 if (!WithFrameRecord && ShadowBase)
1407 Value *SlotPtr =
nullptr;
1408 Value *ThreadLong =
nullptr;
1409 Value *ThreadLongMaybeUntagged =
nullptr;
1411 auto getThreadLongMaybeUntagged = [&]() {
1413 SlotPtr = getHwasanThreadSlotPtr(IRB);
1415 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1418 return TargetTriple.
isAArch64() ? ThreadLong
1419 : untagPointer(IRB, ThreadLong);
1422 if (WithFrameRecord) {
1427 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1428 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1432 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1434 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1437 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1447 "A stack history recording mode should've been selected.");
1453 if (!ThreadLongMaybeUntagged)
1454 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1461 ThreadLongMaybeUntagged,
1463 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1468void HWAddressSanitizer::instrumentLandingPads(
1470 for (
auto *LP : LandingPadVec) {
1494 auto *AI = KV.first;
1499 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1501 Value *AINoTagLong = untagPointer(IRB, AILong);
1502 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1505 Replacement->
setName(Name +
".hwasan");
1508 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1511 auto *
User =
U.getUser();
1517 auto TagStarts = [&]() {
1520 tagAlloca(IRB, AI,
Tag,
Size);
1529 tagAlloca(IRB, AI, UARTag, AlignedSize);
1531 auto EraseLifetimes = [&]() {
1532 for (
auto &
II :
Info.LifetimeStart)
1533 II->eraseFromParent();
1534 for (
auto &
II :
Info.LifetimeEnd)
1535 II->eraseFromParent();
1554 tagAlloca(IRB, AI,
Tag,
Size);
1560 tagAlloca(IRB, AI,
Tag,
Size);
1573 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1578 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1583bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1585 auto SkipHot = [&]() {
1591 if (!PSI || !PSI->hasProfileSummary()) {
1592 ++NumNoProfileSummaryFuncs;
1595 return PSI->isFunctionHotInCallGraphNthPercentile(
1599 auto SkipRandom = [&]() {
1606 bool Skip = SkipRandom() || SkipHot();
1611void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1613 if (&
F == HwasanCtorFunction)
1617 if (
F.hasFnAttribute(Attribute::Naked))
1620 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1626 if (
F.isPresplitCoroutine())
1634 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1637 NumInstrumentedFuncs++;
1648 if (InstrumentStack) {
1649 SIB.visit(ORE, Inst);
1658 if (!ignoreMemIntrinsic(ORE,
MI))
1664 initializeCallbacks(*
F.getParent());
1666 if (!LandingPadVec.
empty())
1667 instrumentLandingPads(LandingPadVec);
1673 F.setPersonalityFn(
nullptr);
1677 IntrinToInstrument.
empty())
1684 emitPrologue(EntryIRB,
1686 Mapping.withFrameRecord() &&
1693 Value *StackTag = getStackBaseTag(EntryIRB);
1694 Value *UARTag = getUARTag(EntryIRB);
1695 instrumentStack(ORE, SInfo, StackTag, UARTag, DT, PDT, LI);
1701 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1702 InsertPt =
F.getEntryBlock().begin();
1707 I.moveBefore(
F.getEntryBlock(), InsertPt);
1714 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1716 for (
auto &Operand : OperandsToInstrument)
1717 instrumentMemAccess(Operand, DTU, LI,
DL);
1721 for (
auto *Inst : IntrinToInstrument)
1722 instrumentMemIntrinsic(Inst);
1725 ShadowBase =
nullptr;
1726 StackBaseTag =
nullptr;
1733 uint64_t SizeInBytes =
1734 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1735 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1736 if (SizeInBytes != NewSize) {
1739 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1748 NewGV->copyAttributesFrom(GV);
1750 NewGV->copyMetadata(GV, 0);
1751 NewGV->setAlignment(
1771 const uint64_t MaxDescriptorSize = 0xfffff0;
1772 for (uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1773 DescriptorPos += MaxDescriptorSize) {
1776 nullptr, GV->
getName() +
".hwasan.descriptor");
1782 ConstantInt::get(Int64Ty, DescriptorPos)),
1784 uint32_t
Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1785 auto *SizeAndTag = ConstantInt::get(
Int32Ty,
Size | (uint32_t(
Tag) << 24));
1786 Descriptor->setComdat(NewGV->getComdat());
1788 Descriptor->setSection(
"hwasan_globals");
1789 Descriptor->setMetadata(LLVMContext::MD_associated,
1797 ConstantInt::get(Int64Ty, uint64_t(
Tag) << PointerTagShift)),
1802 Alias->takeName(GV);
1807void HWAddressSanitizer::instrumentGlobals() {
1808 std::vector<GlobalVariable *> Globals;
1833 Globals.push_back(&GV);
1837 Hasher.
update(
M.getSourceFileName());
1840 uint8_t
Tag = Hash[0];
1842 assert(TagMaskByte >= 16);
1850 instrumentGlobal(GV,
Tag++);
1854void HWAddressSanitizer::instrumentPersonalityFunctions() {
1863 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1866 if (
F.hasPersonalityFn()) {
1867 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1868 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1869 PersonalityFns[
nullptr].push_back(&
F);
1873 if (PersonalityFns.
empty())
1878 PtrTy, PtrTy, PtrTy, PtrTy);
1879 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1880 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1882 for (
auto &
P : PersonalityFns) {
1885 ThunkName += (
"." +
P.first->getName()).str();
1896 return F->hasFnAttribute(
"branch-target-enforcement");
1898 ThunkFn->addFnAttr(
"branch-target-enforcement");
1902 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1908 HwasanPersonalityWrapper,
1909 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1910 ThunkFn->getArg(3), ThunkFn->getArg(4),
1917 F->setPersonalityFn(ThunkFn);
1921void HWAddressSanitizer::ShadowMapping::init(
Triple &TargetTriple,
1922 bool InstrumentWithCalls,
1923 bool CompileKernel) {
1926 Kind = OffsetKind::kTls;
1927 WithFrameRecord =
true;
1933 Kind = OffsetKind::kGlobal;
1934 }
else if (CompileKernel || InstrumentWithCalls) {
1936 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 cl::opt< uint64_t > ClTagBits("hwasan-tag-bits", cl::desc("Restrict tag to at most N bits. Needs to be > 4."), cl::Hidden, cl::init(0))
static const unsigned kShadowBaseAlignment
static cl::opt< bool > ClGenerateTagsWithCalls("hwasan-generate-tags-with-calls", cl::desc("generate new tags with runtime library calls"), cl::Hidden, cl::init(false))
static cl::opt< bool > ClInstrumentReads("hwasan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static cl::opt< float > ClRandomKeepRate("hwasan-random-rate", cl::desc("Probability value in the range [0.0, 1.0] " "to keep instrumentation of a function. " "Note: instrumentation can be skipped randomly " "OR because of the hot percentile cutoff, if " "both are supplied."))
static cl::opt< bool > ClInstrumentWithCalls("hwasan-instrument-with-calls", cl::desc("instrument reads and writes with callbacks"), cl::Hidden, cl::init(false))
static cl::opt< bool > 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 * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using OverloadTypes.
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)
void forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
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)
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)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
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.
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.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
A CRTP mix-in to automatically provide informational APIs needed for passes.
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 8 > RetVec