73#define DEBUG_TYPE "hwasan"
81 "__hwasan_shadow_memory_dynamic_address";
105 cl::desc(
"HWASan shadow mapping offset [EXPERIMENTAL]"),
109 "hwasan-mapping-offset-dynamic",
112 clEnumValN(OffsetKind::kIfunc,
"ifunc",
"Use ifunc global"),
113 clEnumValN(OffsetKind::kTls,
"tls",
"Use TLS")));
116STATISTIC(NumInstrumentedFuncs,
"Number of instrumented funcs");
117STATISTIC(NumNoProfileSummaryFuncs,
"Number of funcs without PS");
121bool shouldUsePageAliases(
const InstrumentationOptions &Opts,
122 const Triple &TargetTriple) {
123 return Opts.hwasan_experimental_use_page_aliases &&
127bool shouldInstrumentStack(
const InstrumentationOptions &Opts,
128 const Triple &TargetTriple) {
129 return !shouldUsePageAliases(Opts, TargetTriple) &&
130 Opts.hwasan_instrument_stack;
133bool shouldInstrumentWithCalls(
const InstrumentationOptions &Opts,
134 const Triple &TargetTriple) {
135 return valueOr(Opts.hwasan_instrument_with_calls,
139bool mightUseStackSafetyAnalysis(
const InstrumentationOptions &Opts,
140 bool DisableOptimization) {
141 return valueOr(Opts.hwasan_use_stack_safety, !DisableOptimization);
144bool shouldUseStackSafetyAnalysis(
const InstrumentationOptions &Opts,
145 const Triple &TargetTriple,
146 bool DisableOptimization) {
147 return shouldInstrumentStack(Opts, TargetTriple) &&
148 mightUseStackSafetyAnalysis(Opts, DisableOptimization);
151bool shouldDetectUseAfterScope(
const InstrumentationOptions &Opts,
152 const Triple &TargetTriple) {
153 return Opts.hwasan_use_after_scope &&
154 shouldInstrumentStack(Opts, TargetTriple);
159class HWAddressSanitizer {
161 HWAddressSanitizer(
const InstrumentationOptions &Opts,
Module &M,
162 bool CompileKernel,
bool Recover,
163 const StackSafetyGlobalInfo *SSI)
164 : Opts(Opts), M(M), SSI(SSI) {
165 this->Recover =
valueOr(Opts.hwasan_recover, Recover);
166 this->CompileKernel =
valueOr(Opts.hwasan_kernel, CompileKernel);
167 this->Rng = Opts.hwasan_random_rate ? M.createRNG(
DEBUG_TYPE) :
nullptr;
175 struct ShadowTagCheckInfo {
177 Value *PtrLong =
nullptr;
178 Value *AddrLong =
nullptr;
179 Value *PtrTag =
nullptr;
180 Value *MemTag =
nullptr;
183 bool selectiveInstrumentationShouldSkip(
Function &
F,
185 void initializeModule();
186 void createHwasanCtorComdat();
187 void createHwasanNote();
189 void initializeCallbacks(
Module &M);
196 void untagPointerOperand(Instruction *
I,
Value *Addr);
199 int64_t getAccessInfo(
bool IsWrite,
unsigned AccessSizeIndex);
200 ShadowTagCheckInfo insertShadowTagCheck(
Value *Ptr, Instruction *InsertBefore,
201 DomTreeUpdater &DTU, LoopInfo *LI);
202 void instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
203 unsigned AccessSizeIndex,
204 Instruction *InsertBefore,
205 DomTreeUpdater &DTU, LoopInfo *LI);
206 void instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
207 unsigned AccessSizeIndex,
208 Instruction *InsertBefore, DomTreeUpdater &DTU,
210 bool ignoreMemIntrinsic(OptimizationRemarkEmitter &ORE, MemIntrinsic *
MI);
211 void instrumentMemIntrinsic(MemIntrinsic *
MI);
212 bool instrumentMemAccess(InterestingMemoryOperand &O, DomTreeUpdater &DTU,
213 LoopInfo *LI,
const DataLayout &
DL);
214 bool ignoreAccessWithoutRemark(Instruction *Inst,
Value *Ptr);
215 bool ignoreAccess(OptimizationRemarkEmitter &ORE, Instruction *Inst,
219 OptimizationRemarkEmitter &ORE, Instruction *
I,
220 const TargetLibraryInfo &
TLI,
221 SmallVectorImpl<InterestingMemoryOperand> &Interesting);
226 void instrumentStack(OptimizationRemarkEmitter &ORE, memtag::StackInfo &Info,
227 Value *StackTag,
Value *UARTag,
const DominatorTree &DT,
228 const PostDominatorTree &PDT,
const LoopInfo &LI);
229 void instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
237 unsigned retagMask(
unsigned AllocaNo);
239 void emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord);
241 void instrumentGlobal(GlobalVariable *GV, uint8_t
Tag);
242 void instrumentGlobals();
247 void instrumentPersonalityFunctions();
249 const InstrumentationOptions &Opts;
252 const StackSafetyGlobalInfo *SSI;
254 std::unique_ptr<RandomNumberGenerator> Rng;
271 class ShadowMapping {
275 bool WithFrameRecord;
278 Kind = OffsetKind::kFixed;
283 void init(
const InstrumentationOptions &Opts, Triple &TargetTriple,
284 bool InstrumentWithCalls,
bool CompileKernel);
286 bool isInGlobal()
const {
return Kind == OffsetKind::kGlobal; }
287 bool isInIfunc()
const {
return Kind == OffsetKind::kIfunc; }
288 bool isInTls()
const {
return Kind == OffsetKind::kTls; }
289 bool isFixed()
const {
return Kind == OffsetKind::kFixed; }
290 uint8_t
scale()
const {
return Scale; };
295 bool withFrameRecord()
const {
return WithFrameRecord; };
298 ShadowMapping Mapping;
300 Type *VoidTy = Type::getVoidTy(M.getContext());
301 Type *IntptrTy = M.getDataLayout().getIntPtrType(M.getContext());
302 PointerType *PtrTy = PointerType::getUnqual(M.getContext());
303 Type *Int8Ty = Type::getInt8Ty(M.getContext());
304 Type *Int32Ty = Type::getInt32Ty(M.getContext());
305 Type *Int64Ty = Type::getInt64Ty(M.getContext());
311 bool UseShortGranules;
312 bool InstrumentLandingPads;
313 bool InstrumentWithCalls;
314 bool InstrumentStack;
315 bool InstrumentGlobals;
316 bool DetectUseAfterScope;
318 bool UseMatchAllCallback;
320 std::optional<uint8_t> MatchAllTag;
322 unsigned PointerTagShift;
328 FunctionCallee HwasanMemoryAccessCallbackSized[2];
330 FunctionCallee HwasanMemmove, HwasanMemcpy, HwasanMemset;
331 FunctionCallee HwasanHandleVfork;
333 FunctionCallee HwasanTagMemoryFunc;
334 FunctionCallee HwasanGenerateTagFunc;
335 FunctionCallee HwasanRecordFrameRecordFunc;
339 Value *ShadowBase =
nullptr;
340 Value *StackBaseTag =
nullptr;
341 Value *CachedFP =
nullptr;
342 GlobalValue *ThreadPtrGlobal =
nullptr;
353 const Triple &TargetTriple = M.getTargetTriple();
355 if (shouldUseStackSafetyAnalysis(Opts, TargetTriple,
356 Options.DisableOptimization))
359 HWAddressSanitizer HWASan(Opts, M, Options.CompileKernel, Options.Recover,
363 HWASan.sanitizeFunction(
F,
FAM);
380 static_cast<PassInfoMixin<HWAddressSanitizerPass> *
>(
this)->
printPipeline(
381 OS, MapClassName2PassName);
383 if (Options.CompileKernel)
390void HWAddressSanitizer::createHwasanNote() {
427 nullptr,
"__start_hwasan_globals");
431 nullptr,
"__stop_hwasan_globals");
438 auto *NoteTy =
StructType::get(Int32Ty, Int32Ty, Int32Ty, Name->getType(),
443 Note->setSection(
".note.hwasan.globals");
444 Note->setComdat(NoteComdat);
449 auto CreateRelPtr = [&](
Constant *Ptr) {
456 {ConstantInt::get(Int32Ty, 8),
457 ConstantInt::get(Int32Ty, 8),
459 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
467 Dummy->setSection(
"hwasan_globals");
468 Dummy->setComdat(NoteComdat);
469 Dummy->setMetadata(LLVMContext::MD_associated,
474void HWAddressSanitizer::createHwasanCtorComdat() {
475 std::tie(HwasanCtorFunction, std::ignore) =
493 if (!Opts.hwasan_static_linking)
500void HWAddressSanitizer::initializeModule() {
502 TargetTriple =
M.getTargetTriple();
513 UsePageAliases = shouldUsePageAliases(Opts, TargetTriple);
514 InstrumentWithCalls = shouldInstrumentWithCalls(Opts, TargetTriple);
515 InstrumentStack = shouldInstrumentStack(Opts, TargetTriple);
516 DetectUseAfterScope = shouldDetectUseAfterScope(Opts, TargetTriple);
517 PointerTagShift = IsX86_64 ? 57 : 56;
518 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
519 if (Opts.hwasan_tag_bits) {
522 "need more than 4 bits of tag to have non-short-granule tags");
523 TagMaskByte &= (1ULL << Opts.hwasan_tag_bits) - 1;
526 Mapping.init(Opts, TargetTriple, InstrumentWithCalls, CompileKernel);
528 C = &(
M.getContext());
530 HwasanCtorFunction =
nullptr;
538 UseShortGranules =
valueOr(Opts.hwasan_use_short_granules, NewRuntime);
541 !
valueOr(Opts.hwasan_inline_all_checks, Recover);
545 valueOr(Opts.hwasan_inline_fast_path_checks,
548 if (Opts.hwasan_match_all_tag) {
549 if (*Opts.hwasan_match_all_tag != -1) {
550 MatchAllTag = *Opts.hwasan_match_all_tag & 0xFF;
552 }
else if (CompileKernel) {
555 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
558 InstrumentLandingPads =
559 valueOr(Opts.hwasan_instrument_landing_pads, !NewRuntime);
561 InstrumentGlobals = !CompileKernel && !UsePageAliases &&
562 valueOr(Opts.hwasan_globals, NewRuntime);
564 if (!CompileKernel) {
565 if (InstrumentGlobals)
568 createHwasanCtorComdat();
570 bool InstrumentPersonalityFunctions =
571 valueOr(Opts.hwasan_instrument_personality_functions, NewRuntime);
572 if (InstrumentPersonalityFunctions)
573 instrumentPersonalityFunctions();
577 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
580 "__hwasan_tls",
nullptr,
588void HWAddressSanitizer::initializeCallbacks(
Module &M) {
589 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
591 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
593 if (UseMatchAllCallback) {
594 HwasanMemoryAccessCallbackSizedFnTy =
596 HwasanMemoryAccessCallbackFnTy =
598 HwasanMemTransferFnTy =
603 HwasanMemoryAccessCallbackSizedFnTy =
605 HwasanMemoryAccessCallbackFnTy =
607 HwasanMemTransferFnTy =
613 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
614 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
615 const std::string EndingStr = Recover ?
"_noabort" :
"";
617 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
618 M.getOrInsertFunction((Opts.hwasan_memory_access_callback_prefix +
619 TypeStr +
"N" + MatchAllStr + EndingStr)
621 HwasanMemoryAccessCallbackSizedFnTy);
625 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
626 M.getOrInsertFunction((Opts.hwasan_memory_access_callback_prefix +
627 TypeStr +
itostr(1ULL << AccessSizeIndex) +
628 MatchAllStr + EndingStr)
630 HwasanMemoryAccessCallbackFnTy);
634 const std::string MemIntrinCallbackPrefix =
635 (CompileKernel && !Opts.hwasan_kernel_mem_intrinsic_prefix)
637 : Opts.hwasan_memory_access_callback_prefix.str();
639 HwasanMemmove =
M.getOrInsertFunction(
640 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
641 HwasanMemcpy =
M.getOrInsertFunction(
642 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
643 HwasanMemset =
M.getOrInsertFunction(
644 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
646 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
647 PtrTy, Int8Ty, IntptrTy);
648 HwasanGenerateTagFunc =
649 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
651 HwasanRecordFrameRecordFunc =
652 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
658 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
670 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
674 return getOpaqueNoopCast(IRB, ShadowGlobal);
678 if (Mapping.isFixed()) {
679 return getOpaqueNoopCast(
681 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
684 if (Mapping.isInIfunc())
685 return getDynamicShadowIfunc(IRB);
689 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
692bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
708 if (!InstrumentStack)
715 if (!InstrumentGlobals)
725 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
737void HWAddressSanitizer::getInterestingMemoryOperands(
742 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
750 if (!Opts.hwasan_instrument_reads ||
751 ignoreAccess(ORE,
I, LI->getPointerOperand()))
753 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
754 LI->getType(), LI->getAlign());
756 if (!Opts.hwasan_instrument_writes ||
757 ignoreAccess(ORE,
I,
SI->getPointerOperand()))
760 SI->getValueOperand()->getType(),
SI->getAlign());
762 if (!Opts.hwasan_instrument_atomics ||
763 ignoreAccess(ORE,
I, RMW->getPointerOperand()))
765 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
766 RMW->getValOperand()->getType(), std::nullopt);
768 if (!Opts.hwasan_instrument_atomics ||
769 ignoreAccess(ORE,
I, XCHG->getPointerOperand()))
771 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
772 XCHG->getCompareOperand()->getType(),
775 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
776 if (!Opts.hwasan_instrument_byval || !CI->isByValArgument(ArgNo) ||
777 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
779 Type *Ty = CI->getParamByValType(ArgNo);
788 return LI->getPointerOperandIndex();
790 return SI->getPointerOperandIndex();
792 return RMW->getPointerOperandIndex();
794 return XCHG->getPointerOperandIndex();
820 if (Mapping.isFixed() && Mapping.offset() == 0)
826int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
827 unsigned AccessSizeIndex) {
836HWAddressSanitizer::ShadowTagCheckInfo
837HWAddressSanitizer::insertShadowTagCheck(
Value *Ptr,
Instruction *InsertBefore,
839 ShadowTagCheckInfo
R;
846 R.AddrLong = untagPointer(IRB,
R.PtrLong);
847 Value *Shadow = memToShadow(
R.AddrLong, IRB);
851 if (MatchAllTag.has_value()) {
853 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
854 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
858 TagMismatch, InsertBefore,
false,
864void HWAddressSanitizer::instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
865 unsigned AccessSizeIndex,
870 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
874 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
877 bool UseFixedShadowIntrinsic =
false;
885 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
886 uint16_t OffsetShifted = Mapping.offset() >> 32;
887 UseFixedShadowIntrinsic =
888 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
891 if (UseFixedShadowIntrinsic) {
894 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
895 : Intrinsic::hwasan_check_memaccess_fixedshadow,
896 {Ptr, ConstantInt::get(Int32Ty, AccessInfo),
897 ConstantInt::get(Int64Ty, Mapping.offset())});
900 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
901 : Intrinsic::hwasan_check_memaccess,
902 {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
906void HWAddressSanitizer::instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
907 unsigned AccessSizeIndex,
912 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
914 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
917 Value *OutOfShortGranuleTagRange =
920 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
926 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
943 switch (TargetTriple.
getArch()) {
967 "ebreak\naddiw x0, x11, " +
984 return (!Opts.hwasan_instrument_writes ||
985 ignoreAccess(ORE, MTI, MTI->getDest())) &&
986 (!Opts.hwasan_instrument_reads ||
987 ignoreAccess(ORE, MTI, MTI->getSource()));
990 return !Opts.hwasan_instrument_writes ||
991 ignoreAccess(ORE,
MI,
MI->getDest());
995void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
999 MI->getOperand(0),
MI->getOperand(1),
1002 if (UseMatchAllCallback)
1003 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1010 if (UseMatchAllCallback)
1011 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1014 MI->eraseFromParent();
1020 Value *Addr =
O.getPtr();
1039 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1041 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1042 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1044 if (InstrumentWithCalls) {
1046 if (UseMatchAllCallback)
1047 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1048 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1050 }
else if (OutlinedChecks) {
1051 instrumentMemAccessOutline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1054 instrumentMemAccessInline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1061 ConstantInt::get(IntptrTy, 8))};
1062 if (UseMatchAllCallback)
1063 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1064 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1066 untagPointerOperand(
O.getInsn(), Addr);
1073 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1074 if (!UseShortGranules)
1078 if (InstrumentWithCalls) {
1081 ConstantInt::get(IntptrTy, AlignedSize)});
1083 size_t ShadowSize =
Size >> Mapping.scale();
1085 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1094 if (
Size != AlignedSize) {
1095 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1096 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1105unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1107 return AllocaNo & TagMaskByte;
1119 static const unsigned FastMasks[] = {
1120 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1121 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1122 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1123 return FastMasks[AllocaNo % std::size(FastMasks)];
1127 if (TagMaskByte == 0xFF)
1130 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1138 if (Opts.hwasan_generate_tags_with_calls)
1141 return StackBaseTag;
1145 Value *FramePointerLong = getCachedFP(IRB);
1147 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1149 StackTag->
setName(
"hwasan.stack.base.tag");
1154 unsigned AllocaNo) {
1155 if (Opts.hwasan_generate_tags_with_calls)
1156 return getNextTagWithCall(IRB);
1158 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1162 Value *FramePointerLong = getCachedFP(IRB);
1164 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1166 UARTag->
setName(
"hwasan.uar.tag");
1174 Value *TaggedPtrLong;
1175 if (CompileKernel) {
1179 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1180 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1184 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1192 Value *UntaggedPtrLong;
1193 if (CompileKernel) {
1197 TagMaskByte << PointerTagShift));
1201 PtrLong, ConstantInt::get(PtrLong->
getType(),
1202 ~(TagMaskByte << PointerTagShift)));
1204 return UntaggedPtrLong;
1210 constexpr int SanitizerSlot = 6;
1213 return ThreadPtrGlobal;
1240void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1241 if (!Mapping.isInTls())
1242 ShadowBase = getShadowNonTls(IRB);
1243 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1244 ShadowBase = getDynamicShadowIfunc(IRB);
1246 if (!WithFrameRecord && ShadowBase)
1249 Value *SlotPtr =
nullptr;
1250 Value *ThreadLong =
nullptr;
1251 Value *ThreadLongMaybeUntagged =
nullptr;
1253 auto getThreadLongMaybeUntagged = [&]() {
1255 SlotPtr = getHwasanThreadSlotPtr(IRB);
1257 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1260 return TargetTriple.
isAArch64() ? ThreadLong
1261 : untagPointer(IRB, ThreadLong);
1264 if (WithFrameRecord) {
1265 switch (Opts.hwasan_record_stack_history) {
1269 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1270 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1274 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1276 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1279 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1289 "A stack history recording mode should've been selected.");
1295 if (!ThreadLongMaybeUntagged)
1296 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1303 ThreadLongMaybeUntagged,
1305 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1310void HWAddressSanitizer::instrumentLandingPads(
1312 for (
auto *LP : LandingPadVec) {
1336 auto *AI = KV.first;
1342 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1344 Value *AINoTagLong = untagPointer(IRB, AILong);
1345 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1348 Replacement->
setName(Name +
".hwasan");
1351 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1354 auto *
User =
U.getUser();
1360 auto TagStarts = [&]() {
1363 tagAlloca(IRB, AI,
Tag,
Size);
1372 tagAlloca(IRB, AI, UARTag, AlignedSize);
1374 auto EraseLifetimes = [&]() {
1375 for (
auto &
II :
Info.LifetimeStart)
1376 II->eraseFromParent();
1377 for (
auto &
II :
Info.LifetimeEnd)
1378 II->eraseFromParent();
1391 }
else if (DetectUseAfterScope && Opts.hwasan_strict_use_after_scope) {
1397 tagAlloca(IRB, AI,
Tag,
Size);
1403 tagAlloca(IRB, AI,
Tag,
Size);
1416 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1421 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1426bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1428 auto SkipHot = [&]() {
1429 if (!Opts.hwasan_percentile_cutoff_hot)
1434 if (!PSI || !PSI->hasProfileSummary()) {
1435 ++NumNoProfileSummaryFuncs;
1438 return PSI->isFunctionHotInCallGraphNthPercentile(
1439 *Opts.hwasan_percentile_cutoff_hot, &
F,
1443 auto SkipRandom = [&]() {
1444 if (!Opts.hwasan_random_rate)
1446 std::bernoulli_distribution
D(*Opts.hwasan_random_rate);
1450 bool Skip = SkipRandom() || SkipHot();
1455void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1457 if (&
F == HwasanCtorFunction)
1461 if (
F.hasFnAttribute(Attribute::Naked))
1464 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1467 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1473 if (
F.isPresplitCoroutine())
1481 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1484 NumInstrumentedFuncs++;
1495 if (InstrumentStack) {
1496 SIB.visit(ORE, Inst);
1505 if (!ignoreMemIntrinsic(ORE,
MI))
1511 initializeCallbacks(*
F.getParent());
1513 if (!LandingPadVec.
empty())
1514 instrumentLandingPads(LandingPadVec);
1520 F.setPersonalityFn(
nullptr);
1524 IntrinToInstrument.
empty())
1531 EntryIRB.disableGEPCanonicalization();
1532 emitPrologue(EntryIRB,
1533 Opts.hwasan_record_stack_history !=
1535 Mapping.withFrameRecord() &&
1542 Value *StackTag = getStackBaseTag(EntryIRB);
1543 Value *UARTag = getUARTag(EntryIRB);
1546 BasicBlock *EntryBB = EntryIRB.GetInsertBlock();
1547 instrumentStack(ORE, SInfo, StackTag, UARTag, DT, PDT, LI);
1552 if (EntryBB != &
F.getEntryBlock()) {
1553 InsertPt =
F.getEntryBlock().begin();
1557 I.moveBefore(
F.getEntryBlock(), InsertPt);
1565 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1567 for (
auto &Operand : OperandsToInstrument)
1568 instrumentMemAccess(Operand, DTU, LI,
DL);
1571 if (Opts.hwasan_instrument_mem_intrinsics && !IntrinToInstrument.
empty()) {
1572 for (
auto *Inst : IntrinToInstrument)
1573 instrumentMemIntrinsic(Inst);
1576 ShadowBase =
nullptr;
1577 StackBaseTag =
nullptr;
1585 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1586 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1587 if (SizeInBytes != NewSize) {
1590 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1599 NewGV->copyAttributesFrom(GV);
1601 NewGV->copyMetadata(GV, 0);
1602 NewGV->setAlignment(
1622 const uint64_t MaxDescriptorSize = 0xfffff0;
1623 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1624 DescriptorPos += MaxDescriptorSize) {
1627 nullptr, GV->
getName() +
".hwasan.descriptor");
1633 ConstantInt::get(Int64Ty, DescriptorPos)),
1635 uint32_t
Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1636 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (uint32_t(
Tag) << 24));
1637 Descriptor->setComdat(NewGV->getComdat());
1639 Descriptor->setSection(
"hwasan_globals");
1640 Descriptor->setMetadata(LLVMContext::MD_associated,
1648 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1653 Alias->takeName(GV);
1658void HWAddressSanitizer::instrumentGlobals() {
1659 std::vector<GlobalVariable *> Globals;
1672 if (Opts.hwasan_all_globals) {
1684 Globals.push_back(&GV);
1688 Hasher.
update(
M.getSourceFileName());
1691 uint8_t
Tag = Hash[0];
1693 assert(TagMaskByte >= 16);
1701 instrumentGlobal(GV,
Tag++);
1705void HWAddressSanitizer::instrumentPersonalityFunctions() {
1714 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
1715 F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1718 if (
F.hasPersonalityFn()) {
1719 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1720 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1721 PersonalityFns[
nullptr].push_back(&
F);
1725 if (PersonalityFns.
empty())
1729 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1730 PtrTy, PtrTy, PtrTy, PtrTy);
1731 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1732 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1734 for (
auto &
P : PersonalityFns) {
1737 ThunkName += (
"." +
P.first->getName()).str();
1739 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1748 return F->hasFnAttribute(
"branch-target-enforcement");
1750 ThunkFn->addFnAttr(
"branch-target-enforcement");
1754 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1760 HwasanPersonalityWrapper,
1761 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1762 ThunkFn->getArg(3), ThunkFn->getArg(4),
1769 F->setPersonalityFn(ThunkFn);
1773void HWAddressSanitizer::ShadowMapping::init(
const InstrumentationOptions &Opts,
1775 bool InstrumentWithCalls,
1776 bool CompileKernel) {
1779 Kind = OffsetKind::kTls;
1780 WithFrameRecord =
true;
1786 Kind = OffsetKind::kGlobal;
1787 }
else if (CompileKernel || InstrumentWithCalls) {
1789 WithFrameRecord =
false;
1792 WithFrameRecord =
valueOr(Opts.hwasan_with_frame_record, WithFrameRecord);
const TargetLowering & TLI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const uint64_t kDefaultShadowScale
static const size_t kNumberOfAccessSizes
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static uint64_t scale(uint64_t Num, uint32_t N, uint32_t D)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
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< uint64_t > ClMappingOffset("hwasan-mapping-offset", cl::desc("HWASan shadow mapping offset [EXPERIMENTAL]"), cl::Hidden)
const char kHwasanModuleCtorName[]
const char kHwasanNoteName[]
static const unsigned kShadowBaseAlignment
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 const size_t kNumberOfAccessSizes
const char kHwasanShadowMemoryDynamicAddress[]
static unsigned getPointerOperandIndex(Instruction *I)
const char kHwasanInitName[]
const char kHwasanPersonalityThunkName[]
static void emitRemark(const Function &F, OptimizationRemarkEmitter &ORE, bool Skip)
Module.h This file contains the declarations for the Module class.
This file implements a map that provides insertion order iteration.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
an instruction to allocate memory on the stack
PointerType * getType() const
Overload to return most specific pointer type.
const Value * getArraySize() const
Get the number of elements allocated.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
An instruction that atomically checks whether a specified value is in a memory location,...
an instruction that atomically reads a memory location, combines it with another value,...
LLVM Basic Block Representation.
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
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.
Module * getModule() const
Get the module.
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
void disableGEPCanonicalization()
Disable canonicalization of getelementptr instructions to ptradd form.
Value * CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name="")
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, MaybeAlign Align, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memset to the specified pointer and the specified value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="", bool IsNonNeg=false)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > OverloadTypes, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="", ArrayRef< OperandBundleDef > OpBundles={}, function_ref< void(CallInst *)> SetFn=[](CallInst *) {})
Variant to create a possibly constant-folded intrinsic.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="", bool IsNUW=false, bool IsNSW=false)
PointerType * getPtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer.
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Value * CreateAShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI void setSuccessor(unsigned Idx, BasicBlock *BB)
Update the specified successor to point at the provided block.
A wrapper class for inspecting calls to intrinsic functions.
An instruction for reading from memory.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This class implements a map that also provides access to all stored values in a deterministic order.
This is the common base class for memset/memcpy/memmove.
This class wraps the llvm.memcpy/memmove intrinsics.
A Module instance is used to store all the information related to an LLVM module.
GlobalVariable * getOrInsertGlobal(StringRef Name, Type *Ty, function_ref< GlobalVariable *()> CreateGlobalCallback)
Look up the specified global in the module symbol table.
Analysis pass which computes a PostDominatorTree.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & abandon()
Mark an analysis as abandoned.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
LLVM_ABI bool stackAccessIsSafe(const Instruction &I) const
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
bool isAndroidVersionLT(unsigned Major) const
bool isAndroid() const
Tests whether the target is Android.
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isRISCV64() const
Tests whether the target is 64-bit RISC-V.
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI bool isSwiftError() const
Return true if this value is a swifterror value.
LLVM_ABI bool replaceUsesWithIf(Value *New, llvm::function_ref< bool(Use &U)> ShouldReplace)
Go through the uses list for this definition and make each use point to "V" if the callback ShouldRep...
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)
Get all the memory operands from the instruction that needs to be instrumented.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
LLVM_ABI Value * getFP(IRBuilder<> &IRB)
LLVM_ABI void forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI, const AllocaInfo &AInfo, const SmallVectorImpl< Instruction * > &RetVec, llvm::function_ref< void(Instruction *)> Callback)
LLVM_ABI bool isSupportedLifetime(const AllocaInfo &AInfo, const DominatorTree *DT, const LoopInfo *LI)
LLVM_ABI uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
LLVM_ABI Value * getAndroidSlotPtr(IRBuilder<> &IRB, int Slot)
LLVM_ABI Value * readRegister(IRBuilder<> &IRB, StringRef Name)
LLVM_ABI void annotateDebugRecords(AllocaInfo &Info, unsigned int Tag)
LLVM_ABI void alignAndPadAlloca(memtag::AllocaInfo &Info, llvm::Align Align)
LLVM_ABI Value * getPC(const Triple &TargetTriple, IRBuilder<> &IRB)
LLVM_ABI Value * incrementThreadLong(IRBuilder<> &IRB, Value *ThreadLong, unsigned int Inc, bool IsMemtagDarwin=false)
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< NodeBase * > Node
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
@ Known
Known to have no common set bits.
LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
OuterAnalysisManagerProxy< ModuleAnalysisManager, Function > ModuleAnalysisManagerFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI std::pair< Function *, FunctionCallee > getOrCreateSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, function_ref< void(Function *, FunctionCallee)> FunctionsCreatedCallback, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function lazily.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
LLVM_ABI void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem)
Remove memory attributes that are incompatible with the instrumentation added by AddressSanitizer and...
LLVM_ABI void appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Append F to the list of global ctors of module M with the given Priority.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
constexpr bool valueOr(BoolOrDefault X, bool Default)
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void maybeMarkSanitizerLibraryCallNoBuiltin(CallInst *CI, const TargetLibraryInfo *TLI)
Given a CallInst, check if it calls a string function known to CodeGen, and mark it with NoBuiltin if...
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
std::string itostr(int64_t X)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
This struct is a compact representation of a valid (non-zero power of two) alignment.
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
MapVector< AllocaInst *, AllocaInfo > AllocasToInstrument
SmallVector< Instruction *, 8 > RetVec