96#define DEBUG_TYPE "asan"
102 std::numeric_limits<uint64_t>::max();
143 "__asan_unregister_image_globals";
156 "__asan_stack_malloc_always_";
170 "__asan_option_detect_stack_use_after_return";
173 "__asan_shadow_memory_dynamic_address";
199 "asan-kernel",
cl::desc(
"Enable KernelAddressSanitizer instrumentation"),
204 cl::desc(
"Enable recovery mode (continue-after-error)."),
208 "asan-guard-against-version-mismatch",
214 cl::desc(
"instrument read instructions"),
218 "asan-instrument-writes",
cl::desc(
"instrument write instructions"),
227 "asan-instrument-atomics",
237 "asan-always-slow-path",
242 "asan-force-dynamic-shadow",
243 cl::desc(
"Load shadow address into a local variable for each function"),
248 cl::desc(
"Access dynamic shadow through an ifunc global on "
249 "platforms that support this"),
254 cl::desc(
"Address space for pointers to the shadow map"),
258 "asan-with-ifunc-suppress-remat",
259 cl::desc(
"Suppress rematerialization of dynamic shadow address by passing "
260 "it through inline asm in prologue."),
268 "asan-max-ins-per-bb",
cl::init(10000),
269 cl::desc(
"maximal number of instructions to instrument in any given BB"),
276 "asan-max-inline-poisoning-size",
278 "Inline shadow poisoning for blocks up to the given size in bytes."),
282 "asan-use-after-return",
283 cl::desc(
"Sets the mode of detection for stack-use-after-return."),
286 "Never detect stack use after return."),
289 "Detect stack use after return if "
290 "binary flag 'ASAN_OPTIONS=detect_stack_use_after_return' is set."),
292 "Always detect stack use after return.")),
296 cl::desc(
"Create redzones for byval "
297 "arguments (extra copy "
302 cl::desc(
"Check stack-use-after-scope"),
311 cl::desc(
"Handle C++ initializer order"),
315 "asan-detect-invalid-pointer-pair",
320 "asan-detect-invalid-pointer-cmp",
325 "asan-detect-invalid-pointer-sub",
330 "asan-realign-stack",
331 cl::desc(
"Realign stack to the value of this flag (power of two)"),
335 "asan-instrumentation-with-call-threshold",
336 cl::desc(
"If the function being instrumented contains more than "
337 "this number of memory accesses, use callbacks instead of "
338 "inline checks (-1 means never use callbacks)."),
342 "asan-memory-access-callback-prefix",
347 "asan-kernel-mem-intrinsic-prefix",
353 cl::desc(
"instrument dynamic allocas"),
357 "asan-skip-promotable-allocas",
362 "asan-constructor-kind",
363 cl::desc(
"Sets the ASan constructor kind"),
366 "Use global constructors")),
373 cl::desc(
"scale of asan shadow mapping"),
378 cl::desc(
"offset of asan shadow mapping [EXPERIMENTAL]"),
392 "asan-opt-same-temp",
cl::desc(
"Instrument the same temp just once"),
396 cl::desc(
"Don't instrument scalar globals"),
400 "asan-opt-stack",
cl::desc(
"Don't instrument scalar stack variables"),
404 "asan-stack-dynamic-alloca",
409 "asan-force-experiment",
415 cl::desc(
"Use private aliases for global variables"),
420 cl::desc(
"Use odr indicators to improve ODR reporting"),
425 cl::desc(
"Use linker features to support dead "
426 "code stripping of globals"),
433 cl::desc(
"Place ASan constructors in comdat sections"),
437 "asan-destructor-kind",
438 cl::desc(
"Sets the ASan destructor kind. The default is to use the value "
439 "provided to the pass constructor"),
442 "Use global destructors")),
447 "asan-instrument-address-spaces",
448 cl::desc(
"Only instrument variables in the specified address spaces."),
471STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
472STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
474 "Number of optimized accesses to global vars");
476 "Number of optimized accesses to stack vars");
485struct ShadowMapping {
496 bool IsAndroid = TargetTriple.
isAndroid();
499 bool IsMacOS = TargetTriple.
isMacOSX();
502 bool IsPS = TargetTriple.
isPS();
508 bool IsMIPSN32ABI = TargetTriple.
isABIN32();
509 bool IsMIPS32 = TargetTriple.
isMIPS32();
510 bool IsMIPS64 = TargetTriple.
isMIPS64();
511 bool IsArmOrThumb = TargetTriple.
isARM() || TargetTriple.
isThumb();
518 bool IsAMDGPU = TargetTriple.
isAMDGPU();
520 bool IsWasm = TargetTriple.
isWasm();
521 bool IsBPF = TargetTriple.
isBPF();
523 ShadowMapping Mapping;
530 if (LongSize == 32) {
533 else if (IsMIPSN32ABI)
559 else if (IsFreeBSD && IsAArch64)
561 else if (IsFreeBSD && !IsMIPS64) {
566 }
else if (IsNetBSD) {
573 else if (IsLinux && IsX86_64) {
579 }
else if (IsWindows && IsX86_64) {
585 else if (IsMacOS && IsAArch64)
589 else if (IsLoongArch64)
596 else if (IsHaiku && IsX86_64)
618 Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS &&
619 !IsRISCV64 && !IsLoongArch64 &&
620 !(Mapping.Offset & (Mapping.Offset - 1)) &&
622 Mapping.InGlobal =
ClWithIfunc && IsAndroid && IsArmOrThumb;
629 int *MappingScale,
bool *OrShadowOffset) {
631 *ShadowBase = Mapping.Offset;
632 *MappingScale = Mapping.Scale;
633 *OrShadowOffset = Mapping.OrShadowOffset;
652 if (!
F.doesNotAccessMemory()) {
653 bool WritesMemory = !
F.onlyReadsMemory();
654 bool ReadsMemory = !
F.onlyWritesMemory();
655 if ((WritesMemory && !ReadsMemory) ||
F.onlyAccessesArgMemory()) {
656 F.removeFnAttr(Attribute::Memory);
662 if (
A.hasAttribute(Attribute::WriteOnly)) {
663 A.removeAttr(Attribute::WriteOnly);
671 F.addFnAttr(Attribute::NoBuiltin);
692 return std::max(32U, 1U << MappingScale);
710class RuntimeCallInserter {
712 bool TrackInsertedCalls =
false;
716 RuntimeCallInserter(Function &Fn) : OwnerFn(&Fn) {
718 auto Personality = classifyEHPersonality(Fn.getPersonalityFn());
719 if (isScopedEHPersonality(Personality))
720 TrackInsertedCalls = true;
724 ~RuntimeCallInserter() {
725 if (InsertedCalls.
empty())
727 assert(TrackInsertedCalls &&
"Calls were wrongly tracked");
729 DenseMap<BasicBlock *, ColorVector> BlockColors =
colorEHFunclets(*OwnerFn);
730 for (CallInst *CI : InsertedCalls) {
732 assert(BB &&
"Instruction doesn't belong to a BasicBlock");
734 "Instruction doesn't belong to the expected Function!");
742 if (Colors.
size() != 1) {
744 "Instruction's BasicBlock is not monochromatic");
751 if (EHPadIt != Color->end() && EHPadIt->isEHPad()) {
755 OB, CI->getIterator());
756 NewCall->copyMetadata(*CI);
757 CI->replaceAllUsesWith(NewCall);
758 CI->eraseFromParent();
763 CallInst *createRuntimeCall(
IRBuilder<> &IRB, FunctionCallee Callee,
765 const Twine &
Name =
"") {
768 CallInst *Inst = IRB.
CreateCall(Callee, Args, Name,
nullptr);
769 if (TrackInsertedCalls)
770 InsertedCalls.push_back(Inst);
776struct AddressSanitizer {
777 AddressSanitizer(
Module &M,
const StackSafetyGlobalInfo *SSGI,
778 int InstrumentationWithCallsThreshold,
779 uint32_t MaxInlinePoisoningSize,
bool CompileKernel =
false,
780 bool Recover =
false,
bool UseAfterScope =
false,
782 AsanDetectStackUseAfterReturnMode::Runtime)
791 InstrumentationWithCallsThreshold(
794 : InstrumentationWithCallsThreshold),
797 : MaxInlinePoisoningSize) {
798 C = &(
M.getContext());
799 DL = &
M.getDataLayout();
800 LongSize =
M.getDataLayout().getPointerSizeInBits();
801 IntptrTy = Type::getIntNTy(*
C, LongSize);
802 PtrTy = PointerType::getUnqual(*
C);
804 TargetTriple =
M.getTargetTriple();
808 assert(this->UseAfterReturn != AsanDetectStackUseAfterReturnMode::Invalid);
816 bool isInterestingAlloca(
const AllocaInst &AI);
818 bool ignoreAccess(Instruction *Inst,
Value *Ptr);
820 Instruction *
I, SmallVectorImpl<InterestingMemoryOperand> &Interesting,
821 const TargetTransformInfo *
TTI);
823 void instrumentMop(ObjectSizeOffsetVisitor &ObjSizeVis,
824 InterestingMemoryOperand &O,
bool UseCalls,
825 const DataLayout &
DL, RuntimeCallInserter &RTCI);
826 void instrumentPointerComparisonOrSubtraction(Instruction *
I,
827 RuntimeCallInserter &RTCI);
829 Value *Addr, MaybeAlign Alignment,
830 uint32_t TypeStoreSize,
bool IsWrite,
831 Value *SizeArgument,
bool UseCalls, uint32_t Exp,
832 RuntimeCallInserter &RTCI);
833 Instruction *instrumentAMDGPUAddress(Instruction *OrigIns,
834 Instruction *InsertBefore,
Value *Addr,
835 uint32_t TypeStoreSize,
bool IsWrite,
836 Value *SizeArgument);
839 void instrumentUnusualSizeOrAlignment(Instruction *
I,
840 Instruction *InsertBefore,
Value *Addr,
841 TypeSize TypeStoreSize,
bool IsWrite,
842 Value *SizeArgument,
bool UseCalls,
844 RuntimeCallInserter &RTCI);
845 void instrumentMaskedLoadOrStore(AddressSanitizer *
Pass,
const DataLayout &
DL,
848 MaybeAlign Alignment,
unsigned Granularity,
849 Type *OpType,
bool IsWrite,
850 Value *SizeArgument,
bool UseCalls,
851 uint32_t Exp, RuntimeCallInserter &RTCI);
853 Value *ShadowValue, uint32_t TypeStoreSize);
855 bool IsWrite,
size_t AccessSizeIndex,
856 Value *SizeArgument, uint32_t Exp,
857 RuntimeCallInserter &RTCI);
858 void instrumentMemIntrinsic(MemIntrinsic *
MI, RuntimeCallInserter &RTCI);
860 bool suppressInstrumentationSiteForDebug(
int &Instrumented);
861 bool instrumentFunction(Function &
F,
const TargetLibraryInfo *TLI,
862 const TargetTransformInfo *
TTI);
863 bool maybeInsertAsanInitAtFunctionEntry(Function &
F);
864 bool maybeInsertDynamicShadowAtFunctionEntry(Function &
F);
865 void markEscapedLocalAllocas(Function &
F);
866 void markCatchParametersAsUninteresting(Function &
F);
869 friend struct FunctionStackPoisoner;
871 void initializeCallbacks(
const TargetLibraryInfo *TLI);
873 bool LooksLikeCodeInBug11395(Instruction *
I);
874 bool GlobalIsLinkerInitialized(GlobalVariable *
G);
875 bool isSafeAccess(ObjectSizeOffsetVisitor &ObjSizeVis,
Value *Addr,
876 TypeSize TypeStoreSize)
const;
879 struct FunctionStateRAII {
880 AddressSanitizer *
Pass;
882 FunctionStateRAII(AddressSanitizer *
Pass) :
Pass(
Pass) {
884 "last pass forgot to clear cache");
888 ~FunctionStateRAII() {
889 Pass->LocalDynamicShadow =
nullptr;
890 Pass->ProcessedAllocas.clear();
896 const DataLayout *
DL;
906 ShadowMapping Mapping;
907 FunctionCallee AsanHandleNoReturnFunc;
908 FunctionCallee AsanPtrCmpFunction, AsanPtrSubFunction;
916 FunctionCallee AsanErrorCallbackSized[2][2];
917 FunctionCallee AsanMemoryAccessCallbackSized[2][2];
919 FunctionCallee AsanMemmove, AsanMemcpy, AsanMemset;
920 Value *LocalDynamicShadow =
nullptr;
921 const StackSafetyGlobalInfo *SSGI;
922 DenseMap<const AllocaInst *, bool> ProcessedAllocas;
924 FunctionCallee AMDGPUAddressShared;
925 FunctionCallee AMDGPUAddressPrivate;
926 int InstrumentationWithCallsThreshold;
927 uint32_t MaxInlinePoisoningSize;
930class ModuleAddressSanitizer {
932 ModuleAddressSanitizer(
Module &M,
bool InsertVersionCheck,
933 bool CompileKernel =
false,
bool Recover =
false,
934 bool UseGlobalsGC =
true,
bool UseOdrIndicator =
true,
942 : InsertVersionCheck),
944 UseGlobalsGC(UseGlobalsGC &&
ClUseGlobalsGC && !this->CompileKernel),
959 UseCtorComdat(UseGlobalsGC &&
ClWithComdat && !this->CompileKernel),
960 DestructorKind(DestructorKind),
964 C = &(
M.getContext());
965 int LongSize =
M.getDataLayout().getPointerSizeInBits();
966 IntptrTy = Type::getIntNTy(*
C, LongSize);
967 PtrTy = PointerType::getUnqual(*
C);
968 TargetTriple =
M.getTargetTriple();
973 assert(this->DestructorKind != AsanDtorKind::Invalid);
976 bool instrumentModule();
979 void initializeCallbacks();
981 void instrumentGlobals(
IRBuilder<> &IRB,
bool *CtorComdat);
988 const std::string &UniqueModuleId);
993 InstrumentGlobalsWithMetadataArray(
IRBuilder<> &IRB,
997 GlobalVariable *CreateMetadataGlobal(Constant *Initializer,
998 StringRef OriginalName);
999 void SetComdatForGlobalMetadata(GlobalVariable *
G, GlobalVariable *
Metadata,
1000 StringRef InternalSuffix);
1003 const GlobalVariable *getExcludedAliasedGlobal(
const GlobalAlias &GA)
const;
1004 bool shouldInstrumentGlobal(GlobalVariable *
G)
const;
1005 bool ShouldUseMachOGlobalsSection()
const;
1006 StringRef getGlobalMetadataSection()
const;
1007 void poisonOneInitializer(Function &GlobalInit);
1008 void createInitializerPoisonCalls();
1009 uint64_t getMinRedzoneSizeForGlobal()
const {
1013 int GetAsanVersion()
const;
1014 GlobalVariable *getOrCreateModuleName();
1018 bool InsertVersionCheck;
1021 bool UsePrivateAlias;
1022 bool UseOdrIndicator;
1029 Triple TargetTriple;
1030 ShadowMapping Mapping;
1031 FunctionCallee AsanPoisonGlobals;
1032 FunctionCallee AsanUnpoisonGlobals;
1033 FunctionCallee AsanRegisterGlobals;
1034 FunctionCallee AsanUnregisterGlobals;
1035 FunctionCallee AsanRegisterImageGlobals;
1036 FunctionCallee AsanUnregisterImageGlobals;
1037 FunctionCallee AsanRegisterElfGlobals;
1038 FunctionCallee AsanUnregisterElfGlobals;
1040 Function *AsanCtorFunction =
nullptr;
1041 Function *AsanDtorFunction =
nullptr;
1042 GlobalVariable *ModuleName =
nullptr;
1054struct FunctionStackPoisoner :
public InstVisitor<FunctionStackPoisoner> {
1056 AddressSanitizer &ASan;
1057 RuntimeCallInserter &RTCI;
1062 ShadowMapping Mapping;
1066 SmallVector<Instruction *, 8> RetVec;
1070 FunctionCallee AsanSetShadowFunc[0x100] = {};
1071 FunctionCallee AsanPoisonStackMemoryFunc, AsanUnpoisonStackMemoryFunc;
1072 FunctionCallee AsanAllocaPoisonFunc, AsanAllocasUnpoisonFunc;
1075 struct AllocaPoisonCall {
1076 IntrinsicInst *InsBefore;
1086 AllocaInst *DynamicAllocaLayout =
nullptr;
1087 IntrinsicInst *LocalEscapeCall =
nullptr;
1089 bool HasInlineAsm =
false;
1090 bool HasReturnsTwiceCall =
false;
1093 FunctionStackPoisoner(Function &
F, AddressSanitizer &ASan,
1094 RuntimeCallInserter &RTCI)
1095 :
F(
F), ASan(ASan), RTCI(RTCI),
1097 IntptrTy(ASan.IntptrTy),
1099 Mapping(ASan.Mapping),
1107 copyArgsPassedByValToAllocas();
1112 if (AllocaVec.
empty() && DynamicAllocaVec.
empty())
return false;
1114 initializeCallbacks(*
F.getParent());
1116 processDynamicAllocas();
1117 processStaticAllocas();
1128 void copyArgsPassedByValToAllocas();
1133 void processStaticAllocas();
1134 void processDynamicAllocas();
1136 void createDynamicAllocasInitStorage();
1141 void visitReturnInst(ReturnInst &RI) {
1142 if (CallInst *CI = RI.
getParent()->getTerminatingMustTailCall())
1149 void visitResumeInst(ResumeInst &RI) { RetVec.
push_back(&RI); }
1152 void visitCleanupReturnInst(CleanupReturnInst &CRI) { RetVec.
push_back(&CRI); }
1154 void unpoisonDynamicAllocasBeforeInst(Instruction *InstBefore,
1155 Value *SavedStack) {
1164 Intrinsic::get_dynamic_area_offset, {IntptrTy}, {});
1170 RTCI.createRuntimeCall(
1171 IRB, AsanAllocasUnpoisonFunc,
1172 {IRB.
CreateLoad(IntptrTy, DynamicAllocaLayout), DynamicAreaPtr});
1176 void unpoisonDynamicAllocas() {
1177 for (Instruction *Ret : RetVec)
1178 unpoisonDynamicAllocasBeforeInst(Ret, DynamicAllocaLayout);
1180 for (Instruction *StackRestoreInst : StackRestoreVec)
1181 unpoisonDynamicAllocasBeforeInst(StackRestoreInst,
1182 StackRestoreInst->getOperand(0));
1195 void handleDynamicAllocaCall(AllocaInst *AI);
1198 void visitAllocaInst(AllocaInst &AI) {
1203 (STy && STy->containsHomogeneousScalableVectorTypes())) {
1207 if (AllocaVec.
empty())
1223 void visitIntrinsicInst(IntrinsicInst &
II) {
1225 if (
ID == Intrinsic::stackrestore) StackRestoreVec.
push_back(&
II);
1226 if (
ID == Intrinsic::localescape) LocalEscapeCall = &
II;
1227 if (!ASan.UseAfterScope)
1229 if (!
II.isLifetimeStartOrEnd())
1234 if (!AI || !ASan.isInterestingAlloca(*AI))
1244 bool DoPoison = (
ID == Intrinsic::lifetime_end);
1245 AllocaPoisonCall APC = {&
II, AI, *
Size, DoPoison};
1247 StaticAllocaPoisonCallVec.
push_back(APC);
1249 DynamicAllocaPoisonCallVec.
push_back(APC);
1252 void visitCallBase(CallBase &CB) {
1254 HasInlineAsm |= CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow;
1255 HasReturnsTwiceCall |= CI->canReturnTwice();
1260 void initializeCallbacks(
Module &M);
1265 void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
1267 void copyToShadow(ArrayRef<uint8_t> ShadowMask, ArrayRef<uint8_t> ShadowBytes,
1270 void copyToShadowInline(ArrayRef<uint8_t> ShadowMask,
1271 ArrayRef<uint8_t> ShadowBytes,
size_t Begin,
1276 Value *createAllocaForLayout(
IRBuilder<> &IRB,
const ASanStackFrameLayout &L,
1279 Instruction *ThenTerm,
Value *ValueIfFalse);
1287 OS, MapClassName2PassName);
1289 if (Options.CompileKernel)
1291 if (Options.UseAfterScope)
1292 OS <<
"use-after-scope";
1300 : Options(Options), UseGlobalGC(UseGlobalGC),
1301 UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
1302 ConstructorKind(ConstructorKind) {}
1311 ModuleAddressSanitizer ModuleSanitizer(
1312 M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover,
1313 UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind);
1325 if (
F.getName().starts_with(
"__asan_"))
1327 if (
F.isPresplitCoroutine())
1329 AddressSanitizer FunctionSanitizer(
1330 M, SSGI, Options.InstrumentationWithCallsThreshold,
1331 Options.MaxInlinePoisoningSize, Options.CompileKernel, Options.Recover,
1332 Options.UseAfterScope, Options.UseAfterReturn);
1335 Modified |= FunctionSanitizer.instrumentFunction(
F, &TLI, &
TTI);
1337 Modified |= ModuleSanitizer.instrumentModule();
1358 if (
G->getName().starts_with(
"llvm.") ||
1360 G->getName().starts_with(
"__llvm_gcov_ctr") ||
1362 G->getName().starts_with(
"__llvm_rtti_proxy"))
1378 if (AddrSpace == 3 || AddrSpace == 5)
1393 return AddrSpace == 0;
1398 Shadow = IRB.
CreateLShr(Shadow, Mapping.Scale);
1399 if (Mapping.Offset == 0)
return Shadow;
1402 if (LocalDynamicShadow)
1403 ShadowBase = LocalDynamicShadow;
1405 ShadowBase = ConstantInt::get(IntptrTy, Mapping.Offset);
1406 if (Mapping.OrShadowOffset)
1407 return IRB.
CreateOr(Shadow, ShadowBase);
1409 return IRB.
CreateAdd(Shadow, ShadowBase);
1414 RuntimeCallInserter &RTCI) {
1417 RTCI.createRuntimeCall(
1423 RTCI.createRuntimeCall(
1429 MI->eraseFromParent();
1433bool AddressSanitizer::isInterestingAlloca(
const AllocaInst &AI) {
1434 auto [It,
Inserted] = ProcessedAllocas.try_emplace(&AI);
1437 return It->getSecond();
1439 bool IsInteresting =
1452 !(SSGI && SSGI->
isSafe(AI)));
1454 It->second = IsInteresting;
1455 return IsInteresting;
1485void AddressSanitizer::getInterestingMemoryOperands(
1489 if (LocalDynamicShadow ==
I)
1495 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
1496 LI->getType(), LI->getAlign());
1501 SI->getValueOperand()->getType(),
SI->getAlign());
1505 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
1506 RMW->getValOperand()->getType(), std::nullopt);
1510 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
1511 XCHG->getCompareOperand()->getType(),
1514 switch (CI->getIntrinsicID()) {
1515 case Intrinsic::masked_load:
1516 case Intrinsic::masked_store:
1517 case Intrinsic::masked_gather:
1518 case Intrinsic::masked_scatter: {
1519 bool IsWrite = CI->getType()->isVoidTy();
1521 unsigned OpOffset = IsWrite ? 1 : 0;
1525 auto BasePtr = CI->getOperand(OpOffset);
1526 if (ignoreAccess(
I, BasePtr))
1528 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1530 Value *
Mask = CI->getOperand(1 + OpOffset);
1531 Interesting.
emplace_back(
I, OpOffset, IsWrite, Ty, Alignment, Mask);
1534 case Intrinsic::masked_expandload:
1535 case Intrinsic::masked_compressstore: {
1536 bool IsWrite = CI->getIntrinsicID() == Intrinsic::masked_compressstore;
1537 unsigned OpOffset = IsWrite ? 1 : 0;
1540 auto BasePtr = CI->getOperand(OpOffset);
1541 if (ignoreAccess(
I, BasePtr))
1544 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1547 Value *
Mask = CI->getOperand(1 + OpOffset);
1550 Value *ExtMask =
IB.CreateZExt(Mask, ExtTy);
1551 Value *EVL =
IB.CreateAddReduce(ExtMask);
1552 Value *TrueMask = ConstantInt::get(
Mask->getType(), 1);
1553 Interesting.
emplace_back(
I, OpOffset, IsWrite, Ty, Alignment, TrueMask,
1557 case Intrinsic::vp_load:
1558 case Intrinsic::vp_store:
1559 case Intrinsic::experimental_vp_strided_load:
1560 case Intrinsic::experimental_vp_strided_store: {
1562 unsigned IID = CI->getIntrinsicID();
1563 bool IsWrite = CI->getType()->isVoidTy();
1566 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1567 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1568 MaybeAlign Alignment = VPI->getOperand(PtrOpNo)->getPointerAlignment(*
DL);
1569 Value *Stride =
nullptr;
1570 if (IID == Intrinsic::experimental_vp_strided_store ||
1571 IID == Intrinsic::experimental_vp_strided_load) {
1572 Stride = VPI->getOperand(PtrOpNo + 1);
1579 Alignment =
Align(1);
1581 Interesting.
emplace_back(
I, PtrOpNo, IsWrite, Ty, Alignment,
1582 VPI->getMaskParam(), VPI->getVectorLengthParam(),
1586 case Intrinsic::vp_gather:
1587 case Intrinsic::vp_scatter: {
1589 unsigned IID = CI->getIntrinsicID();
1590 bool IsWrite = IID == Intrinsic::vp_scatter;
1593 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1594 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1595 MaybeAlign Alignment = VPI->getPointerAlignment();
1596 Interesting.
emplace_back(
I, PtrOpNo, IsWrite, Ty, Alignment,
1597 VPI->getMaskParam(),
1598 VPI->getVectorLengthParam());
1604 if (
TTI->getTgtMemIntrinsic(
II, IntrInfo))
1608 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
1610 ignoreAccess(
I, CI->getArgOperand(ArgNo)))
1612 Type *Ty = CI->getParamByValType(ArgNo);
1628 if (!Cmp->isRelational())
1642 if (BO->getOpcode() != Instruction::Sub)
1655 if (!
G->hasInitializer())
1658 if (
G->hasSanitizerMetadata() &&
G->getSanitizerMetadata().IsDynInit)
1664void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
1668 Value *
Param[2] = {
I->getOperand(0),
I->getOperand(1)};
1669 for (
Value *&i : Param) {
1670 if (i->getType()->isPointerTy())
1673 RTCI.createRuntimeCall(IRB,
F, Param);
1679 TypeSize TypeStoreSize,
bool IsWrite,
1680 Value *SizeArgument,
bool UseCalls,
1681 uint32_t Exp, RuntimeCallInserter &RTCI) {
1686 switch (FixedSize) {
1692 if (!Alignment || *Alignment >= Granularity ||
1693 *Alignment >= FixedSize / 8)
1694 return Pass->instrumentAddress(
I, InsertBefore, Addr, Alignment,
1695 FixedSize, IsWrite,
nullptr, UseCalls,
1699 Pass->instrumentUnusualSizeOrAlignment(
I, InsertBefore, Addr, TypeStoreSize,
1700 IsWrite,
nullptr, UseCalls, Exp, RTCI);
1703void AddressSanitizer::instrumentMaskedLoadOrStore(
1706 MaybeAlign Alignment,
unsigned Granularity,
Type *OpType,
bool IsWrite,
1707 Value *SizeArgument,
bool UseCalls, uint32_t Exp,
1708 RuntimeCallInserter &RTCI) {
1710 TypeSize ElemTypeSize =
DL.getTypeStoreSizeInBits(VTy->getScalarType());
1711 auto Zero = ConstantInt::get(IntptrTy, 0);
1719 Value *IsEVLZero =
IB.CreateICmpNE(EVL, ConstantInt::get(EVLType, 0));
1721 IB.SetInsertPoint(LoopInsertBefore);
1723 EVL =
IB.CreateZExtOrTrunc(EVL, IntptrTy);
1726 Value *
EC =
IB.CreateElementCount(IntptrTy, VTy->getElementCount());
1727 EVL =
IB.CreateBinaryIntrinsic(Intrinsic::umin, EVL, EC);
1729 EVL =
IB.CreateElementCount(IntptrTy, VTy->getElementCount());
1734 Stride =
IB.CreateZExtOrTrunc(Stride, IntptrTy);
1738 Value *MaskElem = IRB.CreateExtractElement(Mask, Index);
1739 if (auto *MaskElemC = dyn_cast<ConstantInt>(MaskElem)) {
1740 if (MaskElemC->isZero())
1746 Instruction *ThenTerm = SplitBlockAndInsertIfThen(
1747 MaskElem, &*IRB.GetInsertPoint(), false);
1748 IRB.SetInsertPoint(ThenTerm);
1751 Value *InstrumentedAddress;
1754 cast<VectorType>(Addr->getType())->getElementType()->isPointerTy() &&
1755 "Expected vector of pointer.");
1756 InstrumentedAddress = IRB.CreateExtractElement(Addr, Index);
1757 }
else if (Stride) {
1764 Alignment, Granularity, ElemTypeSize, IsWrite,
1765 SizeArgument, UseCalls, Exp, RTCI);
1772 RuntimeCallInserter &RTCI) {
1773 Value *Addr =
O.getPtr();
1793 isSafeAccess(ObjSizeVis, Addr,
O.TypeStoreSize)) {
1794 NumOptimizedAccessesToGlobalVar++;
1802 isSafeAccess(ObjSizeVis, Addr,
O.TypeStoreSize)) {
1803 NumOptimizedAccessesToStackVar++;
1809 NumInstrumentedWrites++;
1811 NumInstrumentedReads++;
1813 if (
O.MaybeByteOffset) {
1818 if (TargetTriple.isRISCV()) {
1823 static_cast<unsigned>(LongSize)) {
1832 unsigned Granularity = 1 << Mapping.Scale;
1834 instrumentMaskedLoadOrStore(
this,
DL, IntptrTy,
O.MaybeMask,
O.MaybeEVL,
1835 O.MaybeStride,
O.getInsn(), Addr,
O.Alignment,
1836 Granularity,
O.OpType,
O.IsWrite,
nullptr,
1837 UseCalls, Exp, RTCI);
1840 Granularity,
O.TypeStoreSize,
O.IsWrite,
nullptr,
1841 UseCalls, Exp, RTCI);
1846 Value *Addr,
bool IsWrite,
1847 size_t AccessSizeIndex,
1848 Value *SizeArgument,
1850 RuntimeCallInserter &RTCI) {
1856 Call = RTCI.createRuntimeCall(IRB, AsanErrorCallbackSized[IsWrite][0],
1857 {Addr, SizeArgument});
1859 Call = RTCI.createRuntimeCall(IRB, AsanErrorCallbackSized[IsWrite][1],
1860 {Addr, SizeArgument, ExpVal});
1863 Call = RTCI.createRuntimeCall(
1864 IRB, AsanErrorCallback[IsWrite][0][AccessSizeIndex], Addr);
1866 Call = RTCI.createRuntimeCall(
1867 IRB, AsanErrorCallback[IsWrite][1][AccessSizeIndex], {Addr, ExpVal});
1876 uint32_t TypeStoreSize) {
1877 size_t Granularity =
static_cast<size_t>(1) << Mapping.Scale;
1879 Value *LastAccessedByte =
1880 IRB.
CreateAnd(AddrLong, ConstantInt::get(IntptrTy, Granularity - 1));
1882 if (TypeStoreSize / 8 > 1)
1884 LastAccessedByte, ConstantInt::get(IntptrTy, TypeStoreSize / 8 - 1));
1887 IRB.
CreateIntCast(LastAccessedByte, ShadowValue->getType(),
false);
1892Instruction *AddressSanitizer::instrumentAMDGPUAddress(
1894 uint32_t TypeStoreSize,
bool IsWrite,
Value *SizeArgument) {
1901 return InsertBefore;
1906 Value *IsSharedOrPrivate = IRB.
CreateOr(IsShared, IsPrivate);
1908 Value *AddrSpaceZeroLanding =
1911 return InsertBefore;
1927 Trm->getParent()->setName(
"asan.report");
1938void AddressSanitizer::instrumentAddress(
Instruction *OrigIns,
1941 uint32_t TypeStoreSize,
bool IsWrite,
1942 Value *SizeArgument,
bool UseCalls,
1944 RuntimeCallInserter &RTCI) {
1945 if (TargetTriple.isAMDGPU()) {
1946 InsertBefore = instrumentAMDGPUAddress(OrigIns, InsertBefore, Addr,
1947 TypeStoreSize, IsWrite, SizeArgument);
1956 const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
1959 ConstantInt::get(
Int32Ty, AccessInfo.Packed)});
1966 RTCI.createRuntimeCall(
1967 IRB, AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], AddrLong);
1969 RTCI.createRuntimeCall(
1970 IRB, AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex],
1971 {AddrLong, ConstantInt::get(IRB.
getInt32Ty(), Exp)});
1978 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1979 const uint64_t ShadowAlign =
1980 std::max<uint64_t>(Alignment.
valueOrOne().
value() >> Mapping.Scale, 1);
1985 size_t Granularity = 1ULL << Mapping.Scale;
1988 bool GenSlowPath = (
ClAlwaysSlowPath || (TypeStoreSize < 8 * Granularity));
1990 if (TargetTriple.isAMDGCN()) {
1992 auto *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
1995 CrashTerm = genAMDGPUReportBlock(IRB, Cmp, Recover);
1996 }
else if (GenSlowPath) {
2004 Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
2019 CrashTerm, AddrLong, IsWrite, AccessSizeIndex, SizeArgument, Exp, RTCI);
2028void AddressSanitizer::instrumentUnusualSizeOrAlignment(
2030 TypeSize TypeStoreSize,
bool IsWrite,
Value *SizeArgument,
bool UseCalls,
2031 uint32_t Exp, RuntimeCallInserter &RTCI) {
2039 RTCI.createRuntimeCall(IRB, AsanMemoryAccessCallbackSized[IsWrite][0],
2042 RTCI.createRuntimeCall(
2043 IRB, AsanMemoryAccessCallbackSized[IsWrite][1],
2057void ModuleAddressSanitizer::poisonOneInitializer(
Function &GlobalInit) {
2063 Value *ModuleNameAddr =
2065 IRB.
CreateCall(AsanPoisonGlobals, ModuleNameAddr);
2068 for (
auto &BB : GlobalInit)
2073void ModuleAddressSanitizer::createInitializerPoisonCalls() {
2093 poisonOneInitializer(*
F);
2099ModuleAddressSanitizer::getExcludedAliasedGlobal(
const GlobalAlias &GA)
const {
2104 assert(CompileKernel &&
"Only expecting to be called when compiling kernel");
2116bool ModuleAddressSanitizer::shouldInstrumentGlobal(
GlobalVariable *
G)
const {
2117 Type *Ty =
G->getValueType();
2120 if (
G->hasSanitizerMetadata() &&
G->getSanitizerMetadata().NoAddress)
2122 if (!Ty->
isSized())
return false;
2123 if (!
G->hasInitializer())
return false;
2130 if (
G->isThreadLocal())
return false;
2132 if (
G->getAlign() && *
G->getAlign() > getMinRedzoneSizeForGlobal())
return false;
2138 if (!TargetTriple.isOSBinFormatCOFF()) {
2139 if (!
G->hasExactDefinition() ||
G->hasComdat())
2143 if (
G->isInterposable())
2147 if (
G->hasAvailableExternallyLinkage())
2154 switch (
C->getSelectionKind()) {
2165 if (
G->hasSection()) {
2175 if (Section ==
"llvm.metadata")
return false;
2182 if (
Section.starts_with(
".preinit_array") ||
2183 Section.starts_with(
".init_array") ||
2184 Section.starts_with(
".fini_array")) {
2190 if (TargetTriple.isOSBinFormatELF()) {
2204 if (TargetTriple.isOSBinFormatCOFF() &&
Section.contains(
'$')) {
2205 LLVM_DEBUG(
dbgs() <<
"Ignoring global in sorted section (contains '$'): "
2210 if (TargetTriple.isOSBinFormatMachO()) {
2212 unsigned TAA = 0, StubSize = 0;
2215 Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize));
2220 if (ParsedSegment ==
"__OBJC" ||
2221 (ParsedSegment ==
"__DATA" && ParsedSection.
starts_with(
"__objc_"))) {
2233 if (ParsedSegment ==
"__DATA" && ParsedSection ==
"__cfstring") {
2246 if (CompileKernel) {
2249 if (
G->getName().starts_with(
"__"))
2259bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection()
const {
2260 if (!TargetTriple.isOSBinFormatMachO())
2263 if (TargetTriple.isMacOSX() && !TargetTriple.isMacOSXVersionLT(10, 11))
2265 if (TargetTriple.isiOS() && !TargetTriple.isOSVersionLT(9))
2267 if (TargetTriple.isWatchOS() && !TargetTriple.isOSVersionLT(2))
2269 if (TargetTriple.isDriverKit())
2271 if (TargetTriple.isXROS())
2277StringRef ModuleAddressSanitizer::getGlobalMetadataSection()
const {
2278 switch (TargetTriple.getObjectFormat()) {
2288 "ModuleAddressSanitizer not implemented for object file format");
2295void ModuleAddressSanitizer::initializeCallbacks() {
2301 AsanUnpoisonGlobals =
2305 AsanRegisterGlobals =
M.getOrInsertFunction(
2307 AsanUnregisterGlobals =
M.getOrInsertFunction(
2312 AsanRegisterImageGlobals =
M.getOrInsertFunction(
2314 AsanUnregisterImageGlobals =
M.getOrInsertFunction(
2317 AsanRegisterElfGlobals =
2319 IntptrTy, IntptrTy, IntptrTy);
2320 AsanUnregisterElfGlobals =
2322 IntptrTy, IntptrTy, IntptrTy);
2327void ModuleAddressSanitizer::SetComdatForGlobalMetadata(
2332 if (!
G->hasName()) {
2336 G->setName(
genName(
"anon_global"));
2339 if (!InternalSuffix.
empty() &&
G->hasLocalLinkage()) {
2340 std::string
Name = std::string(
G->getName());
2341 Name += InternalSuffix;
2342 C =
M.getOrInsertComdat(Name);
2344 C =
M.getOrInsertComdat(
G->getName());
2350 if (TargetTriple.isOSBinFormatCOFF()) {
2352 if (
G->hasPrivateLinkage())
2365ModuleAddressSanitizer::CreateMetadataGlobal(
Constant *Initializer,
2367 auto Linkage = TargetTriple.isOSBinFormatMachO()
2373 Metadata->setSection(getGlobalMetadataSection());
2380Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor() {
2384 AsanDtorFunction->addFnAttr(Attribute::NoUnwind);
2392void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
2396 auto &
DL =
M.getDataLayout();
2399 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2400 Constant *Initializer = MetadataInitializers[i];
2404 Metadata->setMetadata(LLVMContext::MD_associated, MD);
2410 unsigned SizeOfGlobalStruct =
DL.getTypeAllocSize(Initializer->
getType());
2412 "global metadata will not be padded appropriately");
2415 SetComdatForGlobalMetadata(
G,
Metadata,
"");
2420 if (!MetadataGlobals.empty())
2424void ModuleAddressSanitizer::instrumentGlobalsELF(
2427 const std::string &UniqueModuleId) {
2434 bool UseComdatForGlobalsGC = UseOdrIndicator && !UniqueModuleId.empty();
2437 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2440 CreateMetadataGlobal(MetadataInitializers[i],
G->getName());
2442 Metadata->setMetadata(LLVMContext::MD_associated, MD);
2445 if (UseComdatForGlobalsGC)
2446 SetComdatForGlobalMetadata(
G,
Metadata, UniqueModuleId);
2451 if (!MetadataGlobals.empty())
2468 "__start_" + getGlobalMetadataSection());
2472 "__stop_" + getGlobalMetadataSection());
2486 IrbDtor.CreateCall(AsanUnregisterElfGlobals,
2493void ModuleAddressSanitizer::InstrumentGlobalsMachO(
2504 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2505 Constant *Initializer = MetadataInitializers[i];
2511 auto LivenessBinder =
2516 Twine(
"__asan_binder_") +
G->getName());
2517 Liveness->
setSection(
"__DATA,__asan_liveness,regular,live_support");
2518 LivenessGlobals[i] = Liveness;
2525 if (!LivenessGlobals.empty())
2547 IrbDtor.CreateCall(AsanUnregisterImageGlobals,
2552void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
2556 unsigned N = ExtendedGlobals.
size();
2566 if (Mapping.Scale > 3)
2567 AllGlobals->setAlignment(
Align(1ULL << Mapping.Scale));
2572 ConstantInt::get(IntptrTy,
N)});
2578 IrbDtor.CreateCall(AsanUnregisterGlobals,
2580 ConstantInt::get(IntptrTy,
N)});
2589void ModuleAddressSanitizer::instrumentGlobals(
IRBuilder<> &IRB,
2594 if (CompileKernel) {
2595 for (
auto &GA :
M.aliases()) {
2597 AliasedGlobalExclusions.
insert(GV);
2602 for (
auto &
G :
M.globals()) {
2603 if (!AliasedGlobalExclusions.
count(&
G) && shouldInstrumentGlobal(&
G))
2607 size_t n = GlobalsToChange.
size();
2608 auto &
DL =
M.getDataLayout();
2622 IntptrTy, IntptrTy, IntptrTy);
2626 for (
size_t i = 0; i < n; i++) {
2630 if (
G->hasSanitizerMetadata())
2631 MD =
G->getSanitizerMetadata();
2636 std::string NameForGlobal =
G->getName().str();
2641 Type *Ty =
G->getValueType();
2642 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
2655 M, NewTy,
G->isConstant(),
Linkage, NewInitializer,
"",
G,
2656 G->getThreadLocalMode(),
G->getAddressSpace());
2666 if (TargetTriple.isOSBinFormatMachO() && !
G->hasSection() &&
2669 if (Seq && Seq->isCString())
2670 NewGlobal->
setSection(
"__TEXT,__asan_cstring,regular");
2677 G->replaceAllUsesWith(NewGlobal);
2679 G->eraseFromParent();
2680 NewGlobals[i] = NewGlobal;
2685 bool CanUsePrivateAliases =
2686 TargetTriple.isOSBinFormatELF() || TargetTriple.isOSBinFormatMachO() ||
2687 TargetTriple.isOSBinFormatWasm();
2688 if (CanUsePrivateAliases && UsePrivateAlias) {
2691 InstrumentedGlobal =
2698 }
else if (UseOdrIndicator) {
2701 auto *ODRIndicatorSym =
2710 ODRIndicatorSym->setAlignment(
Align(1));
2717 ConstantInt::get(IntptrTy, SizeInBytes),
2718 ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
2721 ConstantInt::get(IntptrTy, MD.
IsDynInit),
2726 Initializers[i] = Initializer;
2732 for (
size_t i = 0; i < n; i++) {
2734 if (
G->getName().empty())
continue;
2739 if (UseGlobalsGC && TargetTriple.isOSBinFormatELF()) {
2746 }
else if (n == 0) {
2749 *CtorComdat = TargetTriple.isOSBinFormatELF();
2751 *CtorComdat =
false;
2752 if (UseGlobalsGC && TargetTriple.isOSBinFormatCOFF()) {
2753 InstrumentGlobalsCOFF(IRB, NewGlobals, Initializers);
2754 }
else if (UseGlobalsGC && ShouldUseMachOGlobalsSection()) {
2755 InstrumentGlobalsMachO(IRB, NewGlobals, Initializers);
2757 InstrumentGlobalsWithMetadataArray(IRB, NewGlobals, Initializers);
2763 createInitializerPoisonCalls();
2769ModuleAddressSanitizer::getRedzoneSizeForGlobal(uint64_t SizeInBytes)
const {
2770 constexpr uint64_t kMaxRZ = 1 << 18;
2771 const uint64_t MinRZ = getMinRedzoneSizeForGlobal();
2774 if (SizeInBytes <= MinRZ / 2) {
2778 RZ = MinRZ - SizeInBytes;
2781 RZ = std::clamp((SizeInBytes / MinRZ / 4) * MinRZ, MinRZ, kMaxRZ);
2784 if (SizeInBytes % MinRZ)
2785 RZ += MinRZ - (SizeInBytes % MinRZ);
2788 assert((RZ + SizeInBytes) % MinRZ == 0);
2793int ModuleAddressSanitizer::GetAsanVersion()
const {
2794 int LongSize =
M.getDataLayout().getPointerSizeInBits();
2795 bool isAndroid =
M.getTargetTriple().isAndroid();
2799 Version += (LongSize == 32 && isAndroid);
2814bool ModuleAddressSanitizer::instrumentModule() {
2815 initializeCallbacks();
2823 if (CompileKernel) {
2828 std::string AsanVersion = std::to_string(GetAsanVersion());
2829 std::string VersionCheckName =
2831 std::tie(AsanCtorFunction, std::ignore) =
2834 {}, VersionCheckName);
2838 bool CtorComdat =
true;
2841 if (AsanCtorFunction) {
2842 IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2843 instrumentGlobals(IRB, &CtorComdat);
2846 instrumentGlobals(IRB, &CtorComdat);
2855 if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
2856 if (AsanCtorFunction) {
2860 if (AsanDtorFunction) {
2865 if (AsanCtorFunction)
2867 if (AsanDtorFunction)
2878 for (
int Exp = 0;
Exp < 2;
Exp++) {
2879 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
2880 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
2881 const std::string ExpStr =
Exp ?
"exp_" :
"";
2882 const std::string EndingStr = Recover ?
"_noabort" :
"";
2892 if (
auto AK = TLI->getExtAttrForI32Param(
false)) {
2893 AL2 = AL2.addParamAttribute(*
C, 2, AK);
2894 AL1 = AL1.addParamAttribute(*
C, 1, AK);
2897 AsanErrorCallbackSized[AccessIsWrite][
Exp] =
M.getOrInsertFunction(
2901 AsanMemoryAccessCallbackSized[AccessIsWrite][
Exp] =
M.getOrInsertFunction(
2906 AccessSizeIndex++) {
2907 const std::string Suffix = TypeStr +
itostr(1ULL << AccessSizeIndex);
2908 AsanErrorCallback[AccessIsWrite][
Exp][AccessSizeIndex] =
2909 M.getOrInsertFunction(
2913 AsanMemoryAccessCallback[AccessIsWrite][
Exp][AccessSizeIndex] =
2914 M.getOrInsertFunction(
2921 const std::string MemIntrinCallbackPrefix =
2925 AsanMemmove =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memmove",
2926 PtrTy, PtrTy, PtrTy, IntptrTy);
2927 AsanMemcpy =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memcpy", PtrTy,
2928 PtrTy, PtrTy, IntptrTy);
2929 AsanMemset =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memset",
2933 AsanHandleNoReturnFunc =
2936 AsanPtrCmpFunction =
2938 AsanPtrSubFunction =
2940 if (Mapping.InGlobal)
2941 AsanShadowGlobal =
M.getOrInsertGlobal(
"__asan_shadow",
2944 AMDGPUAddressShared =
2946 AMDGPUAddressPrivate =
2950bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(
Function &
F) {
2958 if (
F.getName().contains(
" load]")) {
2968bool AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(
Function &
F) {
2974 if (Mapping.InGlobal) {
2982 LocalDynamicShadow =
2983 IRB.
CreateCall(Asm, {AsanShadowGlobal},
".asan.shadow");
2985 LocalDynamicShadow =
2989 Value *GlobalDynamicAddress =
F.getParent()->getOrInsertGlobal(
2991 LocalDynamicShadow = IRB.
CreateLoad(IntptrTy, GlobalDynamicAddress);
2996void AddressSanitizer::markEscapedLocalAllocas(
Function &
F) {
3001 assert(ProcessedAllocas.empty() &&
"must process localescape before allocas");
3005 if (!
F.getParent()->getFunction(
"llvm.localescape"))
return;
3011 if (
II &&
II->getIntrinsicID() == Intrinsic::localescape) {
3013 for (
Value *Arg :
II->args()) {
3016 "non-static alloca arg to localescape");
3017 ProcessedAllocas[AI] =
false;
3026void AddressSanitizer::markCatchParametersAsUninteresting(
Function &
F) {
3032 for (
Value *Operand : CatchPad->arg_operands())
3034 ProcessedAllocas[AI] =
false;
3040bool AddressSanitizer::suppressInstrumentationSiteForDebug(
int &Instrumented) {
3041 bool ShouldInstrument =
3045 return !ShouldInstrument;
3048bool AddressSanitizer::instrumentFunction(
Function &
F,
3051 bool FunctionModified =
false;
3054 if (
F.hasFnAttribute(Attribute::Naked))
3055 return FunctionModified;
3060 if (maybeInsertAsanInitAtFunctionEntry(
F))
3061 FunctionModified =
true;
3064 if (!
F.hasFnAttribute(Attribute::SanitizeAddress))
return FunctionModified;
3066 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
3067 return FunctionModified;
3071 initializeCallbacks(TLI);
3073 FunctionStateRAII CleanupObj(
this);
3075 RuntimeCallInserter RTCI(
F);
3077 FunctionModified |= maybeInsertDynamicShadowAtFunctionEntry(
F);
3081 markEscapedLocalAllocas(
F);
3083 if (TargetTriple.isOSWindows())
3084 markCatchParametersAsUninteresting(
F);
3096 for (
auto &BB :
F) {
3098 TempsToInstrument.
clear();
3099 int NumInsnsPerBB = 0;
3100 for (
auto &Inst : BB) {
3101 if (LooksLikeCodeInBug11395(&Inst))
return false;
3108 if (!InterestingOperands.
empty()) {
3109 for (
auto &Operand : InterestingOperands) {
3111 Value *Ptr = Operand.getPtr();
3115 if (Operand.MaybeMask) {
3116 if (TempsToInstrument.
count(Ptr))
3119 if (!TempsToInstrument.
insert(Ptr).second)
3123 OperandsToInstrument.
push_back(Operand);
3130 PointerComparisonsOrSubtracts.
push_back(&Inst);
3138 TempsToInstrument.
clear();
3149 bool UseCalls = (InstrumentationWithCallsThreshold >= 0 &&
3150 OperandsToInstrument.
size() + IntrinToInstrument.
size() >
3151 (
unsigned)InstrumentationWithCallsThreshold);
3156 int NumInstrumented = 0;
3157 for (
auto &Operand : OperandsToInstrument) {
3158 if (!suppressInstrumentationSiteForDebug(NumInstrumented))
3159 instrumentMop(ObjSizeVis, Operand, UseCalls,
3160 F.getDataLayout(), RTCI);
3161 FunctionModified =
true;
3163 for (
auto *Inst : IntrinToInstrument) {
3164 if (!suppressInstrumentationSiteForDebug(NumInstrumented))
3165 instrumentMemIntrinsic(Inst, RTCI);
3166 FunctionModified =
true;
3169 FunctionStackPoisoner FSP(
F, *
this, RTCI);
3170 bool ChangedStack = FSP.runOnFunction();
3174 for (
auto *CI : NoReturnCalls) {
3176 RTCI.createRuntimeCall(IRB, AsanHandleNoReturnFunc, {});
3179 for (
auto *Inst : PointerComparisonsOrSubtracts) {
3180 instrumentPointerComparisonOrSubtraction(Inst, RTCI);
3181 FunctionModified =
true;
3184 if (ChangedStack || !NoReturnCalls.empty())
3185 FunctionModified =
true;
3187 LLVM_DEBUG(
dbgs() <<
"ASAN done instrumenting: " << FunctionModified <<
" "
3190 return FunctionModified;
3196bool AddressSanitizer::LooksLikeCodeInBug11395(
Instruction *
I) {
3197 if (LongSize != 32)
return false;
3206void FunctionStackPoisoner::initializeCallbacks(
Module &M) {
3210 const char *MallocNameTemplate =
3215 std::string Suffix =
itostr(Index);
3216 AsanStackMallocFunc[
Index] =
M.getOrInsertFunction(
3217 MallocNameTemplate + Suffix, IntptrTy, IntptrTy);
3218 AsanStackFreeFunc[
Index] =
3223 if (ASan.UseAfterScope) {
3224 AsanPoisonStackMemoryFunc =
M.getOrInsertFunction(
3226 AsanUnpoisonStackMemoryFunc =
M.getOrInsertFunction(
3230 for (
size_t Val : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf1, 0xf2,
3231 0xf3, 0xf5, 0xf8}) {
3232 std::ostringstream
Name;
3234 Name << std::setw(2) << std::setfill(
'0') << std::hex << Val;
3235 AsanSetShadowFunc[Val] =
3236 M.getOrInsertFunction(
Name.str(), IRB.
getVoidTy(), IntptrTy, IntptrTy);
3239 AsanAllocaPoisonFunc =
M.getOrInsertFunction(
3241 AsanAllocasUnpoisonFunc =
M.getOrInsertFunction(
3247 size_t Begin,
size_t End,
3249 Value *ShadowBase) {
3253 const size_t LargestStoreSizeInBytes =
3254 std::min<size_t>(
sizeof(uint64_t), ASan.LongSize / 8);
3256 const bool IsLittleEndian =
F.getDataLayout().isLittleEndian();
3262 for (
size_t i = Begin; i < End;) {
3263 if (!ShadowMask[i]) {
3269 size_t StoreSizeInBytes = LargestStoreSizeInBytes;
3271 while (StoreSizeInBytes > End - i)
3272 StoreSizeInBytes /= 2;
3275 for (
size_t j = StoreSizeInBytes - 1;
j && !ShadowMask[i +
j]; --
j) {
3276 while (j <= StoreSizeInBytes / 2)
3277 StoreSizeInBytes /= 2;
3281 for (
size_t j = 0;
j < StoreSizeInBytes;
j++) {
3283 Val |= (uint64_t)ShadowBytes[i + j] << (8 * j);
3285 Val = (Val << 8) | ShadowBytes[i + j];
3288 Value *Ptr = IRB.
CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i));
3294 i += StoreSizeInBytes;
3301 copyToShadow(ShadowMask, ShadowBytes, 0, ShadowMask.
size(), IRB, ShadowBase);
3306 size_t Begin,
size_t End,
3309 size_t Done = Begin;
3310 for (
size_t i = Begin, j = Begin + 1; i < End; i =
j++) {
3311 if (!ShadowMask[i]) {
3315 uint8_t Val = ShadowBytes[i];
3316 if (!AsanSetShadowFunc[Val])
3320 for (;
j < End && ShadowMask[
j] && Val == ShadowBytes[
j]; ++
j) {
3323 if (j - i >= ASan.MaxInlinePoisoningSize) {
3324 copyToShadowInline(ShadowMask, ShadowBytes,
Done, i, IRB, ShadowBase);
3325 RTCI.createRuntimeCall(
3326 IRB, AsanSetShadowFunc[Val],
3327 {IRB.
CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)),
3328 ConstantInt::get(IntptrTy, j - i)});
3333 copyToShadowInline(ShadowMask, ShadowBytes,
Done, End, IRB, ShadowBase);
3341 for (
int i = 0;; i++, MaxSize *= 2)
3342 if (LocalStackSize <= MaxSize)
return i;
3346void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {
3348 if (CopyInsertPoint == ASan.LocalDynamicShadow) {
3356 if (Arg.hasByValAttr()) {
3357 Type *Ty = Arg.getParamByValType();
3358 const Align Alignment =
3359 DL.getValueOrABITypeAlignment(Arg.getParamAlign(), Ty);
3363 (Arg.hasName() ? Arg.getName() :
"Arg" +
Twine(Arg.getArgNo())) +
3366 Arg.replaceAllUsesWith(AI);
3368 uint64_t AllocSize =
DL.getTypeAllocSize(Ty);
3369 IRB.
CreateMemCpy(AI, Alignment, &Arg, Alignment, AllocSize);
3377 Value *ValueIfFalse) {
3380 PHI->addIncoming(ValueIfFalse, CondBlock);
3382 PHI->addIncoming(ValueIfTrue, ThenBlock);
3386Value *FunctionStackPoisoner::createAllocaForLayout(
3395 nullptr,
"MyAlloca");
3399 uint64_t FrameAlignment = std::max(
L.FrameAlignment, uint64_t(
ClRealignStack));
3404void FunctionStackPoisoner::createDynamicAllocasInitStorage() {
3407 DynamicAllocaLayout = IRB.
CreateAlloca(IntptrTy,
nullptr);
3412void FunctionStackPoisoner::processDynamicAllocas() {
3419 for (
const auto &APC : DynamicAllocaPoisonCallVec) {
3422 assert(ASan.isInterestingAlloca(*APC.AI));
3423 assert(!APC.AI->isStaticAlloca());
3426 poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
3433 createDynamicAllocasInitStorage();
3434 for (
auto &AI : DynamicAllocaVec)
3435 handleDynamicAllocaCall(AI);
3436 unpoisonDynamicAllocas();
3448 for (
Instruction *It = Start; It; It = It->getNextNode()) {
3465 if (!Alloca || ASan.isInterestingAlloca(*Alloca))
3468 Value *Val = Store->getValueOperand();
3470 bool IsArgInitViaCast =
3475 Val == It->getPrevNode();
3476 bool IsArgInit = IsDirectArgInit || IsArgInitViaCast;
3480 if (IsArgInitViaCast)
3495 if (AI->
hasMetadata(LLVMContext::MD_annotation)) {
3498 for (
auto &Annotation : AllocaAnnotations->
operands()) {
3502 for (
unsigned Index = 0; Index < AnnotationTuple->getNumOperands();
3505 auto MetadataString =
3507 if (MetadataString->getString() ==
"alloca_name_altered")
3516void FunctionStackPoisoner::processStaticAllocas() {
3517 if (AllocaVec.
empty()) {
3522 int StackMallocIdx = -1;
3524 if (
auto SP =
F.getSubprogram())
3525 EntryDebugLocation =
3534 auto InsBeforeB = InsBefore->
getParent();
3535 assert(InsBeforeB == &
F.getEntryBlock());
3536 for (
auto *AI : StaticAllocasToMoveUp)
3547 ArgInitInst->moveBefore(InsBefore->
getIterator());
3550 if (LocalEscapeCall)
3558 ASan.getAllocaSizeInBytes(*AI),
3569 uint64_t Granularity = 1ULL << Mapping.Scale;
3570 uint64_t MinHeaderSize = std::max((uint64_t)ASan.LongSize / 2, Granularity);
3576 for (
auto &
Desc : SVD)
3580 for (
const auto &APC : StaticAllocaPoisonCallVec) {
3583 assert(ASan.isInterestingAlloca(*APC.AI));
3584 assert(APC.AI->isStaticAlloca());
3589 if (
const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) {
3590 if (LifetimeLoc->getFile() == FnLoc->getFile())
3591 if (
unsigned Line = LifetimeLoc->getLine())
3592 Desc.Line = std::min(
Desc.Line ?
Desc.Line : Line, Line);
3598 LLVM_DEBUG(
dbgs() << DescriptionString <<
" --- " <<
L.FrameSize <<
"\n");
3599 uint64_t LocalStackSize =
L.FrameSize;
3600 bool DoStackMalloc =
3610 DoDynamicAlloca &= !HasInlineAsm && !HasReturnsTwiceCall;
3611 DoStackMalloc &= !HasInlineAsm && !HasReturnsTwiceCall;
3613 Type *PtrTy =
F.getDataLayout().getAllocaPtrType(
F.getContext());
3614 Value *StaticAlloca =
3615 DoDynamicAlloca ? nullptr : createAllocaForLayout(IRB, L,
false);
3617 Value *FakeStackPtr;
3618 Value *FakeStackInt;
3619 Value *LocalStackBase;
3620 Value *LocalStackBaseAlloca;
3623 if (DoStackMalloc) {
3624 LocalStackBaseAlloca =
3625 IRB.
CreateAlloca(IntptrTy,
nullptr,
"asan_local_stack_base");
3632 Constant *OptionDetectUseAfterReturn =
F.getParent()->getOrInsertGlobal(
3642 Value *FakeStackValue =
3643 RTCI.createRuntimeCall(IRBIf, AsanStackMallocFunc[StackMallocIdx],
3644 ConstantInt::get(IntptrTy, LocalStackSize));
3646 FakeStackInt = createPHI(IRB, UseAfterReturnIsEnabled, FakeStackValue,
3647 Term, ConstantInt::get(IntptrTy, 0));
3655 RTCI.createRuntimeCall(IRB, AsanStackMallocFunc[StackMallocIdx],
3656 ConstantInt::get(IntptrTy, LocalStackSize));
3659 Value *NoFakeStack =
3664 Value *AllocaValue =
3665 DoDynamicAlloca ? createAllocaForLayout(IRBIf, L,
true) : StaticAlloca;
3669 createPHI(IRB, NoFakeStack, AllocaValue, Term, FakeStackPtr);
3670 IRB.
CreateStore(LocalStackBase, LocalStackBaseAlloca);
3678 DoDynamicAlloca ? createAllocaForLayout(IRB, L,
true) : StaticAlloca;
3679 LocalStackBaseAlloca = LocalStackBase;
3684 for (
const auto &
Desc : SVD) {
3688 LocalStackBase, ConstantInt::get(IntptrTy,
Desc.Offset));
3699 LocalStackBase, ConstantInt::get(IntptrTy, ASan.LongSize / 8));
3707 LocalStackBase, ConstantInt::get(IntptrTy, 2 * ASan.LongSize / 8));
3714 ASan.memToShadow(IRB.
CreatePtrToInt(LocalStackBase, IntptrTy), IRB);
3717 copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase);
3719 if (!StaticAllocaPoisonCallVec.empty()) {
3723 for (
const auto &APC : StaticAllocaPoisonCallVec) {
3726 size_t Begin =
Desc.Offset /
L.Granularity;
3727 size_t End = Begin + (APC.Size +
L.Granularity - 1) /
L.Granularity;
3730 copyToShadow(ShadowAfterScope,
3731 APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin, End,
3737 for (
Value *NewAllocaPtr : NewAllocaPtrs) {
3740 if (
I->isLifetimeStartOrEnd())
3741 I->eraseFromParent();
3754 if (DoStackMalloc) {
3755 assert(StackMallocIdx >= 0);
3772 if (ASan.MaxInlinePoisoningSize != 0 && StackMallocIdx <= 4) {
3774 ShadowAfterReturn.
resize(ClassSize /
L.Granularity,
3776 copyToShadow(ShadowAfterReturn, ShadowAfterReturn, IRBPoison,
3778 Value *SavedFlagPtrPtr = IRBPoison.CreatePtrAdd(
3780 ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8));
3781 Value *SavedFlagPtr = IRBPoison.CreateLoad(IntptrTy, SavedFlagPtrPtr);
3782 IRBPoison.CreateStore(
3784 IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getPtrTy()));
3787 RTCI.createRuntimeCall(
3788 IRBPoison, AsanStackFreeFunc[StackMallocIdx],
3789 {FakeStackInt, ConstantInt::get(IntptrTy, LocalStackSize)});
3793 copyToShadow(ShadowAfterScope, ShadowClean, IRBElse, ShadowBase);
3795 copyToShadow(ShadowAfterScope, ShadowClean, IRBRet, ShadowBase);
3800 for (
auto *AI : AllocaVec)
3804void FunctionStackPoisoner::poisonAlloca(
Value *V, uint64_t
Size,
3808 Value *SizeArg = ConstantInt::get(IntptrTy,
Size);
3809 RTCI.createRuntimeCall(
3810 IRB, DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc,
3811 {AddrArg, SizeArg});
3822void FunctionStackPoisoner::handleDynamicAllocaCall(
AllocaInst *AI) {
3830 Value *AllocaRzMask = ConstantInt::get(IntptrTy, AllocaRedzoneMask);
3864 ConstantInt::get(IntptrTy, Alignment.
value()));
3867 RTCI.createRuntimeCall(IRB, AsanAllocaPoisonFunc, {NewAddress, OldSize});
3878 if (
I->isLifetimeStartOrEnd())
3879 I->eraseFromParent();
3911 Size - uint64_t(
Offset) >= TypeStoreSize / 8;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::desc("Use Stack Safety analysis results"))
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void findStoresToUninstrumentedArgAllocas(AddressSanitizer &ASan, Instruction &InsBefore, SmallVectorImpl< Instruction * > &InitInsts)
Collect instructions in the entry block after InsBefore which initialize permanent storage for a func...
static void doInstrumentAddress(AddressSanitizer *Pass, Instruction *I, Instruction *InsertBefore, Value *Addr, MaybeAlign Alignment, unsigned Granularity, TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls, uint32_t Exp, RuntimeCallInserter &RTCI)
static const uint64_t kDefaultShadowScale
const char kAMDGPUUnreachableName[]
constexpr size_t kAccessSizeIndexMask
static cl::opt< int > ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClUsePrivateAlias("asan-use-private-alias", cl::desc("Use private aliases for global variables"), cl::Hidden, cl::init(true))
static const uint64_t kPS_ShadowOffset64
static const uint64_t kFreeBSD_ShadowOffset32
constexpr size_t kIsWriteShift
static const uint64_t kSmallX86_64ShadowOffsetAlignMask
static bool isInterestingPointerSubtraction(Instruction *I)
const char kAMDGPUAddressSharedName[]
const char kAsanStackFreeNameTemplate[]
constexpr size_t kCompileKernelMask
static cl::opt< bool > ClForceDynamicShadow("asan-force-dynamic-shadow", cl::desc("Load shadow address into a local variable for each function"), cl::Hidden, cl::init(false))
const char kAsanOptionDetectUseAfterReturn[]
static cl::opt< std::string > ClMemoryAccessCallbackPrefix("asan-memory-access-callback-prefix", cl::desc("Prefix for memory access callbacks"), cl::Hidden, cl::init("__asan_"))
static const uint64_t kRISCV64_ShadowOffset64
static cl::opt< bool > ClInsertVersionCheck("asan-guard-against-version-mismatch", cl::desc("Guard against compiler/runtime version mismatch."), cl::Hidden, cl::init(true))
const char kAsanSetShadowPrefix[]
static cl::opt< AsanDtorKind > ClOverrideDestructorKind("asan-destructor-kind", cl::desc("Sets the ASan destructor kind. The default is to use the value " "provided to the pass constructor"), cl::values(clEnumValN(AsanDtorKind::None, "none", "No destructors"), clEnumValN(AsanDtorKind::Global, "global", "Use global destructors")), cl::init(AsanDtorKind::Invalid), cl::Hidden)
static Twine genName(StringRef suffix)
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static uint64_t GetCtorAndDtorPriority(Triple &TargetTriple)
const char kAsanStackMallocNameTemplate[]
static cl::opt< bool > ClInstrumentByval("asan-instrument-byval", cl::desc("instrument byval call arguments"), cl::Hidden, cl::init(true))
const char kAsanInitName[]
static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClRedzoneByvalArgs("asan-redzone-byval-args", cl::desc("Create redzones for byval " "arguments (extra copy " "required)"), cl::Hidden, cl::init(true))
static const uint64_t kWindowsShadowOffset64
const char kAsanGenPrefix[]
constexpr size_t kIsWriteMask
static uint64_t getRedzoneSizeForScale(int MappingScale)
static const uint64_t kDefaultShadowOffset64
static cl::opt< bool > ClOptimizeCallbacks("asan-optimize-callbacks", cl::desc("Optimize callbacks"), cl::Hidden, cl::init(false))
const char kAsanUnregisterGlobalsName[]
static const uint64_t kAsanCtorAndDtorPriority
const char kAsanUnpoisonGlobalsName[]
static cl::opt< bool > ClWithIfuncSuppressRemat("asan-with-ifunc-suppress-remat", cl::desc("Suppress rematerialization of dynamic shadow address by passing " "it through inline asm in prologue."), cl::Hidden, cl::init(true))
static cl::opt< int > ClDebugStack("asan-debug-stack", cl::desc("debug stack"), cl::Hidden, cl::init(0))
const char kAsanUnregisterElfGlobalsName[]
static bool isUnsupportedAMDGPUAddrspace(Value *Addr)
const char kAsanRegisterImageGlobalsName[]
static const uint64_t kWebAssemblyShadowOffset
static cl::opt< bool > ClOpt("asan-opt", cl::desc("Optimize instrumentation"), cl::Hidden, cl::init(true))
static const uint64_t kAllocaRzSize
const char kODRGenPrefix[]
static const uint64_t kSystemZ_ShadowOffset64
static const uint64_t kDefaultShadowOffset32
const char kAsanShadowMemoryDynamicAddress[]
static cl::opt< bool > ClUseOdrIndicator("asan-use-odr-indicator", cl::desc("Use odr indicators to improve ODR reporting"), cl::Hidden, cl::init(true))
static bool GlobalWasGeneratedByCompiler(GlobalVariable *G)
Check if G has been created by a trusted compiler pass.
const char kAsanStackMallocAlwaysNameTemplate[]
static cl::opt< int > ClShadowAddrSpace("asan-shadow-addr-space", cl::desc("Address space for pointers to the shadow map"), cl::Hidden, cl::init(0))
static cl::opt< bool > ClInvalidPointerCmp("asan-detect-invalid-pointer-cmp", cl::desc("Instrument <, <=, >, >= with pointer operands"), cl::Hidden, cl::init(false))
static const uint64_t kAsanEmscriptenCtorAndDtorPriority
static cl::opt< int > ClInstrumentationWithCallsThreshold("asan-instrumentation-with-call-threshold", cl::desc("If the function being instrumented contains more than " "this number of memory accesses, use callbacks instead of " "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(7000))
static cl::opt< int > ClDebugMax("asan-debug-max", cl::desc("Debug max inst"), cl::Hidden, cl::init(-1))
static cl::opt< bool > ClInvalidPointerSub("asan-detect-invalid-pointer-sub", cl::desc("Instrument - operations with pointer operands"), cl::Hidden, cl::init(false))
static cl::list< unsigned > ClAddrSpaces("asan-instrument-address-spaces", cl::desc("Only instrument variables in the specified address spaces."), cl::Hidden, cl::CommaSeparated, cl::ZeroOrMore, cl::callback([](const unsigned &AddrSpace) { SrcAddrSpaces.insert(AddrSpace);}))
static const uint64_t kFreeBSD_ShadowOffset64
static cl::opt< uint32_t > ClForceExperiment("asan-force-experiment", cl::desc("Force optimization experiment (for testing)"), cl::Hidden, cl::init(0))
const char kSanCovGenPrefix[]
static const uint64_t kFreeBSDKasan_ShadowOffset64
const char kAsanModuleDtorName[]
static const uint64_t kDynamicShadowSentinel
static bool isInterestingPointerComparison(Instruction *I)
static cl::opt< bool > ClStack("asan-stack", cl::desc("Handle stack memory"), cl::Hidden, cl::init(true))
static const uint64_t kMIPS64_ShadowOffset64
static const uint64_t kLinuxKasan_ShadowOffset64
static int StackMallocSizeClass(uint64_t LocalStackSize)
static cl::opt< uint32_t > ClMaxInlinePoisoningSize("asan-max-inline-poisoning-size", cl::desc("Inline shadow poisoning for blocks up to the given size in bytes."), cl::Hidden, cl::init(64))
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClUseAfterScope("asan-use-after-scope", cl::desc("Check stack-use-after-scope"), cl::Hidden, cl::init(false))
constexpr size_t kAccessSizeIndexShift
static cl::opt< int > ClMappingScale("asan-mapping-scale", cl::desc("scale of asan shadow mapping"), cl::Hidden, cl::init(0))
const char kAsanPoisonStackMemoryName[]
static cl::opt< bool > ClEnableKasan("asan-kernel", cl::desc("Enable KernelAddressSanitizer instrumentation"), cl::Hidden, cl::init(false))
static cl::opt< std::string > ClDebugFunc("asan-debug-func", cl::Hidden, cl::desc("Debug func"))
static bool isSupportedAddrspace(const Triple &TargetTriple, Value *Addr)
static cl::opt< bool > ClUseGlobalsGC("asan-globals-live-support", cl::desc("Use linker features to support dead " "code stripping of globals"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
const char kAsanUnpoisonStackMemoryName[]
static const uint64_t kLoongArch64_ShadowOffset64
const char kAsanRegisterGlobalsName[]
static cl::opt< bool > ClInstrumentDynamicAllocas("asan-instrument-dynamic-allocas", cl::desc("instrument dynamic allocas"), cl::Hidden, cl::init(true))
const char kAsanModuleCtorName[]
const char kAsanGlobalsRegisteredFlagName[]
static const size_t kMaxStackMallocSize
static cl::opt< bool > ClRecover("asan-recover", cl::desc("Enable recovery mode (continue-after-error)."), cl::Hidden, cl::init(false))
static cl::opt< bool > ClOptSameTemp("asan-opt-same-temp", cl::desc("Instrument the same temp just once"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClDynamicAllocaStack("asan-stack-dynamic-alloca", cl::desc("Use dynamic alloca to represent stack variables"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClOptStack("asan-opt-stack", cl::desc("Don't instrument scalar stack variables"), cl::Hidden, cl::init(false))
static const uint64_t kMIPS_ShadowOffsetN32
const char kAsanUnregisterImageGlobalsName[]
static cl::opt< AsanDetectStackUseAfterReturnMode > ClUseAfterReturn("asan-use-after-return", cl::desc("Sets the mode of detection for stack-use-after-return."), cl::values(clEnumValN(AsanDetectStackUseAfterReturnMode::Never, "never", "Never detect stack use after return."), clEnumValN(AsanDetectStackUseAfterReturnMode::Runtime, "runtime", "Detect stack use after return if " "binary flag 'ASAN_OPTIONS=detect_stack_use_after_return' is set."), clEnumValN(AsanDetectStackUseAfterReturnMode::Always, "always", "Always detect stack use after return.")), cl::Hidden, cl::init(AsanDetectStackUseAfterReturnMode::Runtime))
static cl::opt< bool > ClOptGlobals("asan-opt-globals", cl::desc("Don't instrument scalar globals"), cl::Hidden, cl::init(true))
static const uintptr_t kCurrentStackFrameMagic
static ShadowMapping getShadowMapping(const Triple &TargetTriple, int LongSize, bool IsKasan)
static const uint64_t kPPC64_ShadowOffset64
static cl::opt< AsanCtorKind > ClConstructorKind("asan-constructor-kind", cl::desc("Sets the ASan constructor kind"), cl::values(clEnumValN(AsanCtorKind::None, "none", "No constructors"), clEnumValN(AsanCtorKind::Global, "global", "Use global constructors")), cl::init(AsanCtorKind::Global), cl::Hidden)
static const int kMaxAsanStackMallocSizeClass
static const uint64_t kMIPS32_ShadowOffset32
static cl::opt< bool > ClAlwaysSlowPath("asan-always-slow-path", cl::desc("use instrumentation with slow path for all accesses"), cl::Hidden, cl::init(false))
static const uint64_t kNetBSD_ShadowOffset32
static const uint64_t kFreeBSDAArch64_ShadowOffset64
static const uint64_t kSmallX86_64ShadowOffsetBase
static cl::opt< bool > ClInitializers("asan-initialization-order", cl::desc("Handle C++ initializer order"), cl::Hidden, cl::init(true))
static const uint64_t kNetBSD_ShadowOffset64
static cl::opt< unsigned > ClRealignStack("asan-realign-stack", cl::desc("Realign stack to the value of this flag (power of two)"), cl::Hidden, cl::init(32))
static const uint64_t kWindowsShadowOffset32
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static size_t TypeStoreSizeToSizeIndex(uint32_t TypeSize)
const char kAsanAllocaPoison[]
constexpr size_t kCompileKernelShift
static SmallSet< unsigned, 8 > SrcAddrSpaces
static cl::opt< bool > ClWithIfunc("asan-with-ifunc", cl::desc("Access dynamic shadow through an ifunc global on " "platforms that support this"), cl::Hidden, cl::init(true))
static cl::opt< bool > ClKasanMemIntrinCallbackPrefix("asan-kernel-mem-intrinsic-prefix", cl::desc("Use prefix for memory intrinsics in KASAN mode"), cl::Hidden, cl::init(false))
const char kAsanVersionCheckNamePrefix[]
const char kAMDGPUAddressPrivateName[]
static const uint64_t kNetBSDKasan_ShadowOffset64
const char kAMDGPUBallotName[]
const char kAsanRegisterElfGlobalsName[]
static cl::opt< uint64_t > ClMappingOffset("asan-mapping-offset", cl::desc("offset of asan shadow mapping [EXPERIMENTAL]"), cl::Hidden, cl::init(0))
const char kAsanReportErrorTemplate[]
static cl::opt< bool > ClWithComdat("asan-with-comdat", cl::desc("Place ASan constructors in comdat sections"), cl::Hidden, cl::init(true))
static StringRef getAllocaName(AllocaInst *AI)
static cl::opt< bool > ClSkipPromotableAllocas("asan-skip-promotable-allocas", cl::desc("Do not instrument promotable allocas"), cl::Hidden, cl::init(true))
static cl::opt< int > ClMaxInsnsToInstrumentPerBB("asan-max-ins-per-bb", cl::init(10000), cl::desc("maximal number of instructions to instrument in any given BB"), cl::Hidden)
static const uintptr_t kRetiredStackFrameMagic
static cl::opt< bool > ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(true), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional)
const char kAsanPoisonGlobalsName[]
const char kAsanHandleNoReturnName[]
static const size_t kMinStackMallocSize
static cl::opt< int > ClDebug("asan-debug", cl::desc("debug"), cl::Hidden, cl::init(0))
const char kAsanAllocasUnpoison[]
static const uint64_t kAArch64_ShadowOffset64
static cl::opt< bool > ClInvalidPointerPairs("asan-detect-invalid-pointer-pair", cl::desc("Instrument <, <=, >, >=, - with pointer operands"), cl::Hidden, cl::init(false))
Function Alias Analysis false
This file contains the simple types necessary to represent the attributes associated with functions a...
static bool isPointerOperand(Value *I, User *U)
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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 defines the DenseMap class.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
static bool runOnFunction(Function &F, bool PostInlining)
This is the interface for a simple mod/ref and alias analysis over globals.
Module.h This file contains the declarations for the Module class.
This defines the Use class.
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
print mir2vec MIR2Vec Vocabulary Printer Pass
Machine Check Debug Module
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
const SmallVectorImpl< MachineOperand > & Cond
void visit(MachineFunction &MF, MachineBasicBlock &Start, std::function< void(MachineBasicBlock *)> op)
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
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)
static SymbolRef::Type getType(const Symbol *Sym)
uint64_t getZExtValue() const
Get zero extended value.
int64_t getSExtValue() const
Get sign extended value.
LLVM_ABI AddressSanitizerPass(const AddressSanitizerOptions &Options, bool UseGlobalGC=true, bool UseOdrIndicator=true, AsanDtorKind DestructorKind=AsanDtorKind::Global, AsanCtorKind ConstructorKind=AsanCtorKind::Global)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)
an instruction to allocate memory on the stack
bool isSwiftError() const
Return true if this alloca is used as a swifterror argument to a call.
LLVM_ABI bool isStaticAlloca() const
Return true if this alloca is in the entry block of the function and is a constant size.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
PointerType * getType() const
Overload to return most specific pointer type.
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
bool isUsedWithInAlloca() const
Return true if this alloca is used as an inalloca argument to a call.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
void setAlignment(Align Align)
This class represents an incoming formal argument to a Function.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Class to represent array types.
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.
iterator begin()
Instruction iterator methods.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
LLVM_ABI const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
bool isInlineAsm() const
Check if this call is an inline asm statement.
static LLVM_ABI CallBase * addOperandBundle(CallBase *CB, uint32_t ID, OperandBundleDef OB, InsertPosition InsertPt=nullptr)
Create a clone of CB with operand bundle OB added.
bool doesNotReturn() const
Determine if the call cannot return.
unsigned arg_size() const
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
@ Largest
The linker will choose the largest COMDAT.
@ SameSize
The data referenced by the COMDAT must be the same size.
@ Any
The linker may choose any COMDAT.
@ NoDeduplicate
No deduplication is performed.
@ ExactMatch
The data referenced by the COMDAT must be the same.
ConstantArray - Constant Array Declarations.
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static LLVM_ABI Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static LLVM_ABI Constant * getPtrToInt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static LLVM_ABI bool isValueValidForType(Type *Ty, uint64_t V)
This static method returns true if the type Ty is big enough to represent the value V.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
A parsed version of the target data layout string in and methods for querying it.
LLVM_ABI DILocation * get() const
Get the underlying DILocation.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
const BasicBlock & front() const
static Function * createWithDefaultAttr(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Creates a function with some attributes recorded in llvm.module.flags and the LLVMContext applied.
bool hasPersonalityFn() const
Check whether this function has a personality function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
const Constant * getAliasee() const
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...
LLVM_ABI void copyMetadata(const GlobalObject *Src, unsigned Offset)
Copy metadata from Src, adjusting offsets by Offset.
LLVM_ABI void setComdat(Comdat *C)
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
VisibilityTypes getVisibility() const
void setUnnamedAddr(UnnamedAddr Val)
bool hasLocalLinkage() const
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
ThreadLocalMode getThreadLocalMode() const
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
LinkageTypes
An enumeration for the kinds of linkage for global values.
@ PrivateLinkage
Like Internal, but omit from symbol table.
@ CommonLinkage
Tentative definitions.
@ InternalLinkage
Rename collisions when linking (static functions).
@ AvailableExternallyLinkage
Available for inspection, not emission.
@ ExternalWeakLinkage
ExternalWeak linkage description.
DLLStorageClassTypes getDLLStorageClass() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ABI void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
Analysis pass providing a never-invalidated alias analysis result.
This instruction compares its operands according to the predicate given to the constructor.
Common base class shared among various IRBuilders.
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
IntegerType * getInt1Ty()
Fetch the type representing a single bit.
LLVM_ABI Value * CreateAllocationSize(Type *DestTy, AllocaInst *AI)
Get allocation size of an alloca as a runtime Value* (handles both static and dynamic allocas and vsc...
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, const AAMDNodes &AAInfo=AAMDNodes())
Create and insert a memcpy between the specified pointers.
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name="")
LLVM_ABI Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
BasicBlock::iterator GetInsertPoint() const
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())
BasicBlock * GetInsertBlock() const
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
LLVM_ABI CallInst * CreateIntrinsic(Intrinsic::ID ID, ArrayRef< Type * > Types, ArrayRef< Value * > Args, FMFSource FMFSource={}, const Twine &Name="")
Create a call to intrinsic ID with Args, mangled using Types.
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateNot(Value *V, const Twine &Name="")
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
ConstantInt * getIntN(unsigned N, uint64_t C)
Get a constant N-bit value, zero extended from a 64-bit value.
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateIsNotNull(Value *Arg, const Twine &Name="")
Return a boolean value testing if Arg != 0.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args={}, const Twine &Name="", MDNode *FPMathTag=nullptr)
LLVM_ABI Value * CreateTypeSize(Type *Ty, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="", bool IsDisjoint=false)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
Value * CreateAddrSpaceCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=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.
Base class for instruction visitors.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void moveBefore(InstListType::iterator InsertPos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
A wrapper class for inspecting calls to intrinsic functions.
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
An instruction for reading from memory.
static Error ParseSectionSpecifier(StringRef Spec, StringRef &Segment, StringRef &Section, unsigned &TAA, bool &TAAParsed, unsigned &StubSize)
Parse the section specifier indicated by "Spec".
LLVM_ABI MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
ArrayRef< MDOperand > operands() const
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
This is the common base class for memset/memcpy/memmove.
A Module instance is used to store all the information related to an LLVM module.
Evaluate the size and offset of an object pointed to by a Value* statically.
LLVM_ABI SizeOffsetAPInt compute(Value *V)
Pass interface - Implemented by all 'passes'.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
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.
Return a value (possibly void), from a function.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This pass performs the global (interprocedural) stack safety analysis (new pass manager).
bool stackAccessIsSafe(const Instruction &I) const
bool isSafe(const AllocaInst &AI) const
An instruction for storing to memory.
StringRef - Represent a constant reference to a string, i.e.
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
constexpr bool empty() const
empty - Check if the string is empty.
Class to represent struct types.
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 TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
Triple - Helper class for working with autoconf configuration names.
bool isThumb() const
Tests whether the target is Thumb (little and big endian).
bool isDriverKit() const
Is this an Apple DriverKit triple.
bool isBPF() const
Tests whether the target is eBPF.
bool isAndroid() const
Tests whether the target is Android.
bool isMIPS64() const
Tests whether the target is MIPS 64-bit (little and big endian).
ArchType getArch() const
Get the parsed architecture type of this triple.
bool isLoongArch64() const
Tests whether the target is 64-bit LoongArch.
bool isMIPS32() const
Tests whether the target is MIPS 32-bit (little and big endian).
bool isOSWindows() const
Tests whether the OS is Windows.
bool isARM() const
Tests whether the target is ARM (little and big endian).
bool isOSLinux() const
Tests whether the OS is Linux.
bool isMacOSX() const
Is this a Mac OS X triple.
bool isOSEmscripten() const
Tests whether the OS is Emscripten.
bool isWatchOS() const
Is this an Apple watchOS triple.
bool isiOS() const
Is this an iOS triple.
bool isPS() const
Tests whether the target is the PS4 or PS5 platform.
bool isWasm() const
Tests whether the target is wasm (32- and 64-bit).
bool isOSHaiku() const
Tests whether the OS is Haiku.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
This function has undefined behavior.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI bool isSwiftError() const
Return true if this value is a swifterror value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Base class of all SIMD vector types.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr ScalarTy getFixedValue() const
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
self_iterator getIterator()
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.
This file contains the declaration of the Comdat class, which represents a single COMDAT in LLVM.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void getInterestingMemoryOperands(Module &M, Instruction *I, SmallVectorImpl< InterestingMemoryOperand > &Interesting)
Get all the memory operands from the instruction that needs to be instrumented.
void instrumentAddress(Module &M, IRBuilder<> &IRB, Instruction *OrigIns, Instruction *InsertBefore, Value *Addr, Align Alignment, TypeSize TypeStoreSize, bool IsWrite, Value *SizeArgument, bool UseCalls, bool Recover, int AsanScale, int AsanOffset)
Instrument the memory operand Addr.
uint64_t getRedzoneSizeForGlobal(int AsanScale, uint64_t SizeInBytes)
Given SizeInBytes of the Value to be instrunmented, Returns the redzone size corresponding to it.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ S_CSTRING_LITERALS
S_CSTRING_LITERALS - Section with literal C strings.
@ OB
OB - OneByte - Set if this instruction has a one byte opcode.
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)
cb< typename detail::callback_traits< F >::result_type, typename detail::callback_traits< F >::arg_type > callback(F CB)
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
Context & getContext() const
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
FunctionAddr VTableAddr Value
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI SmallVector< uint8_t, 64 > GetShadowBytesAfterScope(const SmallVectorImpl< ASanStackVariableDescription > &Vars, const ASanStackFrameLayout &Layout)
LLVM_ABI GlobalVariable * createPrivateGlobalForString(Module &M, StringRef Str, bool AllowMerging, Twine NamePrefix="")
LLVM_ABI AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
LLVM_ABI Function * createSanitizerCtor(Module &M, StringRef CtorName)
Creates sanitizer constructor function.
AsanDetectStackUseAfterReturnMode
Mode of ASan detect stack use after return.
@ Always
Always detect stack use after return.
@ Never
Never detect stack use after return.
@ Runtime
Detect stack use after return if not disabled runtime with (ASAN_OPTIONS=detect_stack_use_after_retur...
LLVM_ABI DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
LLVM_ABI SmallString< 64 > ComputeASanStackFrameDescription(const SmallVectorImpl< ASanStackVariableDescription > &Vars)
LLVM_ABI SmallVector< uint8_t, 64 > GetShadowBytes(const SmallVectorImpl< ASanStackVariableDescription > &Vars, const ASanStackFrameLayout &Layout)
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef< Type * > InitArgTypes, bool Weak=false)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
LLVM_ABI std::string getUniqueModuleId(Module *M)
Produce a unique identifier for this module by taking the MD5 sum of the names of the module's strong...
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI std::pair< Function *, FunctionCallee > createSanitizerCtorAndInitFunctions(Module &M, StringRef CtorName, StringRef InitName, ArrayRef< Type * > InitArgTypes, ArrayRef< Value * > InitArgs, StringRef VersionCheckName=StringRef(), bool Weak=false)
Creates sanitizer constructor function, and calls sanitizer's init function from it.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void SplitBlockAndInsertIfThenElse(Value *Cond, BasicBlock::iterator SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isAlnum(char C)
Checks whether character C is either a decimal digit or an uppercase or lowercase letter as classifie...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
AsanDtorKind
Types of ASan module destructors supported.
@ Invalid
Not a valid destructor Kind.
@ Global
Append to llvm.global_dtors.
@ None
Do not emit any destructors for ASan.
LLVM_ABI ASanStackFrameLayout ComputeASanStackFrameLayout(SmallVectorImpl< ASanStackVariableDescription > &Vars, uint64_t Granularity, uint64_t MinHeaderSize)
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
OperandBundleDefT< Value * > OperandBundleDef
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
static const int kAsanStackUseAfterReturnMagic
LLVM_ABI void setGlobalVariableLargeSection(const Triple &TargetTriple, GlobalVariable &GV)
void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem)
Remove memory attributes that are incompatible with the instrumentation added by AddressSanitizer and...
@ Dynamic
Denotes mode unknown at compile time.
ArrayRef(const T &OneElt) -> ArrayRef< T >
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.
TinyPtrVector< BasicBlock * > ColorVector
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
iterator_range< df_iterator< T > > depth_first(const T &G)
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 ...
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
AsanCtorKind
Types of ASan module constructors supported.
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 void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
LLVM_ABI void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Same as appendToGlobalCtors(), but for global dtors.
LLVM_ABI bool checkIfAlreadyInstrumented(Module &M, StringRef Flag)
Check if module has flag attached, if not add the flag.
void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize, bool IsKasan, uint64_t *ShadowBase, int *MappingScale, bool *OrShadowOffset)
DEMANGLE_ABI std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
std::string itostr(int64_t X)
LLVM_ABI void SplitBlockAndInsertForEachLane(ElementCount EC, Type *IndexTy, BasicBlock::iterator InsertBefore, std::function< void(IRBuilderBase &, Value *)> Func)
Utility function for performing a given action on each lane of a vector with EC elements.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI bool replaceDbgDeclare(Value *Address, Value *NewAddress, DIBuilder &Builder, uint8_t DIExprFlags, int Offset)
Replaces dbg.declare record when the address it describes is replaced with a new value.
LLVM_ABI ASanAccessInfo(int32_t Packed)
const uint8_t AccessSizeIndex
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Align valueOrOne() const
For convenience, returns a valid alignment or 1 if undefined.
Information about a load/store intrinsic defined by the target.
SmallVector< InterestingMemoryOperand, 1 > InterestingOperands
A CRTP mix-in to automatically provide informational APIs needed for passes.
SizeOffsetAPInt - Used by ObjectSizeOffsetVisitor, which works with APInts.