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 = InstrumentationOptions::Global;
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());
531 HwasanCtorFunction =
nullptr;
539 UseShortGranules =
valueOr(Opts.hwasan_use_short_granules, NewRuntime);
542 !
valueOr(Opts.hwasan_inline_all_checks, Recover);
546 valueOr(Opts.hwasan_inline_fast_path_checks,
549 if (Opts.hwasan_match_all_tag) {
550 if (*Opts.hwasan_match_all_tag != -1) {
551 MatchAllTag = *Opts.hwasan_match_all_tag & 0xFF;
553 }
else if (CompileKernel) {
556 UseMatchAllCallback = !CompileKernel && MatchAllTag.has_value();
559 InstrumentLandingPads =
560 valueOr(Opts.hwasan_instrument_landing_pads, !NewRuntime);
562 InstrumentGlobals = !CompileKernel && !UsePageAliases &&
563 valueOr(Opts.hwasan_globals, NewRuntime);
565 if (!CompileKernel) {
566 if (InstrumentGlobals)
569 createHwasanCtorComdat();
571 bool InstrumentPersonalityFunctions =
572 valueOr(Opts.hwasan_instrument_personality_functions, NewRuntime);
573 if (InstrumentPersonalityFunctions)
574 instrumentPersonalityFunctions();
578 ThreadPtrGlobal =
M.getOrInsertGlobal(
"__hwasan_tls", IntptrTy, [&] {
581 "__hwasan_tls",
nullptr,
589void HWAddressSanitizer::initializeCallbacks(
Module &M) {
591 const std::string MatchAllStr = UseMatchAllCallback ?
"_match_all" :
"";
593 *HwasanMemoryAccessCallbackFnTy, *HwasanMemTransferFnTy,
595 if (UseMatchAllCallback) {
596 HwasanMemoryAccessCallbackSizedFnTy =
598 HwasanMemoryAccessCallbackFnTy =
600 HwasanMemTransferFnTy =
605 HwasanMemoryAccessCallbackSizedFnTy =
607 HwasanMemoryAccessCallbackFnTy =
609 HwasanMemTransferFnTy =
615 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
616 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
617 const std::string EndingStr = Recover ?
"_noabort" :
"";
619 HwasanMemoryAccessCallbackSized[AccessIsWrite] =
620 M.getOrInsertFunction((Opts.hwasan_memory_access_callback_prefix +
621 TypeStr +
"N" + MatchAllStr + EndingStr)
623 HwasanMemoryAccessCallbackSizedFnTy);
627 HwasanMemoryAccessCallback[AccessIsWrite][AccessSizeIndex] =
628 M.getOrInsertFunction((Opts.hwasan_memory_access_callback_prefix +
629 TypeStr +
itostr(1ULL << AccessSizeIndex) +
630 MatchAllStr + EndingStr)
632 HwasanMemoryAccessCallbackFnTy);
636 const std::string MemIntrinCallbackPrefix =
637 (CompileKernel && !Opts.hwasan_kernel_mem_intrinsic_prefix)
639 : Opts.hwasan_memory_access_callback_prefix.str();
641 HwasanMemmove =
M.getOrInsertFunction(
642 MemIntrinCallbackPrefix +
"memmove" + MatchAllStr, HwasanMemTransferFnTy);
643 HwasanMemcpy =
M.getOrInsertFunction(
644 MemIntrinCallbackPrefix +
"memcpy" + MatchAllStr, HwasanMemTransferFnTy);
645 HwasanMemset =
M.getOrInsertFunction(
646 MemIntrinCallbackPrefix +
"memset" + MatchAllStr, HwasanMemsetFnTy);
648 HwasanTagMemoryFunc =
M.getOrInsertFunction(
"__hwasan_tag_memory", VoidTy,
649 PtrTy, Int8Ty, IntptrTy);
650 HwasanGenerateTagFunc =
651 M.getOrInsertFunction(
"__hwasan_generate_tag", Int8Ty);
653 HwasanRecordFrameRecordFunc =
654 M.getOrInsertFunction(
"__hwasan_add_frame_record", VoidTy, Int64Ty);
660 M.getOrInsertFunction(
"__hwasan_handle_vfork", VoidTy, IntptrTy);
672 return IRB.
CreateCall(Asm, {Val},
".hwasan.shadow");
676 return getOpaqueNoopCast(IRB, ShadowGlobal);
680 if (Mapping.isFixed()) {
681 return getOpaqueNoopCast(
683 ConstantInt::get(IntptrTy, Mapping.offset()), PtrTy));
686 if (Mapping.isInIfunc())
687 return getDynamicShadowIfunc(IRB);
691 return IRB.
CreateLoad(PtrTy, GlobalDynamicAddress);
694bool HWAddressSanitizer::ignoreAccessWithoutRemark(
Instruction *Inst,
710 if (!InstrumentStack)
717 if (!InstrumentGlobals)
727 bool Ignored = ignoreAccessWithoutRemark(Inst, Ptr);
739void HWAddressSanitizer::getInterestingMemoryOperands(
744 if (
I->hasMetadata(LLVMContext::MD_nosanitize))
752 if (!Opts.hwasan_instrument_reads ||
753 ignoreAccess(ORE,
I, LI->getPointerOperand()))
755 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
756 LI->getType(), LI->getAlign());
758 if (!Opts.hwasan_instrument_writes ||
759 ignoreAccess(ORE,
I,
SI->getPointerOperand()))
762 SI->getValueOperand()->getType(),
SI->getAlign());
764 if (!Opts.hwasan_instrument_atomics ||
765 ignoreAccess(ORE,
I, RMW->getPointerOperand()))
767 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
768 RMW->getValOperand()->getType(), std::nullopt);
770 if (!Opts.hwasan_instrument_atomics ||
771 ignoreAccess(ORE,
I, XCHG->getPointerOperand()))
773 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
774 XCHG->getCompareOperand()->getType(),
777 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
778 if (!Opts.hwasan_instrument_byval || !CI->isByValArgument(ArgNo) ||
779 ignoreAccess(ORE,
I, CI->getArgOperand(ArgNo)))
781 Type *Ty = CI->getParamByValType(ArgNo);
790 return LI->getPointerOperandIndex();
792 return SI->getPointerOperandIndex();
794 return RMW->getPointerOperandIndex();
796 return XCHG->getPointerOperandIndex();
822 if (Mapping.isFixed() && Mapping.offset() == 0)
828int64_t HWAddressSanitizer::getAccessInfo(
bool IsWrite,
829 unsigned AccessSizeIndex) {
838HWAddressSanitizer::ShadowTagCheckInfo
839HWAddressSanitizer::insertShadowTagCheck(
Value *Ptr,
Instruction *InsertBefore,
841 ShadowTagCheckInfo
R;
848 R.AddrLong = untagPointer(IRB,
R.PtrLong);
849 Value *Shadow = memToShadow(
R.AddrLong, IRB);
853 if (MatchAllTag.has_value()) {
855 R.PtrTag, ConstantInt::get(
R.PtrTag->getType(), *MatchAllTag));
856 TagMismatch = IRB.
CreateAnd(TagMismatch, TagNotIgnored);
860 TagMismatch, InsertBefore,
false,
866void HWAddressSanitizer::instrumentMemAccessOutline(
Value *Ptr,
bool IsWrite,
867 unsigned AccessSizeIndex,
872 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
876 insertShadowTagCheck(Ptr, InsertBefore, DTU, LI).TagMismatchTerm;
879 bool UseFixedShadowIntrinsic =
false;
887 if (TargetTriple.
isAArch64() && Mapping.isFixed()) {
888 uint16_t OffsetShifted = Mapping.offset() >> 32;
889 UseFixedShadowIntrinsic =
890 static_cast<uint64_t>(OffsetShifted) << 32 == Mapping.offset();
893 if (UseFixedShadowIntrinsic) {
896 ? Intrinsic::hwasan_check_memaccess_shortgranules_fixedshadow
897 : Intrinsic::hwasan_check_memaccess_fixedshadow,
898 {Ptr, ConstantInt::get(Int32Ty, AccessInfo),
899 ConstantInt::get(Int64Ty, Mapping.offset())});
902 UseShortGranules ? Intrinsic::hwasan_check_memaccess_shortgranules
903 : Intrinsic::hwasan_check_memaccess,
904 {ShadowBase, Ptr, ConstantInt::get(Int32Ty, AccessInfo)});
908void HWAddressSanitizer::instrumentMemAccessInline(
Value *Ptr,
bool IsWrite,
909 unsigned AccessSizeIndex,
914 const int64_t AccessInfo = getAccessInfo(IsWrite, AccessSizeIndex);
916 ShadowTagCheckInfo TCI = insertShadowTagCheck(Ptr, InsertBefore, DTU, LI);
919 Value *OutOfShortGranuleTagRange =
922 OutOfShortGranuleTagRange, TCI.TagMismatchTerm, !Recover,
928 PtrLowBits, ConstantInt::get(Int8Ty, (1 << AccessSizeIndex) - 1));
945 switch (TargetTriple.
getArch()) {
969 "ebreak\naddiw x0, x11, " +
986 return (!Opts.hwasan_instrument_writes ||
987 ignoreAccess(ORE, MTI, MTI->getDest())) &&
988 (!Opts.hwasan_instrument_reads ||
989 ignoreAccess(ORE, MTI, MTI->getSource()));
992 return !Opts.hwasan_instrument_writes ||
993 ignoreAccess(ORE,
MI,
MI->getDest());
997void HWAddressSanitizer::instrumentMemIntrinsic(
MemIntrinsic *
MI) {
1001 MI->getOperand(0),
MI->getOperand(1),
1004 if (UseMatchAllCallback)
1005 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1012 if (UseMatchAllCallback)
1013 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1016 MI->eraseFromParent();
1022 Value *Addr =
O.getPtr();
1041 if (!
O.TypeStoreSize.isScalable() &&
isPowerOf2_64(
O.TypeStoreSize) &&
1043 (!
O.Alignment || *
O.Alignment >= Mapping.getObjectAlignment() ||
1044 *
O.Alignment >=
O.TypeStoreSize / 8)) {
1046 if (InstrumentWithCalls) {
1048 if (UseMatchAllCallback)
1049 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1050 IRB.
CreateCall(HwasanMemoryAccessCallback[
O.IsWrite][AccessSizeIndex],
1052 }
else if (OutlinedChecks) {
1053 instrumentMemAccessOutline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1056 instrumentMemAccessInline(Addr,
O.IsWrite, AccessSizeIndex,
O.getInsn(),
1063 ConstantInt::get(IntptrTy, 8))};
1064 if (UseMatchAllCallback)
1065 Args.emplace_back(ConstantInt::get(Int8Ty, *MatchAllTag));
1066 IRB.
CreateCall(HwasanMemoryAccessCallbackSized[
O.IsWrite], Args);
1068 untagPointerOperand(
O.getInsn(), Addr);
1075 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1076 if (!UseShortGranules)
1080 if (InstrumentWithCalls) {
1083 ConstantInt::get(IntptrTy, AlignedSize)});
1085 size_t ShadowSize =
Size >> Mapping.scale();
1087 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1096 if (
Size != AlignedSize) {
1097 const uint8_t SizeRemainder =
Size % Mapping.getObjectAlignment().value();
1098 IRB.
CreateStore(ConstantInt::get(Int8Ty, SizeRemainder),
1107unsigned HWAddressSanitizer::retagMask(
unsigned AllocaNo) {
1109 return AllocaNo & TagMaskByte;
1121 static const unsigned FastMasks[] = {
1122 0, 128, 64, 192, 32, 96, 224, 112, 240, 48, 16, 120,
1123 248, 56, 24, 8, 124, 252, 60, 28, 12, 4, 126, 254,
1124 62, 30, 14, 6, 2, 127, 63, 31, 15, 7, 3, 1};
1125 return FastMasks[AllocaNo % std::size(FastMasks)];
1129 if (TagMaskByte == 0xFF)
1132 ConstantInt::get(OldTag->
getType(), TagMaskByte));
1140 if (Opts.hwasan_generate_tags_with_calls)
1143 return StackBaseTag;
1147 Value *FramePointerLong = getCachedFP(IRB);
1149 applyTagMask(IRB, IRB.
CreateXor(FramePointerLong,
1151 StackTag->
setName(
"hwasan.stack.base.tag");
1156 unsigned AllocaNo) {
1157 if (Opts.hwasan_generate_tags_with_calls)
1158 return getNextTagWithCall(IRB);
1160 StackTag, ConstantInt::get(StackTag->
getType(), retagMask(AllocaNo)));
1164 Value *FramePointerLong = getCachedFP(IRB);
1166 applyTagMask(IRB, IRB.
CreateLShr(FramePointerLong, PointerTagShift));
1168 UARTag->
setName(
"hwasan.uar.tag");
1176 Value *TaggedPtrLong;
1177 if (CompileKernel) {
1181 ConstantInt::get(IntptrTy, (1ULL << PointerTagShift) - 1));
1182 TaggedPtrLong = IRB.
CreateAnd(PtrLong, ShiftedTag);
1186 TaggedPtrLong = IRB.
CreateOr(PtrLong, ShiftedTag);
1194 Value *UntaggedPtrLong;
1195 if (CompileKernel) {
1199 TagMaskByte << PointerTagShift));
1203 PtrLong, ConstantInt::get(PtrLong->
getType(),
1204 ~(TagMaskByte << PointerTagShift)));
1206 return UntaggedPtrLong;
1212 constexpr int SanitizerSlot = 6;
1215 return ThreadPtrGlobal;
1242void HWAddressSanitizer::emitPrologue(
IRBuilder<> &IRB,
bool WithFrameRecord) {
1243 if (!Mapping.isInTls())
1244 ShadowBase = getShadowNonTls(IRB);
1245 else if (!WithFrameRecord && TargetTriple.
isAndroid())
1246 ShadowBase = getDynamicShadowIfunc(IRB);
1248 if (!WithFrameRecord && ShadowBase)
1251 Value *SlotPtr =
nullptr;
1252 Value *ThreadLong =
nullptr;
1253 Value *ThreadLongMaybeUntagged =
nullptr;
1255 auto getThreadLongMaybeUntagged = [&]() {
1257 SlotPtr = getHwasanThreadSlotPtr(IRB);
1259 ThreadLong = IRB.
CreateLoad(IntptrTy, SlotPtr);
1262 return TargetTriple.
isAArch64() ? ThreadLong
1263 : untagPointer(IRB, ThreadLong);
1266 if (WithFrameRecord) {
1267 switch (Opts.hwasan_record_stack_history) {
1271 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1272 IRB.
CreateCall(HwasanRecordFrameRecordFunc, {FrameRecordInfo});
1276 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1278 StackBaseTag = IRB.
CreateAShr(ThreadLong, 3);
1281 Value *FrameRecordInfo = getFrameRecordInfo(IRB);
1291 "A stack history recording mode should've been selected.");
1297 if (!ThreadLongMaybeUntagged)
1298 ThreadLongMaybeUntagged = getThreadLongMaybeUntagged();
1305 ThreadLongMaybeUntagged,
1307 ConstantInt::get(IntptrTy, 1),
"hwasan.shadow");
1312void HWAddressSanitizer::instrumentLandingPads(
1314 for (
auto *LP : LandingPadVec) {
1338 auto *AI = KV.first;
1343 Value *
Tag = getAllocaTag(IRB, StackTag,
N);
1345 Value *AINoTagLong = untagPointer(IRB, AILong);
1346 Value *Replacement = tagPointer(IRB, AI->
getType(), AINoTagLong,
Tag);
1349 Replacement->
setName(Name +
".hwasan");
1352 size_t AlignedSize =
alignTo(
Size, Mapping.getObjectAlignment());
1355 auto *
User =
U.getUser();
1361 auto TagStarts = [&]() {
1364 tagAlloca(IRB, AI,
Tag,
Size);
1373 tagAlloca(IRB, AI, UARTag, AlignedSize);
1375 auto EraseLifetimes = [&]() {
1376 for (
auto &
II :
Info.LifetimeStart)
1377 II->eraseFromParent();
1378 for (
auto &
II :
Info.LifetimeEnd)
1379 II->eraseFromParent();
1392 }
else if (DetectUseAfterScope && Opts.hwasan_strict_use_after_scope) {
1398 tagAlloca(IRB, AI,
Tag,
Size);
1404 tagAlloca(IRB, AI,
Tag,
Size);
1417 <<
"Skipped: F=" <<
ore::NV(
"Function", &
F);
1422 <<
"Sanitized: F=" <<
ore::NV(
"Function", &
F);
1427bool HWAddressSanitizer::selectiveInstrumentationShouldSkip(
1429 auto SkipHot = [&]() {
1430 if (!Opts.hwasan_percentile_cutoff_hot)
1435 if (!PSI || !PSI->hasProfileSummary()) {
1436 ++NumNoProfileSummaryFuncs;
1439 return PSI->isFunctionHotInCallGraphNthPercentile(
1440 *Opts.hwasan_percentile_cutoff_hot, &
F,
1444 auto SkipRandom = [&]() {
1445 if (!Opts.hwasan_random_rate)
1447 std::bernoulli_distribution
D(*Opts.hwasan_random_rate);
1451 bool Skip = SkipRandom() || SkipHot();
1456void HWAddressSanitizer::sanitizeFunction(
Function &
F,
1458 if (&
F == HwasanCtorFunction)
1462 if (
F.hasFnAttribute(Attribute::Naked))
1465 if (!
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1471 if (
F.isPresplitCoroutine())
1479 if (selectiveInstrumentationShouldSkip(
F,
FAM))
1482 NumInstrumentedFuncs++;
1493 if (InstrumentStack) {
1494 SIB.visit(ORE, Inst);
1503 if (!ignoreMemIntrinsic(ORE,
MI))
1509 initializeCallbacks(*
F.getParent());
1511 if (!LandingPadVec.
empty())
1512 instrumentLandingPads(LandingPadVec);
1518 F.setPersonalityFn(
nullptr);
1522 IntrinToInstrument.
empty())
1529 emitPrologue(EntryIRB,
1530 Opts.hwasan_record_stack_history !=
1532 Mapping.withFrameRecord() &&
1539 Value *StackTag = getStackBaseTag(EntryIRB);
1540 Value *UARTag = getUARTag(EntryIRB);
1541 instrumentStack(ORE, SInfo, StackTag, UARTag, DT, PDT, LI);
1547 if (EntryIRB.GetInsertBlock() != &
F.getEntryBlock()) {
1548 InsertPt =
F.getEntryBlock().begin();
1553 I.moveBefore(
F.getEntryBlock(), InsertPt);
1560 DomTreeUpdater DTU(DT, PDT, DomTreeUpdater::UpdateStrategy::Lazy);
1562 for (
auto &Operand : OperandsToInstrument)
1563 instrumentMemAccess(Operand, DTU, LI,
DL);
1566 if (Opts.hwasan_instrument_mem_intrinsics && !IntrinToInstrument.
empty()) {
1567 for (
auto *Inst : IntrinToInstrument)
1568 instrumentMemIntrinsic(Inst);
1571 ShadowBase =
nullptr;
1572 StackBaseTag =
nullptr;
1580 M.getDataLayout().getTypeAllocSize(Initializer->
getType());
1581 uint64_t NewSize =
alignTo(SizeInBytes, Mapping.getObjectAlignment());
1582 if (SizeInBytes != NewSize) {
1585 std::vector<uint8_t>
Init(NewSize - SizeInBytes, 0);
1594 NewGV->copyAttributesFrom(GV);
1596 NewGV->copyMetadata(GV, 0);
1597 NewGV->setAlignment(
1617 const uint64_t MaxDescriptorSize = 0xfffff0;
1618 for (
uint64_t DescriptorPos = 0; DescriptorPos < SizeInBytes;
1619 DescriptorPos += MaxDescriptorSize) {
1622 nullptr, GV->
getName() +
".hwasan.descriptor");
1628 ConstantInt::get(Int64Ty, DescriptorPos)),
1630 uint32_t
Size = std::min(SizeInBytes - DescriptorPos, MaxDescriptorSize);
1631 auto *SizeAndTag = ConstantInt::get(Int32Ty,
Size | (uint32_t(
Tag) << 24));
1632 Descriptor->setComdat(NewGV->getComdat());
1634 Descriptor->setSection(
"hwasan_globals");
1635 Descriptor->setMetadata(LLVMContext::MD_associated,
1643 ConstantInt::get(Int64Ty,
uint64_t(
Tag) << PointerTagShift)),
1648 Alias->takeName(GV);
1653void HWAddressSanitizer::instrumentGlobals() {
1654 std::vector<GlobalVariable *> Globals;
1667 if (Opts.hwasan_all_globals) {
1679 Globals.push_back(&GV);
1683 Hasher.
update(
M.getSourceFileName());
1686 uint8_t
Tag = Hash[0];
1688 assert(TagMaskByte >= 16);
1696 instrumentGlobal(GV,
Tag++);
1700void HWAddressSanitizer::instrumentPersonalityFunctions() {
1709 if (
F.isDeclaration() || !
F.hasFnAttribute(Attribute::SanitizeHWAddress))
1712 if (
F.hasPersonalityFn()) {
1713 PersonalityFns[
F.getPersonalityFn()->stripPointerCasts()].push_back(&
F);
1714 }
else if (!
F.hasFnAttribute(Attribute::NoUnwind)) {
1715 PersonalityFns[
nullptr].push_back(&
F);
1719 if (PersonalityFns.
empty())
1723 "__hwasan_personality_wrapper", Int32Ty, Int32Ty, Int32Ty, Int64Ty, PtrTy,
1724 PtrTy, PtrTy, PtrTy, PtrTy);
1725 FunctionCallee UnwindGetGR =
M.getOrInsertFunction(
"_Unwind_GetGR", VoidTy);
1726 FunctionCallee UnwindGetCFA =
M.getOrInsertFunction(
"_Unwind_GetCFA", VoidTy);
1728 for (
auto &
P : PersonalityFns) {
1731 ThunkName += (
"." +
P.first->getName()).str();
1733 Int32Ty, {Int32Ty, Int32Ty, Int64Ty, PtrTy, PtrTy},
false);
1742 return F->hasFnAttribute(
"branch-target-enforcement");
1744 ThunkFn->addFnAttr(
"branch-target-enforcement");
1748 ThunkFn->setComdat(
M.getOrInsertComdat(ThunkName));
1754 HwasanPersonalityWrapper,
1755 {ThunkFn->getArg(0), ThunkFn->getArg(1), ThunkFn->getArg(2),
1756 ThunkFn->getArg(3), ThunkFn->getArg(4),
1763 F->setPersonalityFn(ThunkFn);
1767void HWAddressSanitizer::ShadowMapping::init(
const InstrumentationOptions &Opts,
1769 bool InstrumentWithCalls,
1770 bool CompileKernel) {
1773 Kind = OffsetKind::kTls;
1774 WithFrameRecord =
true;
1780 Kind = OffsetKind::kGlobal;
1781 }
else if (CompileKernel || InstrumentWithCalls) {
1783 WithFrameRecord =
false;
1786 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,...
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