93#define DEBUG_TYPE "asan"
99 std::numeric_limits<uint64_t>::max();
140 "__asan_unregister_image_globals";
153 "__asan_stack_malloc_always_";
167 "__asan_option_detect_stack_use_after_return";
170 "__asan_shadow_memory_dynamic_address";
194 "asan-kernel",
cl::desc(
"Enable KernelAddressSanitizer instrumentation"),
199 cl::desc(
"Enable recovery mode (continue-after-error)."),
203 "asan-guard-against-version-mismatch",
204 cl::desc(
"Guard against compiler/runtime version mismatch."),
209 cl::desc(
"instrument read instructions"),
213 "asan-instrument-writes",
cl::desc(
"instrument write instructions"),
222 "asan-instrument-atomics",
232 "asan-always-slow-path",
237 "asan-force-dynamic-shadow",
238 cl::desc(
"Load shadow address into a local variable for each function"),
243 cl::desc(
"Access dynamic shadow through an ifunc global on "
244 "platforms that support this"),
248 "asan-with-ifunc-suppress-remat",
249 cl::desc(
"Suppress rematerialization of dynamic shadow address by passing "
250 "it through inline asm in prologue."),
258 "asan-max-ins-per-bb",
cl::init(10000),
259 cl::desc(
"maximal number of instructions to instrument in any given BB"),
266 "asan-max-inline-poisoning-size",
268 "Inline shadow poisoning for blocks up to the given size in bytes."),
272 "asan-use-after-return",
273 cl::desc(
"Sets the mode of detection for stack-use-after-return."),
275 clEnumValN(AsanDetectStackUseAfterReturnMode::Never,
"never",
276 "Never detect stack use after return."),
278 AsanDetectStackUseAfterReturnMode::Runtime,
"runtime",
279 "Detect stack use after return if "
280 "binary flag 'ASAN_OPTIONS=detect_stack_use_after_return' is set."),
281 clEnumValN(AsanDetectStackUseAfterReturnMode::Always,
"always",
282 "Always detect stack use after return.")),
286 cl::desc(
"Create redzones for byval "
287 "arguments (extra copy "
292 cl::desc(
"Check stack-use-after-scope"),
301 cl::desc(
"Handle C++ initializer order"),
305 "asan-detect-invalid-pointer-pair",
310 "asan-detect-invalid-pointer-cmp",
315 "asan-detect-invalid-pointer-sub",
320 "asan-realign-stack",
321 cl::desc(
"Realign stack to the value of this flag (power of two)"),
325 "asan-instrumentation-with-call-threshold",
327 "If the function being instrumented contains more than "
328 "this number of memory accesses, use callbacks instead of "
329 "inline checks (-1 means never use callbacks)."),
333 "asan-memory-access-callback-prefix",
338 "asan-kernel-mem-intrinsic-prefix",
344 cl::desc(
"instrument dynamic allocas"),
348 "asan-skip-promotable-allocas",
353 "asan-constructor-kind",
354 cl::desc(
"Sets the ASan constructor kind"),
357 "Use global constructors")),
364 cl::desc(
"scale of asan shadow mapping"),
369 cl::desc(
"offset of asan shadow mapping [EXPERIMENTAL]"),
383 "asan-opt-same-temp",
cl::desc(
"Instrument the same temp just once"),
387 cl::desc(
"Don't instrument scalar globals"),
391 "asan-opt-stack",
cl::desc(
"Don't instrument scalar stack variables"),
395 "asan-stack-dynamic-alloca",
400 "asan-force-experiment",
406 cl::desc(
"Use private aliases for global variables"),
411 cl::desc(
"Use odr indicators to improve ODR reporting"),
416 cl::desc(
"Use linker features to support dead "
417 "code stripping of globals"),
424 cl::desc(
"Place ASan constructors in comdat sections"),
428 "asan-destructor-kind",
429 cl::desc(
"Sets the ASan destructor kind. The default is to use the value "
430 "provided to the pass constructor"),
433 "Use global destructors")),
453STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
454STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
456 "Number of optimized accesses to global vars");
458 "Number of optimized accesses to stack vars");
467struct ShadowMapping {
478 bool IsAndroid = TargetTriple.
isAndroid();
481 bool IsMacOS = TargetTriple.
isMacOSX();
484 bool IsPS = TargetTriple.
isPS();
491 bool IsMIPS32 = TargetTriple.
isMIPS32();
492 bool IsMIPS64 = TargetTriple.
isMIPS64();
493 bool IsArmOrThumb = TargetTriple.
isARM() || TargetTriple.
isThumb();
500 bool IsAMDGPU = TargetTriple.
isAMDGPU();
502 ShadowMapping Mapping;
509 if (LongSize == 32) {
512 else if (IsMIPSN32ABI)
524 else if (IsEmscripten)
537 else if (IsFreeBSD && IsAArch64)
539 else if (IsFreeBSD && !IsMIPS64) {
544 }
else if (IsNetBSD) {
551 else if (IsLinux && IsX86_64) {
557 }
else if (IsWindows && IsX86_64) {
563 else if (IsMacOS && IsAArch64)
567 else if (IsLoongArch64)
591 Mapping.OrShadowOffset = !IsAArch64 && !IsPPC64 && !IsSystemZ && !IsPS &&
592 !IsRISCV64 && !IsLoongArch64 &&
593 !(Mapping.Offset & (Mapping.Offset - 1)) &&
595 bool IsAndroidWithIfuncSupport =
597 Mapping.InGlobal =
ClWithIfunc && IsAndroidWithIfuncSupport && IsArmOrThumb;
605 int *MappingScale,
bool *OrShadowOffset) {
607 *ShadowBase = Mapping.Offset;
608 *MappingScale = Mapping.Scale;
609 *OrShadowOffset = Mapping.OrShadowOffset;
619 uint8_t AccessSizeIndex)
623 AccessSizeIndex(AccessSizeIndex), IsWrite(IsWrite),
624 CompileKernel(CompileKernel) {}
631 return std::max(32U, 1U << MappingScale);
645struct AddressSanitizer {
647 bool CompileKernel =
false,
bool Recover =
false,
648 bool UseAfterScope =
false,
650 AsanDetectStackUseAfterReturnMode::Runtime)
658 C = &(
M.getContext());
659 DL = &
M.getDataLayout();
660 LongSize =
M.getDataLayout().getPointerSizeInBits();
664 TargetTriple =
Triple(
M.getTargetTriple());
668 assert(this->UseAfterReturn != AsanDetectStackUseAfterReturnMode::Invalid);
676 bool isInterestingAlloca(
const AllocaInst &AI);
679 void getInterestingMemoryOperands(
685 void instrumentPointerComparisonOrSubtraction(
Instruction *
I);
691 uint32_t TypeStoreSize,
bool IsWrite,
692 Value *SizeArgument);
695 TypeSize TypeStoreSize,
bool IsWrite,
696 Value *SizeArgument,
bool UseCalls,
698 void instrumentMaskedLoadOrStore(AddressSanitizer *
Pass,
const DataLayout &DL,
702 Type *OpType,
bool IsWrite,
703 Value *SizeArgument,
bool UseCalls,
708 bool IsWrite,
size_t AccessSizeIndex,
712 bool suppressInstrumentationSiteForDebug(
int &Instrumented);
714 bool maybeInsertAsanInitAtFunctionEntry(
Function &
F);
715 bool maybeInsertDynamicShadowAtFunctionEntry(
Function &
F);
716 void markEscapedLocalAllocas(
Function &
F);
719 friend struct FunctionStackPoisoner;
729 struct FunctionStateRAII {
730 AddressSanitizer *
Pass;
732 FunctionStateRAII(AddressSanitizer *
Pass) :
Pass(
Pass) {
734 "last pass forgot to clear cache");
738 ~FunctionStateRAII() {
739 Pass->LocalDynamicShadow =
nullptr;
740 Pass->ProcessedAllocas.clear();
755 ShadowMapping Mapping;
769 Value *LocalDynamicShadow =
nullptr;
777class ModuleAddressSanitizer {
779 ModuleAddressSanitizer(
Module &M,
bool CompileKernel =
false,
780 bool Recover =
false,
bool UseGlobalsGC =
true,
781 bool UseOdrIndicator =
true,
787 UseGlobalsGC(UseGlobalsGC &&
ClUseGlobalsGC && !this->CompileKernel),
802 UseCtorComdat(UseGlobalsGC &&
ClWithComdat && !this->CompileKernel),
803 DestructorKind(DestructorKind),
804 ConstructorKind(ConstructorKind) {
805 C = &(
M.getContext());
806 int LongSize =
M.getDataLayout().getPointerSizeInBits();
808 TargetTriple =
Triple(
M.getTargetTriple());
813 assert(this->DestructorKind != AsanDtorKind::Invalid);
816 bool instrumentModule(
Module &);
819 void initializeCallbacks(
Module &M);
828 const std::string &UniqueModuleId);
845 bool ShouldUseMachOGlobalsSection()
const;
846 StringRef getGlobalMetadataSection()
const;
849 uint64_t getMinRedzoneSizeForGlobal()
const {
853 int GetAsanVersion(
const Module &M)
const;
858 bool UsePrivateAlias;
859 bool UseOdrIndicator;
866 ShadowMapping Mapping;
876 Function *AsanCtorFunction =
nullptr;
877 Function *AsanDtorFunction =
nullptr;
889struct FunctionStackPoisoner :
public InstVisitor<FunctionStackPoisoner> {
891 AddressSanitizer &ASan;
896 ShadowMapping Mapping;
905 FunctionCallee AsanPoisonStackMemoryFunc, AsanUnpoisonStackMemoryFunc;
909 struct AllocaPoisonCall {
917 bool HasUntracedLifetimeIntrinsic =
false;
924 bool HasInlineAsm =
false;
925 bool HasReturnsTwiceCall =
false;
928 FunctionStackPoisoner(
Function &F, AddressSanitizer &ASan)
930 C(ASan.
C), IntptrTy(ASan.IntptrTy),
931 IntptrPtrTy(
PointerType::
get(IntptrTy, 0)), Mapping(ASan.Mapping),
940 copyArgsPassedByValToAllocas();
945 if (AllocaVec.
empty() && DynamicAllocaVec.
empty())
return false;
947 initializeCallbacks(*
F.getParent());
949 if (HasUntracedLifetimeIntrinsic) {
953 StaticAllocaPoisonCallVec.
clear();
954 DynamicAllocaPoisonCallVec.
clear();
957 processDynamicAllocas();
958 processStaticAllocas();
969 void copyArgsPassedByValToAllocas();
974 void processStaticAllocas();
975 void processDynamicAllocas();
977 void createDynamicAllocasInitStorage();
995 void unpoisonDynamicAllocasBeforeInst(
Instruction *InstBefore,
998 Value *DynamicAreaPtr = IRB.CreatePtrToInt(SavedStack, IntptrTy);
1003 if (!isa<ReturnInst>(InstBefore)) {
1005 InstBefore->
getModule(), Intrinsic::get_dynamic_area_offset,
1008 Value *DynamicAreaOffset = IRB.CreateCall(DynamicAreaOffsetFunc, {});
1010 DynamicAreaPtr = IRB.CreateAdd(IRB.CreatePtrToInt(SavedStack, IntptrTy),
1015 AsanAllocasUnpoisonFunc,
1016 {IRB.CreateLoad(IntptrTy, DynamicAllocaLayout), DynamicAreaPtr});
1020 void unpoisonDynamicAllocas() {
1022 unpoisonDynamicAllocasBeforeInst(Ret, DynamicAllocaLayout);
1024 for (
Instruction *StackRestoreInst : StackRestoreVec)
1025 unpoisonDynamicAllocasBeforeInst(StackRestoreInst,
1026 StackRestoreInst->getOperand(0));
1039 void handleDynamicAllocaCall(
AllocaInst *AI);
1044 if (!ASan.isInterestingAlloca(AI) ||
1049 if (AllocaVec.
empty())
1067 if (
ID == Intrinsic::stackrestore) StackRestoreVec.
push_back(&II);
1068 if (
ID == Intrinsic::localescape) LocalEscapeCall = &II;
1069 if (!ASan.UseAfterScope)
1076 if (
Size->isMinusOne())
return;
1079 const uint64_t SizeValue =
Size->getValue().getLimitedValue();
1080 if (SizeValue == ~0ULL ||
1088 HasUntracedLifetimeIntrinsic =
true;
1092 if (!ASan.isInterestingAlloca(*AI))
1094 bool DoPoison = (
ID == Intrinsic::lifetime_end);
1095 AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison};
1097 StaticAllocaPoisonCallVec.
push_back(APC);
1099 DynamicAllocaPoisonCallVec.
push_back(APC);
1103 if (
CallInst *CI = dyn_cast<CallInst>(&CB)) {
1104 HasInlineAsm |= CI->isInlineAsm() && &CB != ASan.LocalDynamicShadow;
1105 HasReturnsTwiceCall |= CI->canReturnTwice();
1110 void initializeCallbacks(
Module &M);
1137 OS, MapClassName2PassName);
1149 UseOdrIndicator(UseOdrIndicator), DestructorKind(DestructorKind),
1154 ModuleAddressSanitizer ModuleSanitizer(M, Options.
CompileKernel,
1156 UseOdrIndicator, DestructorKind,
1163 AddressSanitizer FunctionSanitizer(M, SSGI, Options.
CompileKernel,
1167 Modified |= FunctionSanitizer.instrumentFunction(
F, &TLI);
1169 Modified |= ModuleSanitizer.instrumentModule(M);
1190 if (
G->getName().startswith(
"llvm.") ||
1192 G->getName().startswith(
"__llvm_gcov_ctr") ||
1194 G->getName().startswith(
"__llvm_rtti_proxy"))
1207 Type *PtrTy = cast<PointerType>(
Addr->getType()->getScalarType());
1209 if (AddrSpace == 3 || AddrSpace == 5)
1216 Shadow = IRB.
CreateLShr(Shadow, Mapping.Scale);
1217 if (Mapping.Offset == 0)
return Shadow;
1220 if (LocalDynamicShadow)
1221 ShadowBase = LocalDynamicShadow;
1224 if (Mapping.OrShadowOffset)
1225 return IRB.
CreateOr(Shadow, ShadowBase);
1227 return IRB.
CreateAdd(Shadow, ShadowBase);
1233 if (isa<MemTransferInst>(
MI)) {
1235 isa<MemMoveInst>(
MI) ? AsanMemmove : AsanMemcpy,
1239 }
else if (isa<MemSetInst>(
MI)) {
1246 MI->eraseFromParent();
1250bool AddressSanitizer::isInterestingAlloca(
const AllocaInst &AI) {
1251 auto PreviouslySeenAllocaInfo = ProcessedAllocas.find(&AI);
1253 if (PreviouslySeenAllocaInfo != ProcessedAllocas.end())
1254 return PreviouslySeenAllocaInfo->getSecond();
1256 bool IsInteresting =
1269 !(SSGI && SSGI->
isSafe(AI)));
1271 ProcessedAllocas[&AI] = IsInteresting;
1272 return IsInteresting;
1277 Type *PtrTy = cast<PointerType>(
Ptr->getType()->getScalarType());
1286 if (
Ptr->isSwiftError())
1292 if (
auto AI = dyn_cast_or_null<AllocaInst>(
Ptr))
1303void AddressSanitizer::getInterestingMemoryOperands(
1306 if (LocalDynamicShadow ==
I)
1309 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
1312 Interesting.
emplace_back(
I, LI->getPointerOperandIndex(),
false,
1313 LI->getType(), LI->getAlign());
1314 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1318 SI->getValueOperand()->getType(),
SI->getAlign());
1322 Interesting.
emplace_back(
I, RMW->getPointerOperandIndex(),
true,
1323 RMW->getValOperand()->getType(), std::nullopt);
1327 Interesting.
emplace_back(
I, XCHG->getPointerOperandIndex(),
true,
1328 XCHG->getCompareOperand()->getType(),
1330 }
else if (
auto CI = dyn_cast<CallInst>(
I)) {
1331 switch (CI->getIntrinsicID()) {
1332 case Intrinsic::masked_load:
1333 case Intrinsic::masked_store: {
1334 bool IsWrite = CI->getIntrinsicID() == Intrinsic::masked_store;
1336 unsigned OpOffset = IsWrite ? 1 : 0;
1340 auto BasePtr = CI->getOperand(OpOffset);
1341 if (ignoreAccess(
I, BasePtr))
1343 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1346 if (
auto *Op = dyn_cast<ConstantInt>(CI->getOperand(1 + OpOffset)))
1347 Alignment =
Op->getMaybeAlignValue();
1348 Value *
Mask = CI->getOperand(2 + OpOffset);
1349 Interesting.
emplace_back(
I, OpOffset, IsWrite, Ty, Alignment, Mask);
1352 case Intrinsic::vp_load:
1353 case Intrinsic::vp_store:
1354 case Intrinsic::experimental_vp_strided_load:
1355 case Intrinsic::experimental_vp_strided_store: {
1356 auto *VPI = cast<VPIntrinsic>(CI);
1357 unsigned IID = CI->getIntrinsicID();
1358 bool IsWrite = CI->getType()->isVoidTy();
1361 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1362 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1363 MaybeAlign Alignment = VPI->getOperand(PtrOpNo)->getPointerAlignment(*
DL);
1364 Value *Stride =
nullptr;
1365 if (IID == Intrinsic::experimental_vp_strided_store ||
1366 IID == Intrinsic::experimental_vp_strided_load) {
1367 Stride = VPI->getOperand(PtrOpNo + 1);
1372 if (!isa<ConstantInt>(Stride) ||
1373 cast<ConstantInt>(Stride)->getZExtValue() % PointerAlign != 0)
1374 Alignment =
Align(1);
1376 Interesting.
emplace_back(
I, PtrOpNo, IsWrite, Ty, Alignment,
1377 VPI->getMaskParam(), VPI->getVectorLengthParam(),
1381 case Intrinsic::vp_gather:
1382 case Intrinsic::vp_scatter: {
1383 auto *VPI = cast<VPIntrinsic>(CI);
1384 unsigned IID = CI->getIntrinsicID();
1385 bool IsWrite = IID == Intrinsic::vp_scatter;
1388 unsigned PtrOpNo = *VPI->getMemoryPointerParamPos(IID);
1389 Type *Ty = IsWrite ? CI->getArgOperand(0)->getType() : CI->getType();
1390 MaybeAlign Alignment = VPI->getPointerAlignment();
1391 Interesting.
emplace_back(
I, PtrOpNo, IsWrite, Ty, Alignment,
1392 VPI->getMaskParam(),
1393 VPI->getVectorLengthParam());
1397 for (
unsigned ArgNo = 0; ArgNo < CI->arg_size(); ArgNo++) {
1399 ignoreAccess(
I, CI->getArgOperand(ArgNo)))
1401 Type *Ty = CI->getParamByValType(ArgNo);
1409 return V->getType()->isPointerTy() || isa<PtrToIntInst>(V);
1416 if (
ICmpInst *Cmp = dyn_cast<ICmpInst>(
I)) {
1417 if (!Cmp->isRelational())
1431 if (BO->getOpcode() != Instruction::Sub)
1444 if (!
G->hasInitializer())
1447 if (
G->hasSanitizerMetadata() &&
G->getSanitizerMetadata().IsDynInit)
1453void AddressSanitizer::instrumentPointerComparisonOrSubtraction(
1456 FunctionCallee F = isa<ICmpInst>(
I) ? AsanPtrCmpFunction : AsanPtrSubFunction;
1457 Value *
Param[2] = {
I->getOperand(0),
I->getOperand(1)};
1458 for (
Value *&i : Param) {
1459 if (i->getType()->isPointerTy())
1468 TypeSize TypeStoreSize,
bool IsWrite,
1469 Value *SizeArgument,
bool UseCalls,
1475 switch (FixedSize) {
1481 if (!Alignment || *Alignment >= Granularity ||
1482 *Alignment >= FixedSize / 8)
1483 return Pass->instrumentAddress(
I, InsertBefore,
Addr, FixedSize,
1484 IsWrite,
nullptr, UseCalls, Exp);
1487 Pass->instrumentUnusualSizeOrAlignment(
I, InsertBefore,
Addr, TypeStoreSize,
1488 IsWrite,
nullptr, UseCalls, Exp);
1491void AddressSanitizer::instrumentMaskedLoadOrStore(
1494 MaybeAlign Alignment,
unsigned Granularity,
Type *OpType,
bool IsWrite,
1496 auto *VTy = cast<VectorType>(OpType);
1497 TypeSize ElemTypeSize =
DL.getTypeStoreSizeInBits(VTy->getScalarType());
1508 IB.SetInsertPoint(LoopInsertBefore);
1510 EVL =
IB.CreateZExtOrTrunc(EVL, IntptrTy);
1513 Value *
EC =
IB.CreateElementCount(IntptrTy, VTy->getElementCount());
1514 EVL =
IB.CreateBinaryIntrinsic(Intrinsic::umin, EVL, EC);
1516 EVL =
IB.CreateElementCount(IntptrTy, VTy->getElementCount());
1521 Stride =
IB.CreateZExtOrTrunc(Stride, IntptrTy);
1526 if (
auto *MaskElemC = dyn_cast<ConstantInt>(MaskElem)) {
1527 if (MaskElemC->isZero())
1538 Value *InstrumentedAddress;
1539 if (isa<VectorType>(
Addr->getType())) {
1541 cast<VectorType>(
Addr->getType())->getElementType()->isPointerTy() &&
1542 "Expected vector of pointer.");
1544 }
else if (Stride) {
1552 InstrumentedAddress, Alignment, Granularity,
1553 ElemTypeSize, IsWrite, SizeArgument, UseCalls, Exp);
1580 isSafeAccess(ObjSizeVis,
Addr,
O.TypeStoreSize)) {
1581 NumOptimizedAccessesToGlobalVar++;
1589 isSafeAccess(ObjSizeVis,
Addr,
O.TypeStoreSize)) {
1590 NumOptimizedAccessesToStackVar++;
1596 NumInstrumentedWrites++;
1598 NumInstrumentedReads++;
1600 unsigned Granularity = 1 << Mapping.Scale;
1602 instrumentMaskedLoadOrStore(
this,
DL, IntptrTy,
O.MaybeMask,
O.MaybeEVL,
1603 O.MaybeStride,
O.getInsn(),
Addr,
O.Alignment,
1604 Granularity,
O.OpType,
O.IsWrite,
nullptr,
1608 Granularity,
O.TypeStoreSize,
O.IsWrite,
nullptr, UseCalls,
1615 size_t AccessSizeIndex,
1616 Value *SizeArgument,
1624 {
Addr, SizeArgument});
1627 {
Addr, SizeArgument, ExpVal});
1631 IRB.
CreateCall(AsanErrorCallback[IsWrite][0][AccessSizeIndex],
Addr);
1633 Call = IRB.
CreateCall(AsanErrorCallback[IsWrite][1][AccessSizeIndex],
1637 Call->setCannotMerge();
1644 size_t Granularity =
static_cast<size_t>(1) << Mapping.Scale;
1646 Value *LastAccessedByte =
1649 if (TypeStoreSize / 8 > 1)
1659Instruction *AddressSanitizer::instrumentAMDGPUAddress(
1661 uint32_t TypeStoreSize,
bool IsWrite,
Value *SizeArgument) {
1665 Type *PtrTy = cast<PointerType>(
Addr->getType()->getScalarType());
1668 return InsertBefore;
1674 Value *IsSharedOrPrivate = IRB.
CreateOr(IsShared, IsPrivate);
1676 Value *AddrSpaceZeroLanding =
1678 InsertBefore = cast<Instruction>(AddrSpaceZeroLanding);
1679 return InsertBefore;
1682void AddressSanitizer::instrumentAddress(
Instruction *OrigIns,
1684 uint32_t TypeStoreSize,
bool IsWrite,
1685 Value *SizeArgument,
bool UseCalls,
1687 if (TargetTriple.isAMDGPU()) {
1688 InsertBefore = instrumentAMDGPUAddress(OrigIns, InsertBefore,
Addr,
1689 TypeStoreSize, IsWrite, SizeArgument);
1696 const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
1699 const ASanAccessInfo AccessInfo(IsWrite, CompileKernel, AccessSizeIndex);
1711 IRB.
CreateCall(AsanMemoryAccessCallback[IsWrite][0][AccessSizeIndex],
1714 IRB.
CreateCall(AsanMemoryAccessCallback[IsWrite][1][AccessSizeIndex],
1722 Value *ShadowPtr = memToShadow(AddrLong, IRB);
1723 Value *ShadowValue =
1727 size_t Granularity = 1ULL << Mapping.Scale;
1735 assert(cast<BranchInst>(CheckTerm)->isUnconditional());
1738 Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeStoreSize);
1752 Instruction *Crash = generateCrashCode(CrashTerm, AddrLong, IsWrite,
1753 AccessSizeIndex, SizeArgument, Exp);
1761void AddressSanitizer::instrumentUnusualSizeOrAlignment(
1763 bool IsWrite,
Value *SizeArgument,
bool UseCalls,
uint32_t Exp) {
1771 IRB.
CreateCall(AsanMemoryAccessCallbackSized[IsWrite][0],
1774 IRB.
CreateCall(AsanMemoryAccessCallbackSized[IsWrite][1],
1781 instrumentAddress(
I, InsertBefore,
Addr, 8, IsWrite,
Size,
false, Exp);
1782 instrumentAddress(
I, InsertBefore, LastByte, 8, IsWrite,
Size,
false, Exp);
1786void ModuleAddressSanitizer::poisonOneInitializer(
Function &GlobalInit,
1794 IRB.
CreateCall(AsanPoisonGlobals, ModuleNameAddr);
1797 for (
auto &BB : GlobalInit)
1798 if (
ReturnInst *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
1802void ModuleAddressSanitizer::createInitializerPoisonCalls(
1813 if (isa<ConstantAggregateZero>(
OP))
continue;
1819 auto *Priority = cast<ConstantInt>(CS->
getOperand(0));
1829ModuleAddressSanitizer::getExcludedAliasedGlobal(
const GlobalAlias &GA)
const {
1834 assert(CompileKernel &&
"Only expecting to be called when compiling kernel");
1841 return dyn_cast<GlobalVariable>(
C->stripPointerCastsAndAliases());
1846bool ModuleAddressSanitizer::shouldInstrumentGlobal(
GlobalVariable *
G)
const {
1847 Type *Ty =
G->getValueType();
1850 if (
G->hasSanitizerMetadata() &&
G->getSanitizerMetadata().NoAddress)
1852 if (!Ty->
isSized())
return false;
1853 if (!
G->hasInitializer())
return false;
1855 if (
G->getAddressSpace() &&
1862 if (
G->isThreadLocal())
return false;
1864 if (
G->getAlign() && *
G->getAlign() > getMinRedzoneSizeForGlobal())
return false;
1870 if (!TargetTriple.isOSBinFormatCOFF()) {
1871 if (!
G->hasExactDefinition() ||
G->hasComdat())
1875 if (
G->isInterposable())
1882 switch (
C->getSelectionKind()) {
1893 if (
G->hasSection()) {
1903 if (Section ==
"llvm.metadata")
return false;
1910 if (
Section.startswith(
".preinit_array") ||
1911 Section.startswith(
".init_array") ||
1912 Section.startswith(
".fini_array")) {
1918 if (TargetTriple.isOSBinFormatELF()) {
1920 [](
char c) {
return llvm::isAlnum(c) || c ==
'_'; }))
1932 if (TargetTriple.isOSBinFormatCOFF() &&
Section.contains(
'$')) {
1933 LLVM_DEBUG(
dbgs() <<
"Ignoring global in sorted section (contains '$'): "
1938 if (TargetTriple.isOSBinFormatMachO()) {
1940 unsigned TAA = 0, StubSize = 0;
1943 Section, ParsedSegment, ParsedSection, TAA, TAAParsed, StubSize));
1948 if (ParsedSegment ==
"__OBJC" ||
1949 (ParsedSegment ==
"__DATA" && ParsedSection.
startswith(
"__objc_"))) {
1961 if (ParsedSegment ==
"__DATA" && ParsedSection ==
"__cfstring") {
1974 if (CompileKernel) {
1977 if (
G->getName().startswith(
"__"))
1987bool ModuleAddressSanitizer::ShouldUseMachOGlobalsSection()
const {
1988 if (!TargetTriple.isOSBinFormatMachO())
1991 if (TargetTriple.isMacOSX() && !TargetTriple.isMacOSXVersionLT(10, 11))
1993 if (TargetTriple.isiOS() && !TargetTriple.isOSVersionLT(9))
1995 if (TargetTriple.isWatchOS() && !TargetTriple.isOSVersionLT(2))
1997 if (TargetTriple.isDriverKit())
2003StringRef ModuleAddressSanitizer::getGlobalMetadataSection()
const {
2004 switch (TargetTriple.getObjectFormat()) {
2014 "ModuleAddressSanitizer not implemented for object file format");
2021void ModuleAddressSanitizer::initializeCallbacks(
Module &M) {
2027 AsanUnpoisonGlobals =
2031 AsanRegisterGlobals =
M.getOrInsertFunction(
2033 AsanUnregisterGlobals =
M.getOrInsertFunction(
2038 AsanRegisterImageGlobals =
M.getOrInsertFunction(
2040 AsanUnregisterImageGlobals =
M.getOrInsertFunction(
2043 AsanRegisterElfGlobals =
2045 IntptrTy, IntptrTy, IntptrTy);
2046 AsanUnregisterElfGlobals =
2048 IntptrTy, IntptrTy, IntptrTy);
2053void ModuleAddressSanitizer::SetComdatForGlobalMetadata(
2058 if (!
G->hasName()) {
2065 if (!InternalSuffix.
empty() &&
G->hasLocalLinkage()) {
2066 std::string
Name = std::string(
G->getName());
2067 Name += InternalSuffix;
2068 C =
M.getOrInsertComdat(
Name);
2070 C =
M.getOrInsertComdat(
G->getName());
2076 if (TargetTriple.isOSBinFormatCOFF()) {
2078 if (
G->hasPrivateLinkage())
2091ModuleAddressSanitizer::CreateMetadataGlobal(
Module &M,
Constant *Initializer,
2093 auto Linkage = TargetTriple.isOSBinFormatMachO()
2097 M, Initializer->
getType(),
false, Linkage, Initializer,
2099 Metadata->setSection(getGlobalMetadataSection());
2107 AsanDtorFunction->addFnAttr(Attribute::NoUnwind);
2115void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
2119 auto &
DL =
M.getDataLayout();
2122 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2123 Constant *Initializer = MetadataInitializers[i];
2126 CreateMetadataGlobal(M, Initializer,
G->getName());
2128 Metadata->setMetadata(LLVMContext::MD_associated, MD);
2134 unsigned SizeOfGlobalStruct =
DL.getTypeAllocSize(Initializer->
getType());
2136 "global metadata will not be padded appropriately");
2139 SetComdatForGlobalMetadata(
G,
Metadata,
"");
2144 if (!MetadataGlobals.empty())
2148void ModuleAddressSanitizer::InstrumentGlobalsELF(
2151 const std::string &UniqueModuleId) {
2158 bool UseComdatForGlobalsGC = UseOdrIndicator;
2161 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2164 CreateMetadataGlobal(M, MetadataInitializers[i],
G->getName());
2166 Metadata->setMetadata(LLVMContext::MD_associated, MD);
2169 if (UseComdatForGlobalsGC)
2170 SetComdatForGlobalMetadata(
G,
Metadata, UniqueModuleId);
2175 if (!MetadataGlobals.empty())
2192 "__start_" + getGlobalMetadataSection());
2196 "__stop_" + getGlobalMetadataSection());
2210 IrbDtor.CreateCall(AsanUnregisterElfGlobals,
2217void ModuleAddressSanitizer::InstrumentGlobalsMachO(
2228 for (
size_t i = 0; i < ExtendedGlobals.
size(); i++) {
2229 Constant *Initializer = MetadataInitializers[i];
2232 CreateMetadataGlobal(M, Initializer,
G->getName());
2236 auto LivenessBinder =
2241 Twine(
"__asan_binder_") +
G->getName());
2242 Liveness->
setSection(
"__DATA,__asan_liveness,regular,live_support");
2243 LivenessGlobals[i] = Liveness;
2250 if (!LivenessGlobals.empty())
2272 IrbDtor.CreateCall(AsanUnregisterImageGlobals,
2277void ModuleAddressSanitizer::InstrumentGlobalsWithMetadataArray(
2281 unsigned N = ExtendedGlobals.
size();
2291 if (Mapping.Scale > 3)
2292 AllGlobals->setAlignment(
Align(1ULL << Mapping.Scale));
2303 IrbDtor.CreateCall(AsanUnregisterGlobals,
2316 *CtorComdat =
false;
2321 if (CompileKernel) {
2322 for (
auto &GA :
M.aliases()) {
2324 AliasedGlobalExclusions.
insert(GV);
2329 for (
auto &
G :
M.globals()) {
2330 if (!AliasedGlobalExclusions.
count(&
G) && shouldInstrumentGlobal(&
G))
2334 size_t n = GlobalsToChange.
size();
2340 auto &
DL =
M.getDataLayout();
2354 IntptrTy, IntptrTy, IntptrTy);
2358 bool HasDynamicallyInitializedGlobals =
false;
2365 for (
size_t i = 0; i < n; i++) {
2369 if (
G->hasSanitizerMetadata())
2370 MD =
G->getSanitizerMetadata();
2375 std::string NameForGlobal =
G->getName().str();
2380 Type *Ty =
G->getValueType();
2381 const uint64_t SizeInBytes =
DL.getTypeAllocSize(Ty);
2382 const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes);
2394 M, NewTy,
G->isConstant(), Linkage, NewInitializer,
"",
G,
2395 G->getThreadLocalMode(),
G->getAddressSpace());
2405 if (TargetTriple.isOSBinFormatMachO() && !
G->hasSection() &&
2407 auto Seq = dyn_cast<ConstantDataSequential>(
G->getInitializer());
2408 if (Seq && Seq->isCString())
2409 NewGlobal->
setSection(
"__TEXT,__asan_cstring,regular");
2420 G->replaceAllUsesWith(
2423 G->eraseFromParent();
2424 NewGlobals[i] = NewGlobal;
2429 bool CanUsePrivateAliases =
2430 TargetTriple.isOSBinFormatELF() || TargetTriple.isOSBinFormatMachO() ||
2431 TargetTriple.isOSBinFormatWasm();
2432 if (CanUsePrivateAliases && UsePrivateAlias) {
2435 InstrumentedGlobal =
2443 }
else if (UseOdrIndicator) {
2446 auto *ODRIndicatorSym =
2455 ODRIndicatorSym->setAlignment(
Align(1));
2456 ODRIndicator = ODRIndicatorSym;
2471 HasDynamicallyInitializedGlobals =
true;
2475 Initializers[i] = Initializer;
2481 for (
size_t i = 0; i < n; i++) {
2483 if (
G->getName().empty())
continue;
2488 std::string ELFUniqueModuleId =
2492 if (!ELFUniqueModuleId.empty()) {
2493 InstrumentGlobalsELF(IRB, M, NewGlobals, Initializers, ELFUniqueModuleId);
2495 }
else if (UseGlobalsGC && TargetTriple.isOSBinFormatCOFF()) {
2496 InstrumentGlobalsCOFF(IRB, M, NewGlobals, Initializers);
2497 }
else if (UseGlobalsGC && ShouldUseMachOGlobalsSection()) {
2498 InstrumentGlobalsMachO(IRB, M, NewGlobals, Initializers);
2500 InstrumentGlobalsWithMetadataArray(IRB, M, NewGlobals, Initializers);
2504 if (HasDynamicallyInitializedGlobals)
2512ModuleAddressSanitizer::getRedzoneSizeForGlobal(
uint64_t SizeInBytes)
const {
2513 constexpr uint64_t kMaxRZ = 1 << 18;
2514 const uint64_t MinRZ = getMinRedzoneSizeForGlobal();
2517 if (SizeInBytes <= MinRZ / 2) {
2521 RZ = MinRZ - SizeInBytes;
2524 RZ = std::clamp((SizeInBytes / MinRZ / 4) * MinRZ, MinRZ, kMaxRZ);
2527 if (SizeInBytes % MinRZ)
2528 RZ += MinRZ - (SizeInBytes % MinRZ);
2531 assert((RZ + SizeInBytes) % MinRZ == 0);
2536int ModuleAddressSanitizer::GetAsanVersion(
const Module &M)
const {
2537 int LongSize =
M.getDataLayout().getPointerSizeInBits();
2542 Version += (LongSize == 32 && isAndroid);
2546bool ModuleAddressSanitizer::instrumentModule(
Module &M) {
2547 initializeCallbacks(M);
2552 if (CompileKernel) {
2557 std::string AsanVersion = std::to_string(GetAsanVersion(M));
2558 std::string VersionCheckName =
2560 std::tie(AsanCtorFunction, std::ignore) =
2563 {}, VersionCheckName);
2567 bool CtorComdat =
true;
2570 if (AsanCtorFunction) {
2571 IRBuilder<> IRB(AsanCtorFunction->getEntryBlock().getTerminator());
2572 InstrumentGlobals(IRB, M, &CtorComdat);
2575 InstrumentGlobals(IRB, M, &CtorComdat);
2584 if (UseCtorComdat && TargetTriple.isOSBinFormatELF() && CtorComdat) {
2585 if (AsanCtorFunction) {
2589 if (AsanDtorFunction) {
2594 if (AsanCtorFunction)
2596 if (AsanDtorFunction)
2607 for (
int Exp = 0;
Exp < 2;
Exp++) {
2608 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
2609 const std::string TypeStr = AccessIsWrite ?
"store" :
"load";
2610 const std::string ExpStr =
Exp ?
"exp_" :
"";
2611 const std::string EndingStr = Recover ?
"_noabort" :
"";
2620 Args1.push_back(ExpType);
2621 if (
auto AK = TLI->getExtAttrForI32Param(
false)) {
2626 AsanErrorCallbackSized[AccessIsWrite][
Exp] =
M.getOrInsertFunction(
2630 AsanMemoryAccessCallbackSized[AccessIsWrite][
Exp] =
M.getOrInsertFunction(
2635 AccessSizeIndex++) {
2636 const std::string Suffix = TypeStr + itostr(1ULL << AccessSizeIndex);
2637 AsanErrorCallback[AccessIsWrite][
Exp][AccessSizeIndex] =
2638 M.getOrInsertFunction(
2642 AsanMemoryAccessCallback[AccessIsWrite][
Exp][AccessSizeIndex] =
2643 M.getOrInsertFunction(
2650 const std::string MemIntrinCallbackPrefix =
2654 AsanMemmove =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memmove",
2657 AsanMemcpy =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memcpy",
2660 AsanMemset =
M.getOrInsertFunction(MemIntrinCallbackPrefix +
"memset",
2665 AsanHandleNoReturnFunc =
2668 AsanPtrCmpFunction =
2670 AsanPtrSubFunction =
2672 if (Mapping.InGlobal)
2673 AsanShadowGlobal =
M.getOrInsertGlobal(
"__asan_shadow",
2676 AMDGPUAddressShared =
M.getOrInsertFunction(
2678 AMDGPUAddressPrivate =
M.getOrInsertFunction(
2682bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(
Function &
F) {
2690 if (
F.getName().find(
" load]") != std::string::npos) {
2700bool AddressSanitizer::maybeInsertDynamicShadowAtFunctionEntry(
Function &
F) {
2706 if (Mapping.InGlobal) {
2714 LocalDynamicShadow =
2715 IRB.
CreateCall(Asm, {AsanShadowGlobal},
".asan.shadow");
2717 LocalDynamicShadow =
2721 Value *GlobalDynamicAddress =
F.getParent()->getOrInsertGlobal(
2723 LocalDynamicShadow = IRB.
CreateLoad(IntptrTy, GlobalDynamicAddress);
2728void AddressSanitizer::markEscapedLocalAllocas(
Function &
F) {
2733 assert(ProcessedAllocas.empty() &&
"must process localescape before allocas");
2737 if (!
F.getParent()->getFunction(
"llvm.localescape"))
return;
2746 AllocaInst *AI = dyn_cast<AllocaInst>(
Arg->stripPointerCasts());
2748 "non-static alloca arg to localescape");
2749 ProcessedAllocas[AI] =
false;
2756bool AddressSanitizer::suppressInstrumentationSiteForDebug(
int &Instrumented) {
2757 bool ShouldInstrument =
2761 return !ShouldInstrument;
2764bool AddressSanitizer::instrumentFunction(
Function &
F,
2770 if (
F.getName().startswith(
"__asan_"))
return false;
2772 bool FunctionModified =
false;
2777 if (maybeInsertAsanInitAtFunctionEntry(
F))
2778 FunctionModified =
true;
2781 if (!
F.hasFnAttribute(Attribute::SanitizeAddress))
return FunctionModified;
2783 if (
F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation))
2784 return FunctionModified;
2788 initializeCallbacks(*
F.getParent(), TLI);
2790 FunctionStateRAII CleanupObj(
this);
2792 FunctionModified |= maybeInsertDynamicShadowAtFunctionEntry(
F);
2796 markEscapedLocalAllocas(
F);
2808 for (
auto &BB :
F) {
2810 TempsToInstrument.
clear();
2811 int NumInsnsPerBB = 0;
2812 for (
auto &Inst : BB) {
2813 if (LooksLikeCodeInBug11395(&Inst))
return false;
2818 getInterestingMemoryOperands(&Inst, InterestingOperands);
2820 if (!InterestingOperands.
empty()) {
2821 for (
auto &Operand : InterestingOperands) {
2827 if (Operand.MaybeMask) {
2831 if (!TempsToInstrument.
insert(
Ptr).second)
2835 OperandsToInstrument.
push_back(Operand);
2842 PointerComparisonsOrSubtracts.
push_back(&Inst);
2848 if (
auto *CB = dyn_cast<CallBase>(&Inst)) {
2850 TempsToInstrument.
clear();
2854 if (
CallInst *CI = dyn_cast<CallInst>(&Inst))
2862 OperandsToInstrument.
size() + IntrinToInstrument.
size() >
2870 int NumInstrumented = 0;
2871 for (
auto &Operand : OperandsToInstrument) {
2872 if (!suppressInstrumentationSiteForDebug(NumInstrumented))
2873 instrumentMop(ObjSizeVis, Operand, UseCalls,
2874 F.getParent()->getDataLayout());
2875 FunctionModified =
true;
2877 for (
auto *Inst : IntrinToInstrument) {
2878 if (!suppressInstrumentationSiteForDebug(NumInstrumented))
2879 instrumentMemIntrinsic(Inst);
2880 FunctionModified =
true;
2883 FunctionStackPoisoner FSP(
F, *
this);
2884 bool ChangedStack = FSP.runOnFunction();
2888 for (
auto *CI : NoReturnCalls) {
2893 for (
auto *Inst : PointerComparisonsOrSubtracts) {
2894 instrumentPointerComparisonOrSubtraction(Inst);
2895 FunctionModified =
true;
2898 if (ChangedStack || !NoReturnCalls.empty())
2899 FunctionModified =
true;
2901 LLVM_DEBUG(
dbgs() <<
"ASAN done instrumenting: " << FunctionModified <<
" "
2904 return FunctionModified;
2910bool AddressSanitizer::LooksLikeCodeInBug11395(
Instruction *
I) {
2911 if (LongSize != 32)
return false;
2920void FunctionStackPoisoner::initializeCallbacks(
Module &M) {
2924 const char *MallocNameTemplate =
2929 std::string Suffix = itostr(
Index);
2930 AsanStackMallocFunc[
Index] =
M.getOrInsertFunction(
2931 MallocNameTemplate + Suffix, IntptrTy, IntptrTy);
2932 AsanStackFreeFunc[
Index] =
2937 if (ASan.UseAfterScope) {
2938 AsanPoisonStackMemoryFunc =
M.getOrInsertFunction(
2940 AsanUnpoisonStackMemoryFunc =
M.getOrInsertFunction(
2944 for (
size_t Val : {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xf1, 0xf2,
2945 0xf3, 0xf5, 0xf8}) {
2946 std::ostringstream
Name;
2948 Name << std::setw(2) << std::setfill(
'0') << std::hex << Val;
2949 AsanSetShadowFunc[Val] =
2950 M.getOrInsertFunction(
Name.str(), IRB.
getVoidTy(), IntptrTy, IntptrTy);
2953 AsanAllocaPoisonFunc =
M.getOrInsertFunction(
2955 AsanAllocasUnpoisonFunc =
M.getOrInsertFunction(
2961 size_t Begin,
size_t End,
2963 Value *ShadowBase) {
2967 const size_t LargestStoreSizeInBytes =
2968 std::min<size_t>(
sizeof(
uint64_t), ASan.LongSize / 8);
2970 const bool IsLittleEndian =
F.getParent()->getDataLayout().isLittleEndian();
2976 for (
size_t i = Begin; i <
End;) {
2977 if (!ShadowMask[i]) {
2983 size_t StoreSizeInBytes = LargestStoreSizeInBytes;
2985 while (StoreSizeInBytes >
End - i)
2986 StoreSizeInBytes /= 2;
2989 for (
size_t j = StoreSizeInBytes - 1;
j && !ShadowMask[i +
j]; --
j) {
2990 while (j <= StoreSizeInBytes / 2)
2991 StoreSizeInBytes /= 2;
2995 for (
size_t j = 0;
j < StoreSizeInBytes;
j++) {
2997 Val |= (
uint64_t)ShadowBytes[i + j] << (8 * j);
2999 Val = (Val << 8) | ShadowBytes[i + j];
3003 Value *Poison = IRB.
getIntN(StoreSizeInBytes * 8, Val);
3008 i += StoreSizeInBytes;
3015 copyToShadow(ShadowMask, ShadowBytes, 0, ShadowMask.
size(), IRB, ShadowBase);
3020 size_t Begin,
size_t End,
3023 size_t Done = Begin;
3024 for (
size_t i = Begin, j = Begin + 1; i <
End; i =
j++) {
3025 if (!ShadowMask[i]) {
3029 uint8_t Val = ShadowBytes[i];
3030 if (!AsanSetShadowFunc[Val])
3034 for (;
j <
End && ShadowMask[
j] && Val == ShadowBytes[
j]; ++
j) {
3038 copyToShadowInline(ShadowMask, ShadowBytes,
Done, i, IRB, ShadowBase);
3046 copyToShadowInline(ShadowMask, ShadowBytes,
Done,
End, IRB, ShadowBase);
3054 for (
int i = 0;; i++, MaxSize *= 2)
3055 if (LocalStackSize <= MaxSize)
return i;
3059void FunctionStackPoisoner::copyArgsPassedByValToAllocas() {
3061 if (CopyInsertPoint == ASan.LocalDynamicShadow) {
3069 if (
Arg.hasByValAttr()) {
3070 Type *Ty =
Arg.getParamByValType();
3071 const Align Alignment =
3072 DL.getValueOrABITypeAlignment(
Arg.getParamAlign(), Ty);
3076 (
Arg.hasName() ?
Arg.getName() :
"Arg" +
Twine(
Arg.getArgNo())) +
3079 Arg.replaceAllUsesWith(AI);
3081 uint64_t AllocSize =
DL.getTypeAllocSize(Ty);
3090 Value *ValueIfFalse) {
3093 PHI->addIncoming(ValueIfFalse, CondBlock);
3095 PHI->addIncoming(ValueIfTrue, ThenBlock);
3099Value *FunctionStackPoisoner::createAllocaForLayout(
3108 nullptr,
"MyAlloca");
3117void FunctionStackPoisoner::createDynamicAllocasInitStorage() {
3120 DynamicAllocaLayout = IRB.
CreateAlloca(IntptrTy,
nullptr);
3125void FunctionStackPoisoner::processDynamicAllocas() {
3132 for (
const auto &APC : DynamicAllocaPoisonCallVec) {
3135 assert(ASan.isInterestingAlloca(*APC.AI));
3136 assert(!APC.AI->isStaticAlloca());
3139 poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
3146 createDynamicAllocasInitStorage();
3147 for (
auto &AI : DynamicAllocaVec)
3148 handleDynamicAllocaCall(AI);
3149 unpoisonDynamicAllocas();
3161 for (
Instruction *It = Start; It; It = It->getNextNonDebugInstruction()) {
3171 if (isa<AllocaInst>(It) || isa<CastInst>(It))
3173 if (
auto *Store = dyn_cast<StoreInst>(It)) {
3177 auto *Alloca = dyn_cast<AllocaInst>(Store->getPointerOperand());
3178 if (!Alloca || ASan.isInterestingAlloca(*Alloca))
3181 Value *Val = Store->getValueOperand();
3182 bool IsDirectArgInit = isa<Argument>(Val);
3183 bool IsArgInitViaCast =
3184 isa<CastInst>(Val) &&
3185 isa<Argument>(cast<CastInst>(Val)->getOperand(0)) &&
3188 Val == It->getPrevNonDebugInstruction();
3189 bool IsArgInit = IsDirectArgInit || IsArgInitViaCast;
3193 if (IsArgInitViaCast)
3194 InitInsts.
push_back(cast<Instruction>(Val));
3205void FunctionStackPoisoner::processStaticAllocas() {
3206 if (AllocaVec.
empty()) {
3211 int StackMallocIdx = -1;
3213 if (
auto SP =
F.getSubprogram())
3214 EntryDebugLocation =
3223 auto InsBeforeB = InsBefore->
getParent();
3224 assert(InsBeforeB == &
F.getEntryBlock());
3225 for (
auto *AI : StaticAllocasToMoveUp)
3236 ArgInitInst->moveBefore(InsBefore);
3239 if (LocalEscapeCall) LocalEscapeCall->
moveBefore(InsBefore);
3245 ASan.getAllocaSizeInBytes(*AI),
3256 uint64_t Granularity = 1ULL << Mapping.Scale;
3257 uint64_t MinHeaderSize = std::max((
uint64_t)ASan.LongSize / 2, Granularity);
3263 for (
auto &Desc : SVD)
3264 AllocaToSVDMap[Desc.AI] = &Desc;
3267 for (
const auto &APC : StaticAllocaPoisonCallVec) {
3270 assert(ASan.isInterestingAlloca(*APC.AI));
3271 assert(APC.AI->isStaticAlloca());
3276 if (
const DILocation *LifetimeLoc = APC.InsBefore->getDebugLoc().get()) {
3277 if (LifetimeLoc->getFile() == FnLoc->getFile())
3278 if (
unsigned Line = LifetimeLoc->getLine())
3279 Desc.
Line = std::min(Desc.
Line ? Desc.
Line : Line, Line);
3285 LLVM_DEBUG(
dbgs() << DescriptionString <<
" --- " <<
L.FrameSize <<
"\n");
3287 bool DoStackMalloc =
3297 DoDynamicAlloca &= !HasInlineAsm && !HasReturnsTwiceCall;
3298 DoStackMalloc &= !HasInlineAsm && !HasReturnsTwiceCall;
3300 Value *StaticAlloca =
3301 DoDynamicAlloca ? nullptr : createAllocaForLayout(IRB, L,
false);
3304 Value *LocalStackBase;
3305 Value *LocalStackBaseAlloca;
3308 if (DoStackMalloc) {
3309 LocalStackBaseAlloca =
3310 IRB.
CreateAlloca(IntptrTy,
nullptr,
"asan_local_stack_base");
3317 Constant *OptionDetectUseAfterReturn =
F.getParent()->getOrInsertGlobal(
3327 Value *FakeStackValue =
3328 IRBIf.CreateCall(AsanStackMallocFunc[StackMallocIdx],
3331 FakeStack = createPHI(IRB, UseAfterReturnIsEnabled, FakeStackValue, Term,
3339 FakeStack = IRB.
CreateCall(AsanStackMallocFunc[StackMallocIdx],
3342 Value *NoFakeStack =
3347 Value *AllocaValue =
3348 DoDynamicAlloca ? createAllocaForLayout(IRBIf, L,
true) : StaticAlloca;
3351 LocalStackBase = createPHI(IRB, NoFakeStack, AllocaValue, Term, FakeStack);
3352 IRB.
CreateStore(LocalStackBase, LocalStackBaseAlloca);
3359 DoDynamicAlloca ? createAllocaForLayout(IRB, L,
true) : StaticAlloca;
3360 LocalStackBaseAlloca = LocalStackBase;
3366 Value *LocalStackBaseAllocaPtr =
3367 isa<PtrToIntInst>(LocalStackBaseAlloca)
3368 ? cast<PtrToIntInst>(LocalStackBaseAlloca)->getPointerOperand()
3369 : LocalStackBaseAlloca;
3370 assert(isa<AllocaInst>(LocalStackBaseAllocaPtr) &&
3371 "Variable descriptions relative to ASan stack base will be dropped");
3374 for (
const auto &Desc : SVD) {
3409 Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB);
3412 copyToShadow(ShadowAfterScope, ShadowAfterScope, IRB, ShadowBase);
3414 if (!StaticAllocaPoisonCallVec.empty()) {
3418 for (
const auto &APC : StaticAllocaPoisonCallVec) {
3421 size_t Begin = Desc.
Offset /
L.Granularity;
3422 size_t End = Begin + (APC.Size +
L.Granularity - 1) /
L.Granularity;
3425 copyToShadow(ShadowAfterScope,
3426 APC.DoPoison ? ShadowAfterScope : ShadowInScope, Begin,
End,
3440 if (DoStackMalloc) {
3441 assert(StackMallocIdx >= 0);
3458 if (StackMallocIdx <= 4) {
3460 ShadowAfterReturn.
resize(ClassSize /
L.Granularity,
3462 copyToShadow(ShadowAfterReturn, ShadowAfterReturn, IRBPoison,
3464 Value *SavedFlagPtrPtr = IRBPoison.CreateAdd(
3467 Value *SavedFlagPtr = IRBPoison.CreateLoad(
3468 IntptrTy, IRBPoison.CreateIntToPtr(SavedFlagPtrPtr, IntptrPtrTy));
3469 IRBPoison.CreateStore(
3471 IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getInt8PtrTy()));
3474 IRBPoison.CreateCall(
3475 AsanStackFreeFunc[StackMallocIdx],
3480 copyToShadow(ShadowAfterScope, ShadowClean, IRBElse, ShadowBase);
3482 copyToShadow(ShadowAfterScope, ShadowClean, IRBRet, ShadowBase);
3487 for (
auto *AI : AllocaVec)
3497 DoPoison ? AsanPoisonStackMemoryFunc : AsanUnpoisonStackMemoryFunc,
3498 {AddrArg, SizeArg});
3509void FunctionStackPoisoner::handleDynamicAllocaCall(
AllocaInst *AI) {
3523 const unsigned ElementSize =
3558 IRB.
CreateCall(AsanAllocaPoisonFunc, {NewAddress, OldSize});
3583 if (!ObjSizeVis.
bothKnown(SizeOffset))
return false;
3585 int64_t
Offset = SizeOffset.second.getSExtValue();
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"))
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
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 const uint64_t kDefaultShadowScale
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 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)
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
static cl::opt< bool > ClUseStackSafety("asan-use-stack-safety", cl::Hidden, cl::init(false), cl::Hidden, cl::desc("Use Stack Safety analysis results"), cl::Optional)
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 > 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 bool isPointerOperand(Value *V)
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 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 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 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
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 const Function * getParent(const Value *V)
SmallVector< MachineOperand, 4 > Cond
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.
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
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.
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 CallInst * getTerminatingMustTailCall() const
Returns the call instruction marked 'musttail' prior to the terminating return instruction of this ba...
Conditional or Unconditional Branch instruction.
static BranchInst * Create(BasicBlock *IfTrue, Instruction *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.
Value * getArgOperand(unsigned i) const
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
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="", Instruction *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, bool InBounds=false, std::optional< unsigned > InRangeIndex=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 Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given 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...
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 applied.
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="")
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.
BasicBlock * GetInsertBlock() const
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
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)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
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...
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
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)
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", bool IsInBounds=false)
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 * 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)
bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
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.
const BasicBlock * getParent() const
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',...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
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.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
This is an important class for using LLVM in a threaded context.
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 * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
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.
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
Evaluate the size and offset of an object pointed to by a Value* statically.
static bool bothKnown(const SizeOffsetType &SizeOffset)
SizeOffsetType compute(Value *V)
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.
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, Instruction *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.
constexpr bool empty() const
empty - Check if the string is empty.
bool startswith(StringRef Prefix) const
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
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.
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.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
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 * getInt8Ty(LLVMContext &C)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
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.
StringRef getName() const
Return a constant reference to the value's name.
void takeName(Value *V)
Transfer the name from V to this value.
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.
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.
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)
std::string demangle(const std::string &MangledName)
Attempt to demangle a string using different demangling schemes.
std::pair< APInt, APInt > SizeOffsetType
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...
Instruction * SplitBlockAndInsertIfThen(Value *Cond, Instruction *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 ...
GlobalVariable * createPrivateGlobalForString(Module &M, StringRef Str, bool AllowMerging, const char *NamePrefix="")
const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)
This method strips off any GEP address adjustments and pointer casts from the specified value,...
void SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore, Instruction **ThenTerm, Instruction **ElseTerm, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr)
SplitBlockAndInsertIfThenElse is similar to SplitBlockAndInsertIfThen, but also creates the ElseBlock...
bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
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 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.
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
@ 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)
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)
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)