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();
354 const InstrumentationOptions &Opts =
355 M.getContext().getLibraryOptions().get<InstrumentationOptions>();
356 if (shouldUseStackSafetyAnalysis(Opts, TargetTriple,
357 Options.DisableOptimization))
360 HWAddressSanitizer HWASan(Opts, M, Options.CompileKernel, Options.Recover,
364 HWASan.sanitizeFunction(
F,
FAM);
381 static_cast<PassInfoMixin<HWAddressSanitizerPass> *
>(
this)->
printPipeline(
382 OS, MapClassName2PassName);
384 if (Options.CompileKernel)
391void HWAddressSanitizer::createHwasanNote() {
428 nullptr,
"__start_hwasan_globals");
432 nullptr,
"__stop_hwasan_globals");
439 auto *NoteTy =
StructType::get(Int32Ty, Int32Ty, Int32Ty, Name->getType(),
444 Note->setSection(
".note.hwasan.globals");
445 Note->setComdat(NoteComdat);
450 auto CreateRelPtr = [&](
Constant *Ptr) {
457 {ConstantInt::get(Int32Ty, 8),
458 ConstantInt::get(Int32Ty, 8),
460 Name, CreateRelPtr(Start), CreateRelPtr(Stop)}));
468 Dummy->setSection(
"hwasan_globals");
469 Dummy->setComdat(NoteComdat);
470 Dummy->setMetadata(LLVMContext::MD_associated,
475void HWAddressSanitizer::createHwasanCtorComdat() {
476 std::tie(HwasanCtorFunction, std::ignore) =
494 if (!Opts.hwasan_static_linking)
501void HWAddressSanitizer::initializeModule() {
503 TargetTriple =
M.getTargetTriple();
514 UsePageAliases = shouldUsePageAliases(Opts, TargetTriple);
515 InstrumentWithCalls = shouldInstrumentWithCalls(Opts, TargetTriple);
516 InstrumentStack = shouldInstrumentStack(Opts, TargetTriple);
517 DetectUseAfterScope = shouldDetectUseAfterScope(Opts, TargetTriple);
518 PointerTagShift = IsX86_64 ? 57 : 56;
519 TagMaskByte = IsX86_64 ? 0x3F : 0xFF;
520 if (Opts.hwasan_tag_bits) {
523 "need more than 4 bits of tag to have non-short-granule tags");
524 TagMaskByte &= (1ULL << Opts.hwasan_tag_bits) - 1;
527 Mapping.init(Opts, TargetTriple, InstrumentWithCalls, CompileKernel);
529 C = &(
M.getContext());
532 HwasanCtorFunction =
nullptr;
540 UseShortGranules =
valueOr(Opts.hwasan_use_short_granules, NewRuntime);
543 !
valueOr(Opts.hwasan_inline_all_checks, Recover);
547 valueOr(Opts.hwasan_inline_fast_path_checks,
550 if (Opts.hwasan_match_all_tag) {
551 if (*Opts.hwasan_match_all_tag != -1) {
552 MatchAllTag = *Opts.hwasan_match_all_tag & 0xFF;
554 }
else if (CompileKernel) {
557 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
560 InstrumentLandingPads =
561 valueOr(Opts.hwasan_instrument_landing_pads, !NewRuntime);
563 InstrumentGlobals = !CompileKernel && !UsePageAliases &&
564 valueOr(Opts.hwasan_globals, NewRuntime);
566 if (!CompileKernel) {
567 if (InstrumentGlobals)
570 createHwasanCtorComdat();
572 bool InstrumentPersonalityFunctions =
573 valueOr(Opts.hwasan_instrument_personality_functions, NewRuntime);
574 if (InstrumentPersonalityFunctions)
575 instrumentPersonalityFunctions();
579 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
582 "__hwasan_tls",
nullptr,
590void HWAddressSanitizer::initializeCallbacks(
Module &M) {
592 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
594 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
596 if (UseMatchAllCallback) {
597 HwasanMemoryAccessCallbackSizedFnTy =
599 HwasanMemoryAccessCallbackFnTy =
601 HwasanMemTransferFnTy =
606 HwasanMemoryAccessCallbackSizedFnTy =
608 HwasanMemoryAccessCallbackFnTy =
610 HwasanMemTransferFnTy =
616 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
617 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
618 const std::string EndingStr = Recover ?
"_noabort" :
"";
620 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
621 M.getOrInsertFunction((Opts.hwasan_memory_access_callback_prefix +
622 TypeStr +
"N" + MatchAllStr + EndingStr)
624 HwasanMemoryAccessCallbackSizedFnTy);
628 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
629 M.getOrInsertFunction((Opts.hwasan_memory_access_callback_prefix +
630 TypeStr +
itostr(1ULL << AccessSizeIndex) +
631 MatchAllStr + EndingStr)
633 HwasanMemoryAccessCallbackFnTy);
637 const std::string MemIntrinCallbackPrefix =
638 (CompileKernel && !Opts.hwasan_kernel_mem_intrinsic_prefix)
640 : Opts.hwasan_memory_access_callback_prefix.str();
642 HwasanMemmove =
M.getOrInsertFunction(
643 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
644 HwasanMemcpy =
M.getOrInsertFunction(
645 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
646 HwasanMemset =
M.getOrInsertFunction(
647 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
649 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
650 PtrTy, Int8Ty, IntptrTy);
651 HwasanGenerateTagFunc =
652 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
654 HwasanRecordFrameRecordFunc =
655 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
661 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
673 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
677 return getOpaqueNoopCast(IRB, ShadowGlobal);
681 if (Mapping.isFixed()) {
682 return getOpaqueNoopCast(
684 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
687 if (Mapping.isInIfunc())
688 return getDynamicShadowIfunc(IRB);
692 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
695bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
711 if (!InstrumentStack)
718 if (!InstrumentGlobals)
728 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
740void HWAddressSanitizer::getInterestingMemoryOperands(
745 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
753 if (!Opts.hwasan_instrument_reads ||
754 ignoreAccess(ORE,
I, LI->getPointerOperand()))
756 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
757 LI->getType(), LI->getAlign());
759 if (!Opts.hwasan_instrument_writes ||
760 ignoreAccess(ORE,
I,
SI->getPointerOperand()))
763 SI->getValueOperand()->getType(),
SI->getAlign());
765 if (!Opts.hwasan_instrument_atomics ||
766 ignoreAccess(ORE,
I, RMW->getPointerOperand()))
768 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
769 RMW->getValOperand()->getType(), std::nullopt);
771 if (!Opts.hwasan_instrument_atomics ||
772 ignoreAccess(ORE,
I, XCHG->getPointerOperand()))
774 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
775 XCHG->getCompareOperand()->getType(),
778 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
779 if (!Opts.hwasan_instrument_byval || !CI->isByValArgument(ArgNo) ||
780 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
782 Type *Ty = CI->getParamByValType(ArgNo);
791 return LI->getPointerOperandIndex();
793 return SI->getPointerOperandIndex();
795 return RMW->getPointerOperandIndex();
797 return XCHG->getPointerOperandIndex();
823 if (Mapping.isFixed() && Mapping.offset() == 0)
829int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
830 unsigned AccessSizeIndex) {
839HWAddressSanitizer::ShadowTagCheckInfo
840HWAddressSanitizer::insertShadowTagCheck(
Value *Ptr,
Instruction *InsertBefore,
842 ShadowTagCheckInfo
R;
849 R.AddrLong = untagPointer(IRB,
R.PtrLong);
850 Value *Shadow = memToShadow(
R.AddrLong, IRB);
854 if (MatchAllTag.has_value()) {
856 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
857 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
861 TagMismatch, InsertBefore,
false,
867void HWAddressSanitizer::instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
868 unsigned AccessSizeIndex,
873 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
877 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
880 bool UseFixedShadowIntrinsic =
false;
888 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
889 uint16_t OffsetShifted = Mapping.offset() >> 32;
890 UseFixedShadowIntrinsic =
891 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
894 if (UseFixedShadowIntrinsic) {
897 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
898 : Intrinsic::hwasan_check_memaccess_fixedshadow,
899 {Ptr, ConstantInt::get(Int32Ty, AccessInfo),
900 ConstantInt::get(Int64Ty, Mapping.offset())});
903 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
904 : Intrinsic::hwasan_check_memaccess,
905 {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
909void HWAddressSanitizer::instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
910 unsigned AccessSizeIndex,
915 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
917 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
920 Value *OutOfShortGranuleTagRange =
923 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
929 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
946 switch (TargetTriple.
getArch()) {
970 "ebreak\naddiw x0, x11, " +
987 return (!Opts.hwasan_instrument_writes ||
988 ignoreAccess(ORE, MTI, MTI->getDest())) &&
989 (!Opts.hwasan_instrument_reads ||
990 ignoreAccess(ORE, MTI, MTI->getSource()));
993 return !Opts.hwasan_instrument_writes ||
994 ignoreAccess(ORE,
MI,
MI->getDest());
998void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1002 MI->getOperand(0),
MI->getOperand(1),
1005 if (UseMatchAllCallback)
1006 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1013 if (UseMatchAllCallback)
1014 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1017 MI->eraseFromParent();
1023 Value *Addr =
O.getPtr();
1042 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1044 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1045 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1047 if (InstrumentWithCalls) {
1049 if (UseMatchAllCallback)
1050 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1051 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1053 }
else if (OutlinedChecks) {
1054 instrumentMemAccessOutline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1057 instrumentMemAccessInline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1064 ConstantInt::get(IntptrTy, 8))};
1065 if (UseMatchAllCallback)
1066 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1067 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1069 untagPointerOperand(
O.getInsn(), Addr);
1076 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1077 if (!UseShortGranules)
1081 if (InstrumentWithCalls) {
1084 ConstantInt::get(IntptrTy, AlignedSize)});
1086 size_t ShadowSize =
Size >> Mapping.scale();
1088 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1097 if (
Size != AlignedSize) {
1098 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1099 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1108unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1110 return AllocaNo & TagMaskByte;
1122 static const unsigned FastMasks[] = {
1123 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1124 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1125 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1126 return FastMasks[AllocaNo % std::size(FastMasks)];
1130 if (TagMaskByte == 0xFF)
1133 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1141 if (Opts.hwasan_generate_tags_with_calls)
1144 return StackBaseTag;
1148 Value *FramePointerLong = getCachedFP(IRB);
1150 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1152 StackTag->
setName(
"hwasan.stack.base.tag");
1157 unsigned AllocaNo) {
1158 if (Opts.hwasan_generate_tags_with_calls)
1159 return getNextTagWithCall(IRB);
1161 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1165 Value *FramePointerLong = getCachedFP(IRB);
1167 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1169 UARTag->
setName(
"hwasan.uar.tag");
1177 Value *TaggedPtrLong;
1178 if (CompileKernel) {
1182 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1183 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1187 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1195 Value *UntaggedPtrLong;
1196 if (CompileKernel) {
1200 TagMaskByte << PointerTagShift));
1204 PtrLong, ConstantInt::get(PtrLong->
getType(),
1205 ~(TagMaskByte << PointerTagShift)));
1207 return UntaggedPtrLong;
1213 constexpr int SanitizerSlot = 6;
1216 return ThreadPtrGlobal;
1243void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1244 if (!Mapping.isInTls())
1245 ShadowBase = getShadowNonTls(IRB);
1246 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1247 ShadowBase = getDynamicShadowIfunc(IRB);
1249 if (!WithFrameRecord && ShadowBase)
1252 Value *SlotPtr =
nullptr;
1253 Value *ThreadLong =
nullptr;
1254 Value *ThreadLongMaybeUntagged =
nullptr;
1256 auto getThreadLongMaybeUntagged = [&]() {
1258 SlotPtr = getHwasanThreadSlotPtr(IRB);
1260 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1263 return TargetTriple.
isAArch64() ? ThreadLong
1264 : untagPointer(IRB, ThreadLong);
1267 if (WithFrameRecord) {
1268 switch (Opts.hwasan_record_stack_history) {
1272 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1273 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1277 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1279 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1282 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1292 "A stack history recording mode should've been selected.");
1298 if (!ThreadLongMaybeUntagged)
1299 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1306 ThreadLongMaybeUntagged,
1308 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1313void HWAddressSanitizer::instrumentLandingPads(
1315 for (
auto *LP : LandingPadVec) {
1339 auto *AI = KV.first;
1344 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1346 Value *AINoTagLong = untagPointer(IRB, AILong);
1347 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1350 Replacement->
setName(Name +
".hwasan");
1353 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1356 auto *
User =
U.getUser();
1362 auto TagStarts = [&]() {
1365 tagAlloca(IRB, AI,
Tag,
Size);
1374 tagAlloca(IRB, AI, UARTag, AlignedSize);
1376 auto EraseLifetimes = [&]() {
1377 for (
auto &
II :
Info.LifetimeStart)
1378 II->eraseFromParent();
1379 for (
auto &
II :
Info.LifetimeEnd)
1380 II->eraseFromParent();
1393 }
else if (DetectUseAfterScope && Opts.hwasan_strict_use_after_scope) {
1399 tagAlloca(IRB, AI,
Tag,
Size);
1405 tagAlloca(IRB, AI,
Tag,
Size);
1418 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1423 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1428bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1430 auto SkipHot = [&]() {
1431 if (!Opts.hwasan_percentile_cutoff_hot)
1436 if (!PSI || !PSI->hasProfileSummary()) {
1437 ++NumNoProfileSummaryFuncs;
1440 return PSI->isFunctionHotInCallGraphNthPercentile(
1441 *Opts.hwasan_percentile_cutoff_hot, &
F,
1445 auto SkipRandom = [&]() {
1446 if (!Opts.hwasan_random_rate)
1448 std::bernoulli_distribution
D(*Opts.hwasan_random_rate);
1452 bool Skip = SkipRandom() || SkipHot();
1457void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1459 if (&
F == HwasanCtorFunction)
1463 if (
F.hasFnAttribute(Attribute::Naked))
1466 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1469 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1475 if (
F.isPresplitCoroutine())
1483 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1486 NumInstrumentedFuncs++;
1497 if (InstrumentStack) {
1498 SIB.visit(ORE, Inst);
1507 if (!ignoreMemIntrinsic(ORE,
MI))
1513 initializeCallbacks(*
F.getParent());
1515 if (!LandingPadVec.
empty())
1516 instrumentLandingPads(LandingPadVec);
1522 F.setPersonalityFn(
nullptr);
1526 IntrinToInstrument.
empty())
1533 emitPrologue(EntryIRB,
1534 Opts.hwasan_record_stack_history !=
1536 Mapping.withFrameRecord() &&
1543 Value *StackTag = getStackBaseTag(EntryIRB);
1544 Value *UARTag = getUARTag(EntryIRB);
1547 BasicBlock *EntryBB = EntryIRB.GetInsertBlock();
1548 instrumentStack(ORE, SInfo, StackTag, UARTag, DT, PDT, LI);
1553 if (EntryBB != &
F.getEntryBlock()) {
1554 InsertPt =
F.getEntryBlock().begin();
1558 I.moveBefore(
F.getEntryBlock(), InsertPt);
1566 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1568 for (
auto &Operand : OperandsToInstrument)
1569 instrumentMemAccess(Operand, DTU, LI,
DL);
1572 if (Opts.hwasan_instrument_mem_intrinsics && !IntrinToInstrument.
empty()) {
1573 for (
auto *Inst : IntrinToInstrument)
1574 instrumentMemIntrinsic(Inst);
1577 ShadowBase =
nullptr;
1578 StackBaseTag =
nullptr;
1586 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1587 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1588 if (SizeInBytes != NewSize) {
1591 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1600 NewGV->copyAttributesFrom(GV);
1602 NewGV->copyMetadata(GV, 0);
1603 NewGV->setAlignment(
1623 const uint64_t MaxDescriptorSize = 0xfffff0;
1624 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1625 DescriptorPos += MaxDescriptorSize) {
1628 nullptr, GV->
getName() +
".hwasan.descriptor");
1634 ConstantInt::get(Int64Ty, DescriptorPos)),
1636 uint32_t
Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1637 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (uint32_t(
Tag) << 24));
1638 Descriptor->setComdat(NewGV->getComdat());
1640 Descriptor->setSection(
"hwasan_globals");
1641 Descriptor->setMetadata(LLVMContext::MD_associated,
1649 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1654 Alias->takeName(GV);
1659void HWAddressSanitizer::instrumentGlobals() {
1660 std::vector<GlobalVariable *> Globals;
1673 if (Opts.hwasan_all_globals) {
1685 Globals.push_back(&GV);
1689 Hasher.
update(
M.getSourceFileName());
1692 uint8_t
Tag = Hash[0];
1694 assert(TagMaskByte >= 16);
1702 instrumentGlobal(GV,
Tag++);
1706void HWAddressSanitizer::instrumentPersonalityFunctions() {
1715 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
1716 F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
1719 if (
F.hasPersonalityFn()) {
1720 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1721 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1722 PersonalityFns[
nullptr].push_back(&
F);
1726 if (PersonalityFns.
empty())
1730 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1731 PtrTy, PtrTy, PtrTy, PtrTy);
1732 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1733 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1735 for (
auto &
P : PersonalityFns) {
1738 ThunkName += (
"." +
P.first->getName()).str();
1740 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1749 return F->hasFnAttribute(
"branch-target-enforcement");
1751 ThunkFn->addFnAttr(
"branch-target-enforcement");
1755 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1761 HwasanPersonalityWrapper,
1762 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1763 ThunkFn->getArg(3), ThunkFn->getArg(4),
1770 F->setPersonalityFn(ThunkFn);
1774void HWAddressSanitizer::ShadowMapping::init(
const InstrumentationOptions &Opts,
1776 bool InstrumentWithCalls,
1777 bool CompileKernel) {
1780 Kind = OffsetKind::kTls;
1781 WithFrameRecord =
true;
1787 Kind = OffsetKind::kGlobal;
1788 }
else if (CompileKernel || InstrumentWithCalls) {
1790 WithFrameRecord =
false;
1793 WithFrameRecord =
valueOr(Opts.hwasan_with_frame_record, WithFrameRecord);
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="")
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.
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