94#define DEBUG_TYPE "asan"
100 std::numeric_limits<uint64_t>::max();
141 "__asan_unregister_image_globals";
154 "__asan_stack_malloc_always_";
168 "__asan_option_detect_stack_use_after_return";
171 "__asan_shadow_memory_dynamic_address";
197 "asan-kernel",
cl::desc(
"Enable KernelAddressSanitizer instrumentation"),
202 cl::desc(
"Enable recovery mode (continue-after-error)."),
206 "asan-guard-against-version-mismatch",
212 cl::desc(
"instrument read instructions"),
216 "asan-instrument-writes",
cl::desc(
"instrument write instructions"),
225 "asan-instrument-atomics",
235 "asan-always-slow-path",
240 "asan-force-dynamic-shadow",
241 cl::desc(
"Load shadow address into a local variable for each function"),
246 cl::desc(
"Access dynamic shadow through an ifunc global on "
247 "platforms that support this"),
251 "asan-with-ifunc-suppress-remat",
252 cl::desc(
"Suppress rematerialization of dynamic shadow address by passing "
253 "it through inline asm in prologue."),
261 "asan-max-ins-per-bb",
cl::init(10000),
262 cl::desc(
"maximal number of instructions to instrument in any given BB"),
269 "asan-max-inline-poisoning-size",
271 "Inline shadow poisoning for blocks up to the given size in bytes."),
275 "asan-use-after-return",
276 cl::desc(
"Sets the mode of detection for stack-use-after-return."),
278 clEnumValN(AsanDetectStackUseAfterReturnMode::Never,
"never",
279 "Never detect stack use after return."),
281 AsanDetectStackUseAfterReturnMode::Runtime,
"runtime",
282 "Detect stack use after return if "
283 "binary flag 'ASAN_OPTIONS=detect_stack_use_after_return' is set."),
284 clEnumValN(AsanDetectStackUseAfterReturnMode::Always,
"always",
285 "Always detect stack use after return.")),
289 cl::desc(
"Create redzones for byval "
290 "arguments (extra copy "
295 cl::desc(
"Check stack-use-after-scope"),
304 cl::desc(
"Handle C++ initializer order"),
308 "asan-detect-invalid-pointer-pair",
313 "asan-detect-invalid-pointer-cmp",
318 "asan-detect-invalid-pointer-sub",
323 "asan-realign-stack",
324 cl::desc(
"Realign stack to the value of this flag (power of two)"),
328 "asan-instrumentation-with-call-threshold",
329 cl::desc(
"If the function being instrumented contains more than "
330 "this number of memory accesses, use callbacks instead of "
331 "inline checks (-1 means never use callbacks)."),
335 "asan-memory-access-callback-prefix",
340 "asan-kernel-mem-intrinsic-prefix",
346 cl::desc(
"instrument dynamic allocas"),
350 "asan-skip-promotable-allocas",
355 "asan-constructor-kind",
356 cl::desc(
"Sets the ASan constructor kind"),
359 "Use global constructors")),
366 cl::desc(
"scale of asan shadow mapping"),
371 cl::desc(
"offset of asan shadow mapping [EXPERIMENTAL]"),
385 "asan-opt-same-temp",
cl::desc(
"Instrument the same temp just once"),
389 cl::desc(
"Don't instrument scalar globals"),
393 "asan-opt-stack",
cl::desc(
"Don't instrument scalar stack variables"),
397 "asan-stack-dynamic-alloca",
402 "asan-force-experiment",
408 cl::desc(
"Use private aliases for global variables"),
413 cl::desc(
"Use odr indicators to improve ODR reporting"),
418 cl::desc(
"Use linker features to support dead "
419 "code stripping of globals"),
426 cl::desc(
"Place ASan constructors in comdat sections"),
430 "asan-destructor-kind",
431 cl::desc(
"Sets the ASan destructor kind. The default is to use the value "
432 "provided to the pass constructor"),
435 "Use global destructors")),
455STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
456STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
458 "Number of optimized accesses to global vars");
460 "Number of optimized accesses to stack vars");
469struct ShadowMapping {
480 bool IsAndroid = TargetTriple.
isAndroid();
483 bool IsMacOS = TargetTriple.
isMacOSX();
486 bool IsPS = TargetTriple.
isPS();
493 bool IsMIPS32 = TargetTriple.
isMIPS32();
494 bool IsMIPS64 = TargetTriple.
isMIPS64();
495 bool IsArmOrThumb = TargetTriple.
isARM() || TargetTriple.
isThumb();
503 bool IsAMDGPU = TargetTriple.
isAMDGPU();
505 ShadowMapping Mapping;
512 if (LongSize == 32) {
515 else if (IsMIPSN32ABI)
527 else if (IsEmscripten)
540 else if (IsFreeBSD && IsAArch64)
542 else if (IsFreeBSD && !IsMIPS64) {
547 }
else if (IsNetBSD) {
554 else if (IsLinux && IsX86_64) {
560 }
else if (IsWindows && IsX86_64) {
566 else if (IsMacOS && IsAArch64)
570 else if (IsLoongArch64)
594 Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS &&
595 !IsRISCV64 && !IsLoongArch64 &&
596 !(Mapping.Offset & (Mapping.Offset - 1)) &&
598 bool IsAndroidWithIfuncSupport =
600 Mapping.InGlobal =
ClWithIfunc && IsAndroidWithIfuncSupport && IsArmOrThumb;
608 int *MappingScale,
bool *OrShadowOffset) {
610 *ShadowBase = Mapping.Offset;
611 *MappingScale = Mapping.Scale;
612 *OrShadowOffset = Mapping.OrShadowOffset;
622 uint8_t AccessSizeIndex)
626 AccessSizeIndex(AccessSizeIndex), IsWrite(IsWrite),
627 CompileKernel(CompileKernel) {}
634 return std::max(32U, 1U << MappingScale);
649class RuntimeCallInserter {
651 bool TrackInsertedCalls =
false;
655 RuntimeCallInserter(
Function &Fn) : OwnerFn(&Fn) {
659 TrackInsertedCalls =
true;
663 ~RuntimeCallInserter() {
664 if (InsertedCalls.
empty())
666 assert(TrackInsertedCalls &&
"Calls were wrongly tracked");
669 for (
CallInst *CI : InsertedCalls) {
671 assert(BB &&
"Instruction doesn't belong to a BasicBlock");
673 "Instruction doesn't belong to the expected Function!");
681 if (Colors.
size() != 1) {
683 "Instruction's BasicBlock is not monochromatic");
690 if (EHPad && EHPad->
isEHPad()) {
695 NewCall->copyMetadata(*CI);
696 CI->replaceAllUsesWith(NewCall);
697 CI->eraseFromParent();
708 if (TrackInsertedCalls)
709 InsertedCalls.push_back(Inst);
715struct AddressSanitizer {
717 int InstrumentationWithCallsThreshold,
718 uint32_t MaxInlinePoisoningSize,
bool CompileKernel =
false,
719 bool Recover =
false,
bool UseAfterScope =
false,
721 AsanDetectStackUseAfterReturnMode::Runtime)
729 InstrumentationWithCallsThreshold(
732 : InstrumentationWithCallsThreshold),
735 : MaxInlinePoisoningSize) {
736 C = &(
M.getContext());
737 DL = &
M.getDataLayout();
738 LongSize =
M.getDataLayout().getPointerSizeInBits();
740 PtrTy = PointerType::getUnqual(*C);
742 TargetTriple =
Triple(
M.getTargetTriple());
746 assert(this->UseAfterReturn != AsanDetectStackUseAfterReturnMode::Invalid);
754 bool isInterestingAlloca(
const AllocaInst &AI);
757 void getInterestingMemoryOperands(
762 const DataLayout &DL, RuntimeCallInserter &RTCI);
763 void instrumentPointerComparisonOrSubtraction(
Instruction *
I,
764 RuntimeCallInserter &RTCI);
767 uint32_t TypeStoreSize,
bool IsWrite,
769 RuntimeCallInserter &RTCI);
772 uint32_t TypeStoreSize,
bool IsWrite,
773 Value *SizeArgument);
778 TypeSize TypeStoreSize,
bool IsWrite,
779 Value *SizeArgument,
bool UseCalls,
781 RuntimeCallInserter &RTCI);
782 void instrumentMaskedLoadOrStore(AddressSanitizer *
Pass,
const DataLayout &DL,
786 Type *OpType,
bool IsWrite,
787 Value *SizeArgument,
bool UseCalls,
788 uint32_t Exp, RuntimeCallInserter &RTCI);
792 bool IsWrite,
size_t AccessSizeIndex,
794 RuntimeCallInserter &RTCI);
795 void instrumentMemIntrinsic(
MemIntrinsic *
MI, RuntimeCallInserter &RTCI);
797 bool suppressInstrumentationSiteForDebug(
int &Instrumented);
799 bool maybeInsertAsanInitAtFunctionEntry(
Function &
F);
800 bool maybeInsertDynamicShadowAtFunctionEntry(
Function &
F);
801 void markEscapedLocalAllocas(
Function &
F);
804 friend struct FunctionStackPoisoner;
814 struct FunctionStateRAII {
815 AddressSanitizer *
Pass;
817 FunctionStateRAII(AddressSanitizer *
Pass) :
Pass(
Pass) {
819 "last pass forgot to clear cache");
823 ~FunctionStateRAII() {
824 Pass->LocalDynamicShadow =
nullptr;
825 Pass->ProcessedAllocas.clear();
840 ShadowMapping Mapping;
854 Value *LocalDynamicShadow =
nullptr;
860 int InstrumentationWithCallsThreshold;
864class ModuleAddressSanitizer {
866 ModuleAddressSanitizer(
Module &M,
bool InsertVersionCheck,
867 bool CompileKernel =
false,
bool Recover =
false,
868 bool UseGlobalsGC =
true,
bool UseOdrIndicator =
true,
875 : InsertVersionCheck),
877 UseGlobalsGC(UseGlobalsGC &&
ClUseGlobalsGC && !this->CompileKernel),
892 UseCtorComdat(UseGlobalsGC &&
ClWithComdat && !this->CompileKernel),
893 DestructorKind(DestructorKind),
897 C = &(
M.getContext());
898 int LongSize =
M.getDataLayout().getPointerSizeInBits();
900 PtrTy = PointerType::getUnqual(*C);
901 TargetTriple =
Triple(
M.getTargetTriple());
906 assert(this->DestructorKind != AsanDtorKind::Invalid);
909 bool instrumentModule(
Module &);
912 void initializeCallbacks(
Module &M);
921 const std::string &UniqueModuleId);
938 bool ShouldUseMachOGlobalsSection()
const;
939 StringRef getGlobalMetadataSection()
const;
942 uint64_t getMinRedzoneSizeForGlobal()
const {
946 int GetAsanVersion(
const Module &M)
const;
949 bool InsertVersionCheck;
952 bool UsePrivateAlias;
953 bool UseOdrIndicator;
961 ShadowMapping Mapping;
971 Function *AsanCtorFunction =
nullptr;
972 Function *AsanDtorFunction =
nullptr;
984struct FunctionStackPoisoner :
public InstVisitor<FunctionStackPoisoner> {
986 AddressSanitizer &ASan;
987 RuntimeCallInserter &RTCI;
992 ShadowMapping Mapping;
1001 FunctionCallee AsanPoisonStackMemoryFunc, AsanUnpoisonStackMemoryFunc;
1005 struct AllocaPoisonCall {
1013 bool HasUntracedLifetimeIntrinsic =
false;
1020 bool HasInlineAsm =
false;
1021 bool HasReturnsTwiceCall =
false;
1024 FunctionStackPoisoner(
Function &F, AddressSanitizer &ASan,
1025 RuntimeCallInserter &RTCI)
1026 :
F(
F), ASan(ASan), RTCI(RTCI),
1028 IntptrTy(ASan.IntptrTy), IntptrPtrTy(
PointerType::
get(IntptrTy, 0)),
1029 Mapping(ASan.Mapping),
1038 copyArgsPassedByValToAllocas();
1043 if (AllocaVec.
empty() && DynamicAllocaVec.
empty())
return false;
1045 initializeCallbacks(*
F.getParent());
1047 if (HasUntracedLifetimeIntrinsic) {
1051 StaticAllocaPoisonCallVec.
clear();
1052 DynamicAllocaPoisonCallVec.
clear();
1055 processDynamicAllocas();
1056 processStaticAllocas();
1067 void copyArgsPassedByValToAllocas();
1072 void processStaticAllocas();
1073 void processDynamicAllocas();
1075 void createDynamicAllocasInitStorage();
1093 void unpoisonDynamicAllocasBeforeInst(
Instruction *InstBefore,
1094 Value *SavedStack) {
1101 if (!isa<ReturnInst>(InstBefore)) {
1103 InstBefore->
getModule(), Intrinsic::get_dynamic_area_offset,
1112 RTCI.createRuntimeCall(
1113 IRB, AsanAllocasUnpoisonFunc,
1114 {IRB.
CreateLoad(IntptrTy, DynamicAllocaLayout), DynamicAreaPtr});
1118 void unpoisonDynamicAllocas() {
1120 unpoisonDynamicAllocasBeforeInst(Ret, DynamicAllocaLayout);
1122 for (
Instruction *StackRestoreInst : StackRestoreVec)
1123 unpoisonDynamicAllocasBeforeInst(StackRestoreInst,
1124 StackRestoreInst->getOperand(0));
1137 void handleDynamicAllocaCall(
AllocaInst *AI);
1143 const auto *STy = dyn_cast<StructType>(AllocaType);
1144 if (!ASan.isInterestingAlloca(AI) || isa<ScalableVectorType>(AllocaType) ||
1145 (STy && STy->containsHomogeneousScalableVectorTypes())) {
1149 if (AllocaVec.
empty())
1167 if (
ID == Intrinsic::stackrestore) StackRestoreVec.
push_back(&
II);
1168 if (
ID == Intrinsic::localescape) LocalEscapeCall = &
II;
1169 if (!ASan.UseAfterScope)
1171 if (!
II.isLifetimeStartOrEnd())
1174 auto *
Size = cast<ConstantInt>(
II.getArgOperand(0));
1176 if (
Size->isMinusOne())
return;
1179 const uint64_t SizeValue =
Size->getValue().getLimitedValue();
1180 if (SizeValue == ~0ULL ||
1188 HasUntracedLifetimeIntrinsic =
true;
1192 if (!ASan.isInterestingAlloca(*AI))
1194 bool DoPoison = (
ID == Intrinsic::lifetime_end);
1195 AllocaPoisonCall APC = {&
II, AI, SizeValue, DoPoison};
1197 StaticAllocaPoisonCallVec.
push_back(APC);
1199 DynamicAllocaPoisonCallVec.
push_back(APC);
1203 if (
CallInst *CI = dyn_cast<CallInst>(&CB)) {
1204 HasInlineAsm |= CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow;
1205 HasReturnsTwiceCall |= CI->canReturnTwice();
1210 void initializeCallbacks(
Module &M);
1237 OS, MapClassName2PassName);
1249 UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
1250 ConstructorKind(ConstructorKind) {}
1254 ModuleAddressSanitizer ModuleSanitizer(
1256 UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind);
1262 AddressSanitizer FunctionSanitizer(
1267 Modified |= FunctionSanitizer.instrumentFunction(
F, &TLI);
1269 Modified |= ModuleSanitizer.instrumentModule(M);
1290 if (
G->getName().starts_with(
"llvm.") ||
1292 G->getName().starts_with(
"__llvm_gcov_ctr") ||
1294 G->getName().starts_with(
"__llvm_rtti_proxy"))
1307 Type *PtrTy = cast<PointerType>(
Addr->getType()->getScalarType());
1309 if (AddrSpace == 3 || AddrSpace == 5)
1316 Shadow = IRB.
CreateLShr(Shadow, Mapping.Scale);
1317 if (Mapping.Offset == 0)
return Shadow;
1320 if (LocalDynamicShadow)
1321 ShadowBase = LocalDynamicShadow;
1323 ShadowBase = ConstantInt::get(IntptrTy, Mapping.Offset);
1324 if (Mapping.OrShadowOffset)
1325 return IRB.
CreateOr(Shadow, ShadowBase);
1327 return IRB.
CreateAdd(Shadow, ShadowBase);
1332 RuntimeCallInserter &RTCI) {
1334 if (isa<MemTransferInst>(
MI)) {
1335 RTCI.createRuntimeCall(
1336 IRB, isa<MemMoveInst>(
MI) ? AsanMemmove : AsanMemcpy,
1340 }
else if (isa<MemSetInst>(
MI)) {
1341 RTCI.createRuntimeCall(
1347 MI->eraseFromParent();
1351bool AddressSanitizer::isInterestingAlloca(
const AllocaInst &AI) {
1352 auto PreviouslySeenAllocaInfo = ProcessedAllocas.find(&AI);
1354 if (PreviouslySeenAllocaInfo != ProcessedAllocas.end())
1355 return PreviouslySeenAllocaInfo->getSecond();
1357 bool IsInteresting =
1370 !(SSGI && SSGI->
isSafe(AI)));
1372 ProcessedAllocas[&AI] = IsInteresting;
1373 return IsInteresting;
1378 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
1387 if (
Ptr->isSwiftError())
1393 if (
auto AI = dyn_cast_or_null<AllocaInst>(
Ptr))
1404void AddressSanitizer::getInterestingMemoryOperands(
1407 if (LocalDynamicShadow ==
I)
1410 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
1413 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
1414 LI->getType(), LI->getAlign());
1415 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1419 SI->getValueOperand()->getType(),
SI->getAlign());
1423 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
1424 RMW->getValOperand()->getType(), std::nullopt);
1428 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
1429 XCHG->getCompareOperand()->getType(),
1431 }
else if (
auto CI = dyn_cast<CallInst>(
I)) {
1432 switch (CI->getIntrinsicID()) {
1433 case Intrinsic::masked_load:
1434 case Intrinsic::masked_store:
1435 case Intrinsic::masked_gather:
1436 case Intrinsic::masked_scatter: {
1437 bool IsWrite = CI->getType()->isVoidTy();
1439 unsigned OpOffset = IsWrite ? 1 : 0;
1443 auto BasePtr = CI->getOperand(OpOffset);
1444 if (ignoreAccess(
I, BasePtr))
1446 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1449 if (
auto *
Op = dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
1450 Alignment =
Op->getMaybeAlignValue();
1451 Value *
Mask = CI->getOperand(2 + OpOffset);
1452 Interesting.
emplace_back(
I, OpOffset, IsWrite, Ty, Alignment, Mask);
1455 case Intrinsic::masked_expandload:
1456 case Intrinsic::masked_compressstore: {
1457 bool IsWrite = CI->getIntrinsicID() == Intrinsic::masked_compressstore;
1458 unsigned OpOffset = IsWrite ? 1 : 0;
1461 auto BasePtr = CI->getOperand(OpOffset);
1462 if (ignoreAccess(
I, BasePtr))
1465 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1468 Value *
Mask = CI->getOperand(1 + OpOffset);
1471 Value *ExtMask =
IB.CreateZExt(Mask, ExtTy);
1472 Value *EVL =
IB.CreateAddReduce(ExtMask);
1473 Value *TrueMask = ConstantInt::get(
Mask->getType(), 1);
1474 Interesting.
emplace_back(
I, OpOffset, IsWrite, Ty, Alignment, TrueMask,
1478 case Intrinsic::vp_load:
1479 case Intrinsic::vp_store:
1480 case Intrinsic::experimental_vp_strided_load:
1481 case Intrinsic::experimental_vp_strided_store: {
1482 auto *VPI = cast<VPIntrinsic>(CI);
1483 unsigned IID = CI->getIntrinsicID();
1484 bool IsWrite = CI->getType()->isVoidTy();
1487 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1488 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1489 MaybeAlign Alignment = VPI->getOperand(PtrOpNo)->getPointerAlignment(*
DL);
1490 Value *Stride =
nullptr;
1491 if (IID == Intrinsic::experimental_vp_strided_store ||
1492 IID == Intrinsic::experimental_vp_strided_load) {
1493 Stride = VPI->getOperand(PtrOpNo + 1);
1498 if (!isa<ConstantInt>(Stride) ||
1499 cast<ConstantInt>(Stride)->getZExtValue() % PointerAlign != 0)
1500 Alignment =
Align(1);
1502 Interesting.
emplace_back(
I, PtrOpNo, IsWrite, Ty, Alignment,
1503 VPI->getMaskParam(), VPI->getVectorLengthParam(),
1507 case Intrinsic::vp_gather:
1508 case Intrinsic::vp_scatter: {
1509 auto *VPI = cast<VPIntrinsic>(CI);
1510 unsigned IID = CI->getIntrinsicID();
1511 bool IsWrite = IID == Intrinsic::vp_scatter;
1514 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1515 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1516 MaybeAlign Alignment = VPI->getPointerAlignment();
1517 Interesting.
emplace_back(
I, PtrOpNo, IsWrite, Ty, Alignment,
1518 VPI->getMaskParam(),
1519 VPI->getVectorLengthParam());
1523 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
1525 ignoreAccess(
I, CI->getArgOperand(ArgNo)))
1527 Type *Ty = CI->getParamByValType(ArgNo);
1535 return V->getType()->isPointerTy() || isa<PtrToIntInst>(V);
1542 if (
ICmpInst *Cmp = dyn_cast<ICmpInst>(
I)) {
1543 if (!Cmp->isRelational())
1557 if (BO->getOpcode() != Instruction::Sub)
1570 if (!
G->hasInitializer())
1573 if (
G->hasSanitizerMetadata() &&
G->getSanitizerMetadata().IsDynInit)
1579void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
1582 FunctionCallee F = isa<ICmpInst>(
I) ? AsanPtrCmpFunction : AsanPtrSubFunction;
1583 Value *
Param[2] = {
I->getOperand(0),
I->getOperand(1)};
1584 for (
Value *&i : Param) {
1585 if (i->getType()->isPointerTy())
1588 RTCI.createRuntimeCall(IRB,
F, Param);
1594 TypeSize TypeStoreSize,
bool IsWrite,
1595 Value *SizeArgument,
bool UseCalls,
1596 uint32_t Exp, RuntimeCallInserter &RTCI) {
1601 switch (FixedSize) {
1607 if (!Alignment || *Alignment >= Granularity ||
1608 *Alignment >= FixedSize / 8)
1609 return Pass->instrumentAddress(
I, InsertBefore,
Addr, Alignment,
1610 FixedSize, IsWrite,
nullptr, UseCalls,
1614 Pass->instrumentUnusualSizeOrAlignment(
I, InsertBefore,
Addr, TypeStoreSize,
1615 IsWrite,
nullptr, UseCalls, Exp, RTCI);
1618void AddressSanitizer::instrumentMaskedLoadOrStore(
1621 MaybeAlign Alignment,
unsigned Granularity,
Type *OpType,
bool IsWrite,
1623 RuntimeCallInserter &RTCI) {
1624 auto *VTy = cast<VectorType>(OpType);
1625 TypeSize ElemTypeSize =
DL.getTypeStoreSizeInBits(VTy->getScalarType());
1626 auto Zero = ConstantInt::get(IntptrTy, 0);
1634 Value *IsEVLZero =
IB.CreateICmpNE(EVL, ConstantInt::get(EVLType, 0));
1636 IB.SetInsertPoint(LoopInsertBefore);
1638 EVL =
IB.CreateZExtOrTrunc(EVL, IntptrTy);
1641 Value *
EC =
IB.CreateElementCount(IntptrTy, VTy->getElementCount());
1642 EVL =
IB.CreateBinaryIntrinsic(Intrinsic::umin, EVL, EC);
1644 EVL =
IB.CreateElementCount(IntptrTy, VTy->getElementCount());
1649 Stride =
IB.CreateZExtOrTrunc(Stride, IntptrTy);
1654 if (
auto *MaskElemC = dyn_cast<ConstantInt>(MaskElem)) {
1655 if (MaskElemC->isZero())
1666 Value *InstrumentedAddress;
1667 if (isa<VectorType>(
Addr->getType())) {
1669 cast<VectorType>(
Addr->getType())->getElementType()->isPointerTy() &&
1670 "Expected vector of pointer.");
1672 }
else if (Stride) {
1679 Alignment, Granularity, ElemTypeSize, IsWrite,
1680 SizeArgument, UseCalls, Exp, RTCI);
1687 RuntimeCallInserter &RTCI) {
1708 isSafeAccess(ObjSizeVis,
Addr,
O.TypeStoreSize)) {
1709 NumOptimizedAccessesToGlobalVar++;
1717 isSafeAccess(ObjSizeVis,
Addr,
O.TypeStoreSize)) {
1718 NumOptimizedAccessesToStackVar++;
1724 NumInstrumentedWrites++;
1726 NumInstrumentedReads++;
1728 unsigned Granularity = 1 << Mapping.Scale;
1730 instrumentMaskedLoadOrStore(
this,
DL, IntptrTy,
O.MaybeMask,
O.MaybeEVL,
1731 O.MaybeStride,
O.getInsn(),
Addr,
O.Alignment,
1732 Granularity,
O.OpType,
O.IsWrite,
nullptr,
1733 UseCalls, Exp, RTCI);
1736 Granularity,
O.TypeStoreSize,
O.IsWrite,
nullptr,
1737 UseCalls, Exp, RTCI);
1743 size_t AccessSizeIndex,
1744 Value *SizeArgument,
1746 RuntimeCallInserter &RTCI) {
1752 Call = RTCI.createRuntimeCall(IRB, AsanErrorCallbackSized[IsWrite][0],
1753 {
Addr, SizeArgument});
1755 Call = RTCI.createRuntimeCall(IRB, AsanErrorCallbackSized[IsWrite][1],
1756 {
Addr, SizeArgument, ExpVal});
1759 Call = RTCI.createRuntimeCall(
1760 IRB, AsanErrorCallback[IsWrite][0][AccessSizeIndex],
Addr);
1762 Call = RTCI.createRuntimeCall(
1763 IRB, AsanErrorCallback[IsWrite][1][AccessSizeIndex], {
Addr, ExpVal});
1766 Call->setCannotMerge();
1773 size_t Granularity =
static_cast<size_t>(1) << Mapping.Scale;
1775 Value *LastAccessedByte =
1776 IRB.
CreateAnd(AddrLong, ConstantInt::get(IntptrTy, Granularity - 1));
1778 if (TypeStoreSize / 8 > 1)
1780 LastAccessedByte, ConstantInt::get(IntptrTy, TypeStoreSize / 8 - 1));
1788Instruction *AddressSanitizer::instrumentAMDGPUAddress(
1790 uint32_t TypeStoreSize,
bool IsWrite,
Value *SizeArgument) {
1794 Type *PtrTy = cast<PointerType>(
Addr->getType()->getScalarType());
1797 return InsertBefore;
1802 Value *IsSharedOrPrivate = IRB.
CreateOr(IsShared, IsPrivate);
1804 Value *AddrSpaceZeroLanding =
1806 InsertBefore = cast<Instruction>(AddrSpaceZeroLanding);
1807 return InsertBefore;
1823 Trm->getParent()->setName(
"asan.report");
1834void AddressSanitizer::instrumentAddress(
Instruction *OrigIns,
1837 uint32_t TypeStoreSize,
bool IsWrite,
1838 Value *SizeArgument,
bool UseCalls,
1840 RuntimeCallInserter &RTCI) {
1841 if (TargetTriple.isAMDGPU()) {
1842 InsertBefore = instrumentAMDGPUAddress(OrigIns, InsertBefore,
Addr,
1843 TypeStoreSize, IsWrite, SizeArgument);
1850 const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
1853 const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
1858 ConstantInt::get(Int32Ty, AccessInfo.Packed)});
1865 RTCI.createRuntimeCall(
1866 IRB, AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex], AddrLong);
1868 RTCI.createRuntimeCall(
1869 IRB, AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex],
1870 {AddrLong, ConstantInt::get(IRB.
getInt32Ty(), Exp)});
1877 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1879 std::max<uint64_t>(Alignment.
valueOrOne().
value() >> Mapping.Scale, 1);
1884 size_t Granularity = 1ULL << Mapping.Scale;
1887 bool GenSlowPath = (
ClAlwaysSlowPath || (TypeStoreSize < 8 * Granularity));
1889 if (TargetTriple.isAMDGCN()) {
1891 auto *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
1894 CrashTerm = genAMDGPUReportBlock(IRB, Cmp, Recover);
1895 }
else if (GenSlowPath) {
1900 assert(cast<BranchInst>(CheckTerm)->isUnconditional());
1903 Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
1918 CrashTerm, AddrLong, IsWrite, AccessSizeIndex, SizeArgument, Exp, RTCI);
1927void AddressSanitizer::instrumentUnusualSizeOrAlignment(
1929 TypeSize TypeStoreSize,
bool IsWrite,
Value *SizeArgument,
bool UseCalls,
1930 uint32_t Exp, RuntimeCallInserter &RTCI) {
1938 RTCI.createRuntimeCall(IRB, AsanMemoryAccessCallbackSized[IsWrite][0],
1941 RTCI.createRuntimeCall(
1942 IRB, AsanMemoryAccessCallbackSized[IsWrite][1],
1949 instrumentAddress(
I, InsertBefore,
Addr, {}, 8, IsWrite,
Size,
false,
Exp,
1951 instrumentAddress(
I, InsertBefore, LastByte, {}, 8, IsWrite,
Size,
false,
1956void ModuleAddressSanitizer::poisonOneInitializer(
Function &GlobalInit,
1964 IRB.
CreateCall(AsanPoisonGlobals, ModuleNameAddr);
1967 for (
auto &BB : GlobalInit)
1972void ModuleAddressSanitizer::createInitializerPoisonCalls(
1983 if (isa<ConstantAggregateZero>(
OP))
continue;
1989 auto *Priority = cast<ConstantInt>(CS->
getOperand(0));
1999ModuleAddressSanitizer::getExcludedAliasedGlobal(
const GlobalAlias &GA)
const {
2004 assert(CompileKernel &&
"Only expecting to be called when compiling kernel");
2011 return dyn_cast<GlobalVariable>(
C->stripPointerCastsAndAliases());
2016bool ModuleAddressSanitizer::shouldInstrumentGlobal(
GlobalVariable *
G)
const {
2017 Type *Ty =
G->getValueType();
2020 if (
G->hasSanitizerMetadata() &&
G->getSanitizerMetadata().NoAddress)
2022 if (!Ty->
isSized())
return false;
2023 if (!
G->hasInitializer())
return false;
2025 if (
G->getAddressSpace() &&
2032 if (
G->isThreadLocal())
return false;
2034 if (
G->getAlign() && *
G->getAlign() > getMinRedzoneSizeForGlobal())
return false;
2040 if (!TargetTriple.isOSBinFormatCOFF()) {
2041 if (!
G->hasExactDefinition() ||
G->hasComdat())
2045 if (
G->isInterposable())
2049 if (
G->hasAvailableExternallyLinkage())
2056 switch (
C->getSelectionKind()) {
2067 if (
G->hasSection()) {
2077 if (Section ==
"llvm.metadata")
return false;
2084 if (
Section.starts_with(
".preinit_array") ||
2085 Section.starts_with(
".init_array") ||
2086 Section.starts_with(
".fini_array")) {
2092 if (TargetTriple.isOSBinFormatELF()) {
2094 [](
char c) {
return llvm::isAlnum(c) || c ==
'_'; }))
2106 if (TargetTriple.isOSBinFormatCOFF() &&
Section.contains(
'$')) {
2107 LLVM_DEBUG(
dbgs() <<
"Ignoring global in sorted section (contains '$'): "
2112 if (TargetTriple.isOSBinFormatMachO()) {
2114 unsigned TAA = 0, StubSize = 0;
2117 Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize));
2122 if (ParsedSegment ==
"__OBJC" ||
2123 (ParsedSegment ==
"__DATA" && ParsedSection.
starts_with(
"__objc_"))) {
2135 if (ParsedSegment ==
"__DATA" && ParsedSection ==
"__cfstring") {
2148 if (CompileKernel) {
2151 if (
G->getName().starts_with(
"__"))
2161bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection()
const {
2162 if (!TargetTriple.isOSBinFormatMachO())
2165 if (TargetTriple.isMacOSX() && !TargetTriple.isMacOSXVersionLT(10, 11))
2167 if (TargetTriple.isiOS() && !TargetTriple.isOSVersionLT(9))
2169 if (TargetTriple.isWatchOS() && !TargetTriple.isOSVersionLT(2))
2171 if (TargetTriple.isDriverKit())
2173 if (TargetTriple.isXROS())
2179StringRef ModuleAddressSanitizer::getGlobalMetadataSection()
const {
2180 switch (TargetTriple.getObjectFormat()) {
2190 "ModuleAddressSanitizer not implemented for object file format");
2197void ModuleAddressSanitizer::initializeCallbacks(
Module &M) {
2203 AsanUnpoisonGlobals =
2207 AsanRegisterGlobals =
M.getOrInsertFunction(
2209 AsanUnregisterGlobals =
M.getOrInsertFunction(
2214 AsanRegisterImageGlobals =
M.getOrInsertFunction(
2216 AsanUnregisterImageGlobals =
M.getOrInsertFunction(
2219 AsanRegisterElfGlobals =
2221 IntptrTy, IntptrTy, IntptrTy);
2222 AsanUnregisterElfGlobals =
2224 IntptrTy, IntptrTy, IntptrTy);
2229void ModuleAddressSanitizer::SetComdatForGlobalMetadata(
2234 if (!
G->hasName()) {
2241 if (!InternalSuffix.
empty() &&
G->hasLocalLinkage()) {
2242 std::string
Name = std::string(
G->getName());
2243 Name += InternalSuffix;
2244 C =
M.getOrInsertComdat(
Name);
2246 C =
M.getOrInsertComdat(
G->getName());
2252 if (TargetTriple.isOSBinFormatCOFF()) {
2254 if (
G->hasPrivateLinkage())
2267ModuleAddressSanitizer::CreateMetadataGlobal(
Module &M,
Constant *Initializer,
2269 auto Linkage = TargetTriple.isOSBinFormatMachO()
2273 M, Initializer->
getType(),
false, Linkage, Initializer,
2275 Metadata->setSection(getGlobalMetadataSection());
2286 AsanDtorFunction->addFnAttr(Attribute::NoUnwind);
2294void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
2298 auto &
DL =
M.getDataLayout();
2301 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2302 Constant *Initializer = MetadataInitializers[i];
2305 CreateMetadataGlobal(M, Initializer,
G->getName());
2307 Metadata->setMetadata(LLVMContext::MD_associated, MD);
2313 unsigned SizeOfGlobalStruct =
DL.getTypeAllocSize(Initializer->
getType());
2315 "global metadata will not be padded appropriately");
2318 SetComdatForGlobalMetadata(
G,
Metadata,
"");
2323 if (!MetadataGlobals.empty())
2327void ModuleAddressSanitizer::instrumentGlobalsELF(
2330 const std::string &UniqueModuleId) {
2337 bool UseComdatForGlobalsGC = UseOdrIndicator && !UniqueModuleId.empty();
2340 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2343 CreateMetadataGlobal(M, MetadataInitializers[i],
G->getName());
2345 Metadata->setMetadata(LLVMContext::MD_associated, MD);
2348 if (UseComdatForGlobalsGC)
2349 SetComdatForGlobalMetadata(
G,
Metadata, UniqueModuleId);
2354 if (!MetadataGlobals.empty())
2371 "__start_" + getGlobalMetadataSection());
2375 "__stop_" + getGlobalMetadataSection());
2389 IrbDtor.CreateCall(AsanUnregisterElfGlobals,
2396void ModuleAddressSanitizer::InstrumentGlobalsMachO(
2407 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2408 Constant *Initializer = MetadataInitializers[i];
2411 CreateMetadataGlobal(M, Initializer,
G->getName());
2415 auto LivenessBinder =
2420 Twine(
"__asan_binder_") +
G->getName());
2421 Liveness->
setSection(
"__DATA,__asan_liveness,regular,live_support");
2422 LivenessGlobals[i] = Liveness;
2429 if (!LivenessGlobals.empty())
2451 IrbDtor.CreateCall(AsanUnregisterImageGlobals,
2456void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
2460 unsigned N = ExtendedGlobals.
size();
2470 if (Mapping.Scale > 3)
2471 AllGlobals->setAlignment(
Align(1ULL << Mapping.Scale));
2476 ConstantInt::get(IntptrTy,
N)});
2482 IrbDtor.CreateCall(AsanUnregisterGlobals,
2484 ConstantInt::get(IntptrTy,
N)});
2498 if (CompileKernel) {
2499 for (
auto &GA :
M.aliases()) {
2501 AliasedGlobalExclusions.
insert(GV);
2506 for (
auto &
G :
M.globals()) {
2507 if (!AliasedGlobalExclusions.
count(&
G) && shouldInstrumentGlobal(&
G))
2511 size_t n = GlobalsToChange.
size();
2512 auto &
DL =
M.getDataLayout();
2526 IntptrTy, IntptrTy, IntptrTy);
2530 bool HasDynamicallyInitializedGlobals =
false;
2540 for (
size_t i = 0; i < n; i++) {
2544 if (
G->hasSanitizerMetadata())
2545 MD =
G->getSanitizerMetadata();
2550 std::string NameForGlobal =
G->getName().str();
2555 Type *Ty =
G->getValueType();
2556 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
2557 const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes);
2569 M, NewTy,
G->isConstant(), Linkage, NewInitializer,
"",
G,
2570 G->getThreadLocalMode(),
G->getAddressSpace());
2580 if (TargetTriple.isOSBinFormatMachO() && !
G->hasSection() &&
2582 auto Seq = dyn_cast<ConstantDataSequential>(
G->getInitializer());
2583 if (Seq && Seq->isCString())
2584 NewGlobal->
setSection(
"__TEXT,__asan_cstring,regular");
2595 G->replaceAllUsesWith(
2598 G->eraseFromParent();
2599 NewGlobals[i] = NewGlobal;
2604 bool CanUsePrivateAliases =
2605 TargetTriple.isOSBinFormatELF() || TargetTriple.isOSBinFormatMachO() ||
2606 TargetTriple.isOSBinFormatWasm();
2607 if (CanUsePrivateAliases && UsePrivateAlias) {
2610 InstrumentedGlobal =
2618 }
else if (UseOdrIndicator) {
2621 auto *ODRIndicatorSym =
2630 ODRIndicatorSym->setAlignment(
Align(1));
2631 ODRIndicator = ODRIndicatorSym;
2637 ConstantInt::get(IntptrTy, SizeInBytes),
2638 ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
2641 ConstantInt::get(IntptrTy, MD.
IsDynInit),
2646 HasDynamicallyInitializedGlobals =
true;
2650 Initializers[i] = Initializer;
2656 for (
size_t i = 0; i < n; i++) {
2658 if (
G->getName().empty())
continue;
2663 if (UseGlobalsGC && TargetTriple.isOSBinFormatELF()) {
2669 instrumentGlobalsELF(IRB, M, NewGlobals, Initializers,
2671 }
else if (n == 0) {
2674 *CtorComdat = TargetTriple.isOSBinFormatELF();
2676 *CtorComdat =
false;
2677 if (UseGlobalsGC && TargetTriple.isOSBinFormatCOFF()) {
2678 InstrumentGlobalsCOFF(IRB, M, NewGlobals, Initializers);
2679 }
else if (UseGlobalsGC && ShouldUseMachOGlobalsSection()) {
2680 InstrumentGlobalsMachO(IRB, M, NewGlobals, Initializers);
2682 InstrumentGlobalsWithMetadataArray(IRB, M, NewGlobals, Initializers);
2687 if (HasDynamicallyInitializedGlobals)
2694ModuleAddressSanitizer::getRedzoneSizeForGlobal(
uint64_t SizeInBytes)
const {
2695 constexpr uint64_t kMaxRZ = 1 << 18;
2696 const uint64_t MinRZ = getMinRedzoneSizeForGlobal();
2699 if (SizeInBytes <= MinRZ / 2) {
2703 RZ = MinRZ - SizeInBytes;
2706 RZ = std::clamp((SizeInBytes / MinRZ / 4) * MinRZ, MinRZ, kMaxRZ);
2709 if (SizeInBytes % MinRZ)
2710 RZ += MinRZ - (SizeInBytes % MinRZ);
2713 assert((RZ + SizeInBytes) % MinRZ == 0);
2718int ModuleAddressSanitizer::GetAsanVersion(
const Module &M)
const {
2719 int LongSize =
M.getDataLayout().getPointerSizeInBits();
2724 Version += (LongSize == 32 && isAndroid);
2728bool ModuleAddressSanitizer::instrumentModule(
Module &M) {
2729 initializeCallbacks(M);
2734 if (CompileKernel) {
2739 std::string AsanVersion = std::to_string(GetAsanVersion(M));
2740 std::string VersionCheckName =
2742 std::tie(AsanCtorFunction, std::ignore) =
2745 {}, VersionCheckName);
2749 bool CtorComdat =
true;
2752 if (AsanCtorFunction) {
2753 IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2754 instrumentGlobals(IRB, M, &CtorComdat);
2757 instrumentGlobals(IRB, M, &CtorComdat);
2766 if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
2767 if (AsanCtorFunction) {
2771 if (AsanDtorFunction) {
2776 if (AsanCtorFunction)
2778 if (AsanDtorFunction)
2789 for (
int Exp = 0;
Exp < 2;
Exp++) {
2790 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
2791 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
2792 const std::string ExpStr =
Exp ?
"exp_" :
"";
2793 const std::string EndingStr = Recover ?
"_noabort" :
"";
2802 Args1.push_back(ExpType);
2803 if (
auto AK = TLI->getExtAttrForI32Param(
false)) {
2808 AsanErrorCallbackSized[AccessIsWrite][
Exp] =
M.getOrInsertFunction(
2812 AsanMemoryAccessCallbackSized[AccessIsWrite][
Exp] =
M.getOrInsertFunction(
2817 AccessSizeIndex++) {
2818 const std::string Suffix = TypeStr + itostr(1ULL << AccessSizeIndex);
2819 AsanErrorCallback[AccessIsWrite][
Exp][AccessSizeIndex] =
2820 M.getOrInsertFunction(
2824 AsanMemoryAccessCallback[AccessIsWrite][
Exp][AccessSizeIndex] =
2825 M.getOrInsertFunction(
2832 const std::string MemIntrinCallbackPrefix =
2836 AsanMemmove =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memmove",
2837 PtrTy, PtrTy, PtrTy, IntptrTy);
2838 AsanMemcpy =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memcpy", PtrTy,
2839 PtrTy, PtrTy, IntptrTy);
2840 AsanMemset =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memset",
2844 AsanHandleNoReturnFunc =
2847 AsanPtrCmpFunction =
2849 AsanPtrSubFunction =
2851 if (Mapping.InGlobal)
2852 AsanShadowGlobal =
M.getOrInsertGlobal(
"__asan_shadow",
2855 AMDGPUAddressShared =
2857 AMDGPUAddressPrivate =
2861bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(
Function &
F) {
2869 if (
F.getName().contains(
" load]")) {
2879bool AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(
Function &
F) {
2885 if (Mapping.InGlobal) {
2893 LocalDynamicShadow =
2894 IRB.
CreateCall(Asm, {AsanShadowGlobal},
".asan.shadow");
2896 LocalDynamicShadow =
2900 Value *GlobalDynamicAddress =
F.getParent()->getOrInsertGlobal(
2902 LocalDynamicShadow = IRB.
CreateLoad(IntptrTy, GlobalDynamicAddress);
2907void AddressSanitizer::markEscapedLocalAllocas(
Function &
F) {
2912 assert(ProcessedAllocas.empty() &&
"must process localescape before allocas");
2916 if (!
F.getParent()->getFunction(
"llvm.localescape"))
return;
2922 if (
II &&
II->getIntrinsicID() == Intrinsic::localescape) {
2924 for (
Value *Arg :
II->args()) {
2925 AllocaInst *AI = dyn_cast<AllocaInst>(Arg->stripPointerCasts());
2927 "non-static alloca arg to localescape");
2928 ProcessedAllocas[AI] =
false;
2935bool AddressSanitizer::suppressInstrumentationSiteForDebug(
int &Instrumented) {
2936 bool ShouldInstrument =
2940 return !ShouldInstrument;
2943bool AddressSanitizer::instrumentFunction(
Function &
F,
2949 if (
F.getName().starts_with(
"__asan_"))
return false;
2951 bool FunctionModified =
false;
2956 if (maybeInsertAsanInitAtFunctionEntry(
F))
2957 FunctionModified =
true;
2960 if (!
F.hasFnAttribute(Attribute::SanitizeAddress))
return FunctionModified;
2962 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
2963 return FunctionModified;
2967 initializeCallbacks(*
F.getParent(), TLI);
2969 FunctionStateRAII CleanupObj(
this);
2971 RuntimeCallInserter RTCI(
F);
2973 FunctionModified |= maybeInsertDynamicShadowAtFunctionEntry(
F);
2977 markEscapedLocalAllocas(
F);
2989 for (
auto &BB :
F) {
2991 TempsToInstrument.
clear();
2992 int NumInsnsPerBB = 0;
2993 for (
auto &Inst : BB) {
2994 if (LooksLikeCodeInBug11395(&Inst))
return false;
2999 getInterestingMemoryOperands(&Inst, InterestingOperands);
3001 if (!InterestingOperands.
empty()) {
3002 for (
auto &Operand : InterestingOperands) {
3008 if (Operand.MaybeMask) {
3012 if (!TempsToInstrument.
insert(
Ptr).second)
3016 OperandsToInstrument.
push_back(Operand);
3023 PointerComparisonsOrSubtracts.
push_back(&Inst);
3029 if (
auto *CB = dyn_cast<CallBase>(&Inst)) {
3031 TempsToInstrument.
clear();
3035 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
3042 bool UseCalls = (InstrumentationWithCallsThreshold >= 0 &&
3043 OperandsToInstrument.
size() + IntrinToInstrument.
size() >
3044 (
unsigned)InstrumentationWithCallsThreshold);
3051 int NumInstrumented = 0;
3052 for (
auto &Operand : OperandsToInstrument) {
3053 if (!suppressInstrumentationSiteForDebug(NumInstrumented))
3054 instrumentMop(ObjSizeVis, Operand, UseCalls,
3055 F.getDataLayout(), RTCI);
3056 FunctionModified =
true;
3058 for (
auto *Inst : IntrinToInstrument) {
3059 if (!suppressInstrumentationSiteForDebug(NumInstrumented))
3060 instrumentMemIntrinsic(Inst, RTCI);
3061 FunctionModified =
true;
3064 FunctionStackPoisoner FSP(
F, *
this, RTCI);
3065 bool ChangedStack = FSP.runOnFunction();
3069 for (
auto *CI : NoReturnCalls) {
3071 RTCI.createRuntimeCall(IRB, AsanHandleNoReturnFunc, {});
3074 for (
auto *Inst : PointerComparisonsOrSubtracts) {
3075 instrumentPointerComparisonOrSubtraction(Inst, RTCI);
3076 FunctionModified =
true;
3079 if (ChangedStack || !NoReturnCalls.empty())
3080 FunctionModified =
true;
3082 LLVM_DEBUG(
dbgs() <<
"ASAN done instrumenting: " << FunctionModified <<
" "
3085 return FunctionModified;
3091bool AddressSanitizer::LooksLikeCodeInBug11395(
Instruction *
I) {
3092 if (LongSize != 32)
return false;
3101void FunctionStackPoisoner::initializeCallbacks(
Module &M) {
3105 const char *MallocNameTemplate =
3110 std::string Suffix = itostr(
Index);
3111 AsanStackMallocFunc[
Index] =
M.getOrInsertFunction(
3112 MallocNameTemplate + Suffix, IntptrTy, IntptrTy);
3113 AsanStackFreeFunc[
Index] =
3118 if (ASan.UseAfterScope) {
3119 AsanPoisonStackMemoryFunc =
M.getOrInsertFunction(
3121 AsanUnpoisonStackMemoryFunc =
M.getOrInsertFunction(
3125 for (
size_t Val : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf1, 0xf2,
3126 0xf3, 0xf5, 0xf8}) {
3127 std::ostringstream
Name;
3129 Name << std::setw(2) << std::setfill(
'0') << std::hex << Val;
3130 AsanSetShadowFunc[Val] =
3131 M.getOrInsertFunction(
Name.str(), IRB.
getVoidTy(), IntptrTy, IntptrTy);
3134 AsanAllocaPoisonFunc =
M.getOrInsertFunction(
3136 AsanAllocasUnpoisonFunc =
M.getOrInsertFunction(
3142 size_t Begin,
size_t End,
3144 Value *ShadowBase) {
3148 const size_t LargestStoreSizeInBytes =
3149 std::min<size_t>(
sizeof(
uint64_t), ASan.LongSize / 8);
3151 const bool IsLittleEndian =
F.getDataLayout().isLittleEndian();
3157 for (
size_t i = Begin; i <
End;) {
3158 if (!ShadowMask[i]) {
3164 size_t StoreSizeInBytes = LargestStoreSizeInBytes;
3166 while (StoreSizeInBytes >
End - i)
3167 StoreSizeInBytes /= 2;
3170 for (
size_t j = StoreSizeInBytes - 1;
j && !ShadowMask[i +
j]; --
j) {
3171 while (j <= StoreSizeInBytes / 2)
3172 StoreSizeInBytes /= 2;
3176 for (
size_t j = 0;
j < StoreSizeInBytes;
j++) {
3178 Val |= (
uint64_t)ShadowBytes[i + j] << (8 * j);
3180 Val = (Val << 8) | ShadowBytes[i + j];
3184 Value *Poison = IRB.
getIntN(StoreSizeInBytes * 8, Val);
3189 i += StoreSizeInBytes;
3196 copyToShadow(ShadowMask, ShadowBytes, 0, ShadowMask.
size(), IRB, ShadowBase);
3201 size_t Begin,
size_t End,
3204 size_t Done = Begin;
3205 for (
size_t i = Begin, j = Begin + 1; i <
End; i =
j++) {
3206 if (!ShadowMask[i]) {
3210 uint8_t Val = ShadowBytes[i];
3211 if (!AsanSetShadowFunc[Val])
3215 for (;
j <
End && ShadowMask[
j] && Val == ShadowBytes[
j]; ++
j) {
3218 if (j - i >= ASan.MaxInlinePoisoningSize) {
3219 copyToShadowInline(ShadowMask, ShadowBytes,
Done, i, IRB, ShadowBase);
3220 RTCI.createRuntimeCall(
3221 IRB, AsanSetShadowFunc[Val],
3222 {IRB.
CreateAdd(ShadowBase, ConstantInt::get(IntptrTy, i)),
3223 ConstantInt::get(IntptrTy, j - i)});
3228 copyToShadowInline(ShadowMask, ShadowBytes,
Done,
End, IRB, ShadowBase);
3236 for (
int i = 0;; i++, MaxSize *= 2)
3237 if (LocalStackSize <= MaxSize)
return i;
3241void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {
3243 if (CopyInsertPoint == ASan.LocalDynamicShadow) {
3251 if (Arg.hasByValAttr()) {
3252 Type *Ty = Arg.getParamByValType();
3253 const Align Alignment =
3254 DL.getValueOrABITypeAlignment(Arg.getParamAlign(), Ty);
3258 (Arg.hasName() ? Arg.getName() :
"Arg" +
Twine(Arg.getArgNo())) +
3261 Arg.replaceAllUsesWith(AI);
3263 uint64_t AllocSize =
DL.getTypeAllocSize(Ty);
3264 IRB.
CreateMemCpy(AI, Alignment, &Arg, Alignment, AllocSize);
3272 Value *ValueIfFalse) {
3275 PHI->addIncoming(ValueIfFalse, CondBlock);
3277 PHI->addIncoming(ValueIfTrue, ThenBlock);
3281Value *FunctionStackPoisoner::createAllocaForLayout(
3290 nullptr,
"MyAlloca");
3299void FunctionStackPoisoner::createDynamicAllocasInitStorage() {
3302 DynamicAllocaLayout = IRB.
CreateAlloca(IntptrTy,
nullptr);
3307void FunctionStackPoisoner::processDynamicAllocas() {
3314 for (
const auto &APC : DynamicAllocaPoisonCallVec) {
3317 assert(ASan.isInterestingAlloca(*APC.AI));
3318 assert(!APC.AI->isStaticAlloca());
3321 poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
3328 createDynamicAllocasInitStorage();
3329 for (
auto &AI : DynamicAllocaVec)
3330 handleDynamicAllocaCall(AI);
3331 unpoisonDynamicAllocas();
3343 for (
Instruction *It = Start; It; It = It->getNextNonDebugInstruction()) {
3353 if (isa<AllocaInst>(It) || isa<CastInst>(It))
3355 if (
auto *Store = dyn_cast<StoreInst>(It)) {
3359 auto *Alloca = dyn_cast<AllocaInst>(Store->getPointerOperand());
3360 if (!Alloca || ASan.isInterestingAlloca(*Alloca))
3363 Value *Val = Store->getValueOperand();
3364 bool IsDirectArgInit = isa<Argument>(Val);
3365 bool IsArgInitViaCast =
3366 isa<CastInst>(Val) &&
3367 isa<Argument>(cast<CastInst>(Val)->getOperand(0)) &&
3370 Val == It->getPrevNonDebugInstruction();
3371 bool IsArgInit = IsDirectArgInit || IsArgInitViaCast;
3375 if (IsArgInitViaCast)
3376 InitInsts.
push_back(cast<Instruction>(Val));
3387void FunctionStackPoisoner::processStaticAllocas() {
3388 if (AllocaVec.
empty()) {
3393 int StackMallocIdx = -1;
3395 if (
auto SP =
F.getSubprogram())
3396 EntryDebugLocation =
3405 auto InsBeforeB = InsBefore->
getParent();
3406 assert(InsBeforeB == &
F.getEntryBlock());
3407 for (
auto *AI : StaticAllocasToMoveUp)
3418 ArgInitInst->moveBefore(InsBefore);
3421 if (LocalEscapeCall) LocalEscapeCall->
moveBefore(InsBefore);
3427 ASan.getAllocaSizeInBytes(*AI),
3438 uint64_t Granularity = 1ULL << Mapping.Scale;
3439 uint64_t MinHeaderSize = std::max((
uint64_t)ASan.LongSize / 2, Granularity);
3445 for (
auto &
Desc : SVD)
3449 for (
const auto &APC : StaticAllocaPoisonCallVec) {
3452 assert(ASan.isInterestingAlloca(*APC.AI));
3453 assert(APC.AI->isStaticAlloca());
3458 if (
const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) {
3459 if (LifetimeLoc->getFile() == FnLoc->getFile())
3460 if (
unsigned Line = LifetimeLoc->getLine())
3461 Desc.Line = std::min(
Desc.Line ?
Desc.Line : Line, Line);
3467 LLVM_DEBUG(
dbgs() << DescriptionString <<
" --- " <<
L.FrameSize <<
"\n");
3469 bool DoStackMalloc =
3479 DoDynamicAlloca &= !HasInlineAsm && !HasReturnsTwiceCall;
3480 DoStackMalloc &= !HasInlineAsm && !HasReturnsTwiceCall;
3482 Value *StaticAlloca =
3483 DoDynamicAlloca ? nullptr : createAllocaForLayout(IRB, L,
false);
3486 Value *LocalStackBase;
3487 Value *LocalStackBaseAlloca;
3490 if (DoStackMalloc) {
3491 LocalStackBaseAlloca =
3492 IRB.
CreateAlloca(IntptrTy,
nullptr,
"asan_local_stack_base");
3499 Constant *OptionDetectUseAfterReturn =
F.getParent()->getOrInsertGlobal(
3509 Value *FakeStackValue =
3510 RTCI.createRuntimeCall(IRBIf, AsanStackMallocFunc[StackMallocIdx],
3511 ConstantInt::get(IntptrTy, LocalStackSize));
3513 FakeStack = createPHI(IRB, UseAfterReturnIsEnabled, FakeStackValue, Term,
3514 ConstantInt::get(IntptrTy, 0));
3522 RTCI.createRuntimeCall(IRB, AsanStackMallocFunc[StackMallocIdx],
3523 ConstantInt::get(IntptrTy, LocalStackSize));
3525 Value *NoFakeStack =
3530 Value *AllocaValue =
3531 DoDynamicAlloca ? createAllocaForLayout(IRBIf, L,
true) : StaticAlloca;
3534 LocalStackBase = createPHI(IRB, NoFakeStack, AllocaValue, Term, FakeStack);
3535 IRB.
CreateStore(LocalStackBase, LocalStackBaseAlloca);
3540 FakeStack = ConstantInt::get(IntptrTy, 0);
3542 DoDynamicAlloca ? createAllocaForLayout(IRB, L,
true) : StaticAlloca;
3543 LocalStackBaseAlloca = LocalStackBase;
3549 Value *LocalStackBaseAllocaPtr =
3550 isa<PtrToIntInst>(LocalStackBaseAlloca)
3551 ? cast<PtrToIntInst>(LocalStackBaseAlloca)->getPointerOperand()
3552 : LocalStackBaseAlloca;
3553 assert(isa<AllocaInst>(LocalStackBaseAllocaPtr) &&
3554 "Variable descriptions relative to ASan stack base will be dropped");
3557 for (
const auto &
Desc : SVD) {
3562 IRB.
CreateAdd(LocalStackBase, ConstantInt::get(IntptrTy,
Desc.Offset)),
3575 ConstantInt::get(IntptrTy, ASan.LongSize / 8)),
3585 ConstantInt::get(IntptrTy, 2 * ASan.LongSize / 8)),
3592 Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB);
3595 copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase);
3597 if (!StaticAllocaPoisonCallVec.empty()) {
3601 for (
const auto &APC : StaticAllocaPoisonCallVec) {
3604 size_t Begin =
Desc.Offset /
L.Granularity;
3605 size_t End = Begin + (APC.Size +
L.Granularity - 1) /
L.Granularity;
3608 copyToShadow(ShadowAfterScope,
3609 APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin,
End,
3623 if (DoStackMalloc) {
3624 assert(StackMallocIdx >= 0);
3641 if (ASan.MaxInlinePoisoningSize != 0 && StackMallocIdx <= 4) {
3643 ShadowAfterReturn.
resize(ClassSize /
L.Granularity,
3645 copyToShadow(ShadowAfterReturn, ShadowAfterReturn, IRBPoison,
3647 Value *SavedFlagPtrPtr = IRBPoison.CreateAdd(
3649 ConstantInt::get(IntptrTy, ClassSize - ASan.LongSize / 8));
3650 Value *SavedFlagPtr = IRBPoison.CreateLoad(
3651 IntptrTy, IRBPoison.CreateIntToPtr(SavedFlagPtrPtr, IntptrPtrTy));
3652 IRBPoison.CreateStore(
3654 IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getPtrTy()));
3657 RTCI.createRuntimeCall(
3658 IRBPoison, AsanStackFreeFunc[StackMallocIdx],
3659 {FakeStack, ConstantInt::get(IntptrTy, LocalStackSize)});
3663 copyToShadow(ShadowAfterScope, ShadowClean, IRBElse, ShadowBase);
3665 copyToShadow(ShadowAfterScope, ShadowClean, IRBRet, ShadowBase);
3670 for (
auto *AI : AllocaVec)
3678 Value *SizeArg = ConstantInt::get(IntptrTy,
Size);
3679 RTCI.createRuntimeCall(
3680 IRB, DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc,
3681 {AddrArg, SizeArg});
3692void FunctionStackPoisoner::handleDynamicAllocaCall(
AllocaInst *AI) {
3700 Value *AllocaRzMask = ConstantInt::get(IntptrTy, AllocaRedzoneMask);
3706 const unsigned ElementSize =
3710 ConstantInt::get(IntptrTy, ElementSize));
3738 ConstantInt::get(IntptrTy, Alignment.
value()));
3741 RTCI.createRuntimeCall(IRB, AsanAllocaPoisonFunc, {NewAddress, OldSize});
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< bool > ClUseStackSafety("stack-tagging-use-stack-safety", cl::Hidden, cl::init(true), cl::desc("Use Stack Safety analysis results"))
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 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
static const uint64_t kEmscriptenShadowOffset
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 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< 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 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 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 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 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))
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< 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.
uint64_t IntrinsicInst * II
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet 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)
This defines the Use class.
uint64_t getZExtValue() const
Get zero extended value.
int64_t getSExtValue() const
Get sign extended value.
AddressSanitizerPass(const AddressSanitizerOptions &Options, bool UseGlobalGC=true, bool UseOdrIndicator=true, AsanDtorKind DestructorKind=AsanDtorKind::Global, AsanCtorKind ConstructorKind=AsanCtorKind::Global)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
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.
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.
std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
void setAlignment(Align Align)
const Value * getArraySize() const
Get the number of elements allocated.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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.
static 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,...
AttributeList addParamAttribute(LLVMContext &C, unsigned ArgNo, Attribute::AttrKind Kind) const
Add an argument attribute to the list.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
const Function * getParent() const
Return the enclosing method, or null if none.
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...
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)
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool isInlineAsm() const
Check if this call is an inline asm statement.
static 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 Constant * get(ArrayType *T, ArrayRef< Constant * > V)
static Constant * getIntToPtr(Constant *C, Type *Ty, bool OnlyIfReduced=false)
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast, AddrSpaceCast, or a PtrToInt cast constant expression.
static Constant * getGetElementPtr(Type *Ty, Constant *C, ArrayRef< Constant * > IdxList, GEPNoWrapFlags NW=GEPNoWrapFlags::none(), std::optional< ConstantRange > InRange=std::nullopt, Type *OnlyIfReducedTy=nullptr)
Getelementptr form.
static 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 ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
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 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.
Constant * getPersonalityFn() const
Get the personality function associated with this function.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
const Constant * getAliasee() const
static 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...
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalObject.
void copyMetadata(const GlobalObject *Src, unsigned Offset)
Copy metadata from Src, adjusting offsets by Offset.
void setComdat(Comdat *C)
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
Module * getParent()
Get the module that this global value is contained inside of...
@ 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.
void copyAttributesFrom(const GlobalVariable *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a GlobalVariable) fro...
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.
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
LoadInst * CreateAlignedLoad(Type *Ty, Value *Ptr, MaybeAlign Align, const char *Name)
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Value * CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name="")
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 * CreateTypeSize(Type *DstType, TypeSize Size)
Create an expression which evaluates to the number of units in Size at runtime.
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())
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
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 or truncated 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.
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block.
Type * getVoidTy()
Fetch the type representing void.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, MaybeAlign Align, bool isVolatile=false)
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value * > Args=std::nullopt, const Twine &Name="", MDNode *FPMathTag=nullptr)
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
CallInst * CreateMemCpy(Value *Dst, MaybeAlign DstAlign, Value *Src, MaybeAlign SrcAlign, uint64_t Size, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *TBAAStructTag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memcpy between the specified pointers.
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 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.
An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...
Base class for instruction visitors.
RetTy visitCallBase(CallBase &I)
RetTy visitCleanupReturnInst(CleanupReturnInst &I)
RetTy visitIntrinsicInst(IntrinsicInst &I)
void visit(Iterator Start, Iterator End)
RetTy visitReturnInst(ReturnInst &I)
RetTy visitAllocaInst(AllocaInst &I)
RetTy visitResumeInst(ResumeInst &I)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
bool isEHPad() const
Return true if the instruction is a variety of EH-block.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
const Instruction * getNextNonDebugInstruction(bool SkipPseudoOp=false) const
Return a pointer to the next non-debug instruction in the same basic block as 'this',...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
void moveBefore(Instruction *MovePos)
Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...
static 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.
This is an important class for using LLVM in a threaded context.
void emitError(uint64_t LocCookie, 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".
MDNode * createUnlikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards false destination.
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.
SizeOffsetAPInt compute(Value *V)
A container for an operand bundle being viewed as a set of values rather than a set of uses.
Pass interface - Implemented by all 'passes'.
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
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.
void abandon()
Mark an analysis as abandoned.
Resume the propagation of an exception.
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.
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.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
AttributeList getAttrList(LLVMContext *C, ArrayRef< unsigned > ArgNos, bool Signed, bool Ret=false, AttributeList AL=AttributeList()) const
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
Triple - Helper class for working with autoconf configuration names.
bool isAndroidVersionLT(unsigned Major) const
bool isThumb() const
Tests whether the target is Thumb (little and big endian).
bool isDriverKit() const
Is this an Apple DriverKit triple.
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.
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
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.
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.
unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Type * getVoidTy(LLVMContext &C)
bool isSized(SmallPtrSetImpl< Type * > *Visited=nullptr) const
Return true if it makes sense to take the size of this type.
static IntegerType * getInt32Ty(LLVMContext &C)
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.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
static 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.
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.
@ C
The default llvm calling convention, compatible with C.
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
@ 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)
Linkage
Describes symbol linkage. This can be used to resolve definition clashes.
uint64_t getAllocaSizeInBytes(const AllocaInst &AI)
This is an optimization pass for GlobalISel generic memory operations.
void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)
Replace the instruction specified by BI with the instruction specified by I.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
SmallVector< uint8_t, 64 > GetShadowBytesAfterScope(const SmallVectorImpl< ASanStackVariableDescription > &Vars, const ASanStackFrameLayout &Layout)
AllocaInst * findAllocaForValue(Value *V, bool OffsetZero=false)
Returns unique alloca where the value comes from, or nullptr.
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...
GlobalVariable * createPrivateGlobalForString(Module &M, StringRef Str, bool AllowMerging, const char *NamePrefix="")
DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
SmallString< 64 > ComputeASanStackFrameDescription(const SmallVectorImpl< ASanStackVariableDescription > &Vars)
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.
FunctionCallee declareSanitizerInitFunction(Module &M, StringRef InitName, ArrayRef< Type * > InitArgTypes, bool Weak=false)
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.
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)
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...
void SplitBlockAndInsertForEachLane(ElementCount EC, Type *IndexTy, Instruction *InsertBefore, std::function< void(IRBuilderBase &, Value *)> Func)
Utility function for performing a given action on each lane of a vector with EC elements.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
AsanDtorKind
Types of ASan module destructors supported.
@ None
Do not emit any destructors for ASan.
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.
void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
static const int kAsanStackUseAfterReturnMagic
void setGlobalVariableLargeSection(const Triple &TargetTriple, GlobalVariable &GV)
@ Dynamic
Denotes mode unknown at compile time.
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.
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)
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 ...
AsanCtorKind
Types of ASan module constructors supported.
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...
void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
void appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data=nullptr)
Same as appendToGlobalCtors(), but for global dtors.
void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize, bool IsKasan, uint64_t *ShadowBase, int *MappingScale, bool *OrShadowOffset)
std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
bool replaceDbgDeclare(Value *Address, Value *NewAddress, DIBuilder &Builder, uint8_t DIExprFlags, int Offset)
Replaces llvm.dbg.declare instruction when the address it describes is replaced with a new value.
ASanAccessInfo(int32_t Packed)
AsanDetectStackUseAfterReturnMode UseAfterReturn
int InstrumentationWithCallsThreshold
uint32_t MaxInlinePoisoningSize
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
Description of the encoding of one expression Op.
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.
Various options to control the behavior of getObjectSize.
bool RoundToAlign
Whether to round the result up to the alignment of allocas, byval arguments, and global variables.
A CRTP mix-in to automatically provide informational APIs needed for passes.
SizeOffsetAPInt - Used by ObjectSizeOffsetVisitor, which works with APInts.