16 #define DEBUG_TYPE "asan"
41 #include "llvm/Support/DataTypes.h"
76 "__asan_unregister_globals";
89 "__asan_poison_stack_memory";
91 "__asan_unpoison_stack_memory";
94 "__asan_option_detect_stack_use_after_return";
116 cl::desc(
"instrument atomic instructions (rmw, cmpxchg)"),
119 cl::desc(
"use instrumentation with slow path for all accesses"),
127 cl::desc(
"maximal number of instructions to instrument in any given BB"),
147 cl::desc(
"File containing the list of objects to ignore "
160 cl::desc(
"Keep uninstrumented copies of functions"),
171 cl::desc(
"Use short immediate constant as the mapping offset for 64bit"),
185 cl::desc(
"Use llvm.lifetime intrinsics to insert extra checks"),
200 STATISTIC(NumInstrumentedReads,
"Number of instrumented reads");
201 STATISTIC(NumInstrumentedWrites,
"Number of instrumented writes");
202 STATISTIC(NumOptimizedAccessesToGlobalArray,
203 "Number of optimized accesses to global arrays");
204 STATISTIC(NumOptimizedAccessesToGlobalVar,
205 "Number of optimized accesses to global vars");
209 class SetOfDynamicallyInitializedGlobals {
217 for (
int i = 0, n = DynamicGlobals->
getNumOperands(); i < n; ++i) {
225 DynInitGlobals.insert(cast<GlobalVariable>(VG));
228 bool Contains(
GlobalVariable *
G) {
return DynInitGlobals.count(G) != 0; }
235 struct ShadowMapping {
241 static ShadowMapping getShadowMapping(
const Module &M,
int LongSize,
242 bool ZeroBaseShadow) {
252 ShadowMapping Mapping;
259 Mapping.Offset = (IsAndroid || ZeroBaseShadow) ? 0 :
264 assert(LongSize == 64);
280 static size_t RedzoneSizeForScale(
int MappingScale) {
283 return std::max(32U, 1U << MappingScale);
288 AddressSanitizer(
bool CheckInitOrder =
true,
289 bool CheckUseAfterReturn =
false,
290 bool CheckLifetime =
false,
292 bool ZeroBaseShadow =
false)
299 ZeroBaseShadow(ZeroBaseShadow) {}
300 virtual const char *getPassName()
const {
301 return "AddressSanitizerFunctionPass";
305 Value *Addr, uint32_t TypeSize,
bool IsWrite,
306 Value *SizeArgument);
308 Value *ShadowValue, uint32_t TypeSize);
310 bool IsWrite,
size_t AccessSizeIndex,
311 Value *SizeArgument);
318 bool maybeInsertAsanInitAtFunctionEntry(
Function &
F);
320 virtual bool doInitialization(
Module &M);
324 void initializeCallbacks(
Module &M);
328 void FindDynamicInitializers(
Module &M);
333 bool CheckUseAfterReturn;
342 ShadowMapping Mapping;
351 Function *AsanErrorCallbackSized[2];
353 SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
355 friend struct FunctionStackPoisoner;
358 class AddressSanitizerModule :
public ModulePass {
360 AddressSanitizerModule(
bool CheckInitOrder =
true,
362 bool ZeroBaseShadow =
false)
367 ZeroBaseShadow(ZeroBaseShadow) {}
368 bool runOnModule(
Module &M);
370 virtual const char *getPassName()
const {
371 return "AddressSanitizerModule";
375 void initializeCallbacks(
Module &M);
379 size_t RedzoneSize()
const {
380 return RedzoneSizeForScale(Mapping.Scale);
388 SetOfDynamicallyInitializedGlobals DynamicallyInitializedGlobals;
392 ShadowMapping Mapping;
408 struct FunctionStackPoisoner :
public InstVisitor<FunctionStackPoisoner> {
410 AddressSanitizer &ASan;
415 ShadowMapping Mapping;
419 uint64_t TotalStackSize;
420 unsigned StackAlignment;
424 Function *AsanPoisonStackMemoryFunc, *AsanUnpoisonStackMemoryFunc;
427 struct AllocaPoisonCall {
437 AllocaForValueMapTy AllocaForValue;
439 FunctionStackPoisoner(
Function &
F, AddressSanitizer &ASan)
440 : F(F), ASan(ASan), DIB(*F.
getParent()),
C(ASan.
C),
441 IntptrTy(ASan.IntptrTy), IntptrPtrTy(
PointerType::get(IntptrTy, 0)),
442 Mapping(ASan.Mapping),
443 TotalStackSize(0), StackAlignment(1 << Mapping.Scale) {}
445 bool runOnFunction() {
453 if (AllocaVec.empty())
return false;
455 initializeCallbacks(*
F.getParent());
473 RetVec.push_back(&RI);
478 if (!isInterestingAlloca(AI))
return;
480 StackAlignment = std::max(StackAlignment, AI.
getAlignment());
481 AllocaVec.push_back(&AI);
482 uint64_t AlignedSize = getAlignedAllocaSize(&AI);
483 TotalStackSize += AlignedSize;
489 if (!ASan.CheckLifetime)
return;
501 if (SizeValue == ~0ULL ||
508 AllocaPoisonCall APC = {&II, AI, SizeValue, DoPoison};
509 AllocaPoisonCallVec.push_back(APC);
513 void initializeCallbacks(
Module &M);
516 bool isInterestingAlloca(
AllocaInst &AI)
const {
523 size_t RedzoneSize()
const {
524 return RedzoneSizeForScale(Mapping.Scale);
526 uint64_t getAllocaSizeInBytes(
AllocaInst *AI)
const {
528 uint64_t SizeInBytes = ASan.TD->getTypeAllocSize(Ty);
531 uint64_t getAlignedSize(uint64_t SizeInBytes)
const {
532 size_t RZ = RedzoneSize();
533 return ((SizeInBytes + RZ - 1) / RZ) *
RZ;
535 uint64_t getAlignedAllocaSize(
AllocaInst *AI)
const {
536 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
537 return getAlignedSize(SizeInBytes);
542 Value *ShadowBase,
bool DoPoison);
543 void poisonAlloca(
Value *V, uint64_t Size,
IRBuilder<> &IRB,
bool DoPoison);
545 void SetShadowToStackAfterReturnInlined(
IRBuilder<> &IRB,
Value *ShadowBase,
553 "AddressSanitizer: detects use-after-free and out-of-bounds bugs.",
556 bool CheckInitOrder,
bool CheckUseAfterReturn,
bool CheckLifetime,
557 StringRef BlacklistFile,
bool ZeroBaseShadow) {
558 return new AddressSanitizer(CheckInitOrder, CheckUseAfterReturn,
559 CheckLifetime, BlacklistFile, ZeroBaseShadow);
564 "AddressSanitizer: detects use-after-free and out-of-bounds bugs."
565 "ModulePass",
false,
false)
567 bool CheckInitOrder,
StringRef BlacklistFile,
bool ZeroBaseShadow) {
568 return new AddressSanitizerModule(CheckInitOrder, BlacklistFile,
595 Shadow = IRB.
CreateLShr(Shadow, Mapping.Scale);
596 if (Mapping.Offset == 0)
599 if (Mapping.OrShadowOffset)
605 void AddressSanitizer::instrumentMemIntrinsicParam(
609 if (Size->
getType() != IntptrTy)
612 instrumentAddress(OrigIns, InsertBefore, Addr, 8, IsWrite, Size);
618 instrumentAddress(OrigIns, InsertBefore, AddrLast, 8, IsWrite, Size);
641 instrumentMemIntrinsicParam(MI, Dst, Length, InsertBefore,
true);
643 instrumentMemIntrinsicParam(MI, Src, Length, InsertBefore,
false);
653 return LI->getPointerOperand();
655 if (
StoreInst *SI = dyn_cast<StoreInst>(I)) {
658 return SI->getPointerOperand();
663 return RMW->getPointerOperand();
668 return XCHG->getPointerOperand();
677 return G->
hasInitializer() && !DynamicallyInitializedGlobals.Contains(G);
681 bool IsWrite =
false;
688 if (!CheckInitOrder || GlobalIsLinkerInitialized(G)) {
689 NumOptimizedAccessesToGlobalVar++;
696 if (CE->
getOperand(1)->isNullValue() && GlobalIsLinkerInitialized(G)) {
697 NumOptimizedAccessesToGlobalArray++;
705 Type *OrigTy = cast<PointerType>(OrigPtrTy)->getElementType();
708 uint32_t TypeSize =
TD->getTypeStoreSizeInBits(OrigTy);
710 assert((TypeSize % 8) == 0);
713 NumInstrumentedWrites++;
715 NumInstrumentedReads++;
718 if (TypeSize == 8 || TypeSize == 16 ||
719 TypeSize == 32 || TypeSize == 64 || TypeSize == 128)
720 return instrumentAddress(I, I, Addr, TypeSize, IsWrite, 0);
731 instrumentAddress(I, I, Addr, 8, IsWrite, Size);
732 instrumentAddress(I, I, LastByte, 8, IsWrite, Size);
740 if (isa<Function>(FuncOrBitcast))
return cast<Function>(FuncOrBitcast);
741 FuncOrBitcast->
dump();
743 "interface function");
748 bool IsWrite,
size_t AccessSizeIndex,
Value *SizeArgument) {
751 ? IRB.
CreateCall2(AsanErrorCallbackSized[IsWrite], Addr, SizeArgument)
752 : IRB.
CreateCall(AsanErrorCallback[IsWrite][AccessSizeIndex], Addr);
764 size_t Granularity = 1 << Mapping.Scale;
769 if (TypeSize / 8 > 1)
774 LastAccessedByte, ShadowValue->
getType(),
false);
779 void AddressSanitizer::instrumentAddress(
Instruction *OrigIns,
781 Value *Addr, uint32_t TypeSize,
782 bool IsWrite,
Value *SizeArgument) {
787 *
C, std::max(8U, TypeSize >> Mapping.Scale));
789 Value *ShadowPtr = memToShadow(AddrLong, IRB);
796 size_t Granularity = 1 << Mapping.Scale;
802 assert(dyn_cast<BranchInst>(CheckTerm)->isUnconditional());
805 Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeSize);
816 CrashTerm, AddrLong, IsWrite, AccessSizeIndex, SizeArgument);
820 void AddressSanitizerModule::createInitializerPoisonCalls(
834 IRB.
CreateCall(AsanPoisonGlobals, ModuleNameAddr);
839 if (
ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator())) {
845 bool AddressSanitizerModule::ShouldInstrumentGlobal(
GlobalVariable *G) {
846 Type *Ty = cast<PointerType>(G->
getType())->getElementType();
847 DEBUG(
dbgs() <<
"GLOBAL: " << *G <<
"\n");
849 if (
BL->isIn(*G))
return false;
850 if (!Ty->
isSized())
return false;
873 DEBUG(
dbgs() <<
"Ignoring \\01L_OBJC_* global: " << *G);
882 if ((
Section.find(
"__OBJC,") == 0) ||
883 (
Section.find(
"__DATA, __objc_") == 0)) {
884 DEBUG(
dbgs() <<
"Ignoring ObjC runtime global: " << *G);
895 if (
Section.find(
"__DATA,__cfstring") == 0) {
896 DEBUG(
dbgs() <<
"Ignoring CFString: " << *G);
904 void AddressSanitizerModule::initializeCallbacks(
Module &M) {
916 IntptrTy, IntptrTy, NULL));
920 IRB.
getVoidTy(), IntptrTy, IntptrTy, NULL));
927 bool AddressSanitizerModule::runOnModule(
Module &M) {
929 TD = getAnalysisIfAvailable<DataLayout>();
933 if (
BL->isIn(M))
return false;
935 int LongSize =
TD->getPointerSizeInBits();
937 Mapping = getShadowMapping(M, LongSize, ZeroBaseShadow);
938 initializeCallbacks(M);
939 DynamicallyInitializedGlobals.Init(M);
945 if (ShouldInstrumentGlobal(G))
949 size_t n = GlobalsToChange.
size();
950 if (n == 0)
return false;
962 IntptrTy, IntptrTy, NULL);
969 bool HasDynamicallyInitializedGlobals =
false;
977 for (
size_t i = 0; i < n; i++) {
978 static const uint64_t kMaxGlobalRedzone = 1 << 18;
982 uint64_t SizeInBytes =
TD->getTypeAllocSize(Ty);
983 uint64_t MinRZ = RedzoneSize();
986 uint64_t
RZ = std::max(MinRZ,
987 std::min(kMaxGlobalRedzone,
988 (SizeInBytes / MinRZ / 4) * MinRZ));
989 uint64_t RightRedzoneSize =
RZ;
991 if (SizeInBytes % MinRZ)
992 RightRedzoneSize += MinRZ - (SizeInBytes % MinRZ);
993 assert(((RightRedzoneSize + SizeInBytes) % MinRZ) == 0);
996 bool GlobalHasDynamicInitializer =
997 DynamicallyInitializedGlobals.Contains(G);
999 GlobalHasDynamicInitializer &= !
BL->isIn(*G,
"init");
1014 NewInitializer,
"",
G, G->getThreadLocalMode());
1025 G->eraseFromParent();
1038 if (CheckInitOrder && GlobalHasDynamicInitializer)
1039 HasDynamicallyInitializedGlobals =
true;
1041 DEBUG(
dbgs() <<
"NEW GLOBAL: " << *NewGlobal <<
"\n");
1050 if (CheckInitOrder && HasDynamicallyInitializedGlobals)
1051 createInitializerPoisonCalls(M, ModuleName);
1063 IRB_Dtor.CreateCall2(AsanUnregisterGlobals,
1072 void AddressSanitizer::initializeCallbacks(
Module &M) {
1075 for (
size_t AccessIsWrite = 0; AccessIsWrite <= 1; AccessIsWrite++) {
1077 AccessSizeIndex++) {
1080 (AccessIsWrite ?
"store" :
"load") +
itostr(1 << AccessSizeIndex);
1082 AsanErrorCallback[AccessIsWrite][AccessSizeIndex] =
1084 FunctionName, IRB.
getVoidTy(), IntptrTy, NULL));
1120 bool AddressSanitizer::doInitialization(
Module &M) {
1122 TD = getAnalysisIfAvailable<DataLayout>();
1127 DynamicallyInitializedGlobals.Init(M);
1130 LongSize =
TD->getPointerSizeInBits();
1144 Mapping = getShadowMapping(M, LongSize, ZeroBaseShadow);
1145 emitShadowMapping(M, IRB);
1151 bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(
Function &
F) {
1159 if (F.
getName().
find(
" load]") != std::string::npos) {
1186 bool AddressSanitizer::InjectCoverage(
Function &F) {
1195 Load->setAlignment(1);
1208 bool AddressSanitizer::runOnFunction(
Function &F) {
1209 if (
BL->isIn(F))
return false;
1210 if (&F == AsanCtorFunction)
return false;
1212 DEBUG(
dbgs() <<
"ASAN instrumenting:\n" << F <<
"\n");
1216 maybeInsertAsanInitAtFunctionEntry(F);
1235 TempsToInstrument.
clear();
1236 int NumInsnsPerBB = 0;
1239 if (LooksLikeCodeInBug11395(BI))
return false;
1242 if (!TempsToInstrument.
insert(Addr))
1245 }
else if (isa<MemIntrinsic>(BI) &&
ClMemIntrin) {
1248 if (isa<AllocaInst>(BI))
1253 TempsToInstrument.
clear();
1254 if (CS.doesNotReturn())
1255 NoReturnCalls.
push_back(CS.getInstruction());
1266 Function *UninstrumentedDuplicate = 0;
1267 bool LikelyToInstrument =
1268 !NoReturnCalls.
empty() || !ToInstrument.
empty() || (NumAllocas > 0);
1278 int NumInstrumented = 0;
1279 for (
size_t i = 0, n = ToInstrument.
size(); i != n; i++) {
1284 instrumentMop(Inst);
1286 instrumentMemIntrinsic(cast<MemIntrinsic>(Inst));
1291 FunctionStackPoisoner FSP(F, *
this);
1292 bool ChangedStack = FSP.runOnFunction();
1296 for (
size_t i = 0, n = NoReturnCalls.
size(); i != n; i++) {
1302 bool res = NumInstrumented > 0 || ChangedStack || !NoReturnCalls.
empty();
1304 if (InjectCoverage(F))
1307 DEBUG(
dbgs() <<
"ASAN done instrumenting: " << res <<
" " << F <<
"\n");
1312 if (UninstrumentedDuplicate)
1316 assert(UninstrumentedDuplicate);
1317 UninstrumentedDuplicate->
setSection(
"NOASAN");
1327 if (ShadowRedzoneSize == 1)
return PoisonByte;
1328 if (ShadowRedzoneSize == 2)
return (PoisonByte << 8) + PoisonByte;
1329 if (ShadowRedzoneSize == 4)
1330 return (PoisonByte << 24) + (PoisonByte << 16) +
1331 (PoisonByte << 8) + (PoisonByte);
1338 size_t ShadowGranularity,
1340 for (
size_t i = 0; i < RZSize;
1341 i+= ShadowGranularity, Shadow++) {
1342 if (i + ShadowGranularity <= Size) {
1344 }
else if (i >= Size) {
1355 bool AddressSanitizer::LooksLikeCodeInBug11395(
Instruction *I) {
1356 if (LongSize != 32)
return false;
1364 void FunctionStackPoisoner::initializeCallbacks(
Module &M) {
1367 std::string Suffix =
itostr(i);
1370 IntptrTy, IntptrTy, NULL));
1373 IntptrTy, IntptrTy, NULL));
1381 void FunctionStackPoisoner::poisonRedZones(
1384 size_t ShadowRZSize = RedzoneSize() >> Mapping.Scale;
1385 assert(ShadowRZSize >= 1 && ShadowRZSize <= 4);
1400 uint64_t Pos = RedzoneSize();
1401 for (
size_t i = 0, n = AllocaVec.
size(); i < n; i++) {
1403 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
1404 uint64_t AlignedSize = getAlignedAllocaSize(AI);
1405 assert(AlignedSize - SizeInBytes < RedzoneSize());
1410 assert(ShadowBase->
getType() == IntptrTy);
1411 if (SizeInBytes < AlignedSize) {
1415 (Pos >> Mapping.Scale) - ShadowRZSize));
1416 size_t AddressableBytes = RedzoneSize() - (AlignedSize - SizeInBytes);
1417 uint32_t Poison = 0;
1421 1ULL << Mapping.Scale,
1424 ASan.TD->isLittleEndian()
1425 ? support::endian::byte_swap<uint32_t, support::little>(Poison)
1426 : support::endian::byte_swap<uint32_t, support::big>(Poison);
1435 bool LastAlloca = (i == AllocaVec.
size() - 1);
1436 Value *Poison = LastAlloca ? PoisonRight : PoisonMid;
1439 Pos += RedzoneSize();
1448 for (
int i = 0; ; i++, MaxSize *= 2)
1449 if (LocalStackSize <= MaxSize)
1459 void FunctionStackPoisoner::SetShadowToStackAfterReturnInlined(
1461 assert(!(Size % 8));
1463 for (
int i = 0; i < Size; i += 8) {
1470 void FunctionStackPoisoner::poisonStack() {
1471 uint64_t LocalStackSize = TotalStackSize +
1472 (AllocaVec.
size() + 1) * RedzoneSize();
1474 bool DoStackMalloc = ASan.CheckUseAfterReturn
1476 int StackMallocIdx = -1;
1478 assert(AllocaVec.
size() > 0);
1485 new AllocaInst(ByteArrayTy,
"MyAlloca", InsBefore);
1487 StackAlignment = RedzoneSize();
1488 MyAlloca->setAlignment(StackAlignment);
1489 assert(MyAlloca->isStaticAlloca());
1491 Value *LocalStackBase = OrigStackBase;
1493 if (DoStackMalloc) {
1507 LocalStackBase = IRBIf.CreateCall2(
1508 AsanStackMallocFunc[StackMallocIdx],
1515 LocalStackBase = Phi;
1521 StackDescription << AllocaVec.
size() <<
" ";
1524 bool HavePoisonedAllocas =
false;
1525 for (
size_t i = 0, n = AllocaPoisonCallVec.size(); i < n; i++) {
1526 const AllocaPoisonCall &APC = AllocaPoisonCallVec[i];
1527 assert(APC.InsBefore);
1530 poisonAlloca(APC.AI, APC.Size, IRB, APC.DoPoison);
1531 HavePoisonedAllocas |= APC.DoPoison;
1534 uint64_t Pos = RedzoneSize();
1536 for (
size_t i = 0, n = AllocaVec.
size(); i < n; i++) {
1538 uint64_t SizeInBytes = getAllocaSizeInBytes(AI);
1540 StackDescription << Pos <<
" " << SizeInBytes <<
" "
1541 << Name.
size() <<
" " << Name <<
" ";
1542 uint64_t AlignedSize = getAlignedAllocaSize(AI);
1543 assert((AlignedSize % RedzoneSize()) == 0);
1549 Pos += AlignedSize + RedzoneSize();
1551 assert(Pos == LocalStackSize);
1570 2 * ASan.LongSize/8)),
1575 Value *ShadowBase = ASan.memToShadow(LocalStackBase, IRB);
1576 poisonRedZones(AllocaVec, IRB, ShadowBase,
true);
1579 for (
size_t i = 0, n = RetVec.size(); i < n; i++) {
1586 poisonRedZones(AllocaVec, IRBRet, ShadowBase,
false);
1587 if (DoStackMalloc) {
1588 assert(StackMallocIdx >= 0);
1590 if (StackMallocIdx <= 4) {
1596 Value *Cmp = IRBRet.CreateICmpNE(LocalStackBase, OrigStackBase);
1601 SetShadowToStackAfterReturnInlined(IRBPoison, ShadowBase,
1602 ClassSize >> Mapping.Scale);
1603 Value *SavedFlagPtrPtr = IRBPoison.CreateAdd(
1606 Value *SavedFlagPtr = IRBPoison.CreateLoad(
1607 IRBPoison.CreateIntToPtr(SavedFlagPtrPtr, IntptrPtrTy));
1608 IRBPoison.CreateStore(
1610 IRBPoison.CreateIntToPtr(SavedFlagPtr, IRBPoison.getInt8PtrTy()));
1613 IRBRet.CreateCall3(AsanStackFreeFunc[StackMallocIdx], LocalStackBase,
1617 }
else if (HavePoisonedAllocas) {
1620 assert(LocalStackBase == OrigStackBase);
1621 poisonAlloca(LocalStackBase, LocalStackSize, IRBRet,
false);
1626 for (
size_t i = 0, n = AllocaVec.
size(); i < n; i++)
1627 AllocaVec[i]->eraseFromParent();
1630 void FunctionStackPoisoner::poisonAlloca(
Value *V, uint64_t Size,
1635 IRB.
CreateCall2(DoPoison ? AsanPoisonStackMemoryFunc
1636 : AsanUnpoisonStackMemoryFunc,
1650 if (
AllocaInst *AI = dyn_cast<AllocaInst>(V))
1652 return isInterestingAlloca(*AI) ? AI : 0;
1655 AllocaForValueMapTy::iterator I = AllocaForValue.find(V);
1656 if (I != AllocaForValue.end())
1660 AllocaForValue[V] = 0;
1664 else if (
PHINode *PN = dyn_cast<PHINode>(V)) {
1665 for (
unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
1666 Value *IncValue = PN->getIncomingValue(i);
1668 if (IncValue == PN)
continue;
1669 AllocaInst *IncValueAI = findAllocaForValue(IncValue);
1671 if (IncValueAI == 0 || (Res != 0 && IncValueAI != Res))
1677 AllocaForValue[V] = Res;
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
static cl::opt< bool > ClKeepUninstrumented("asan-keep-uninstrumented-functions", cl::desc("Keep uninstrumented copies of functions"), cl::Hidden, cl::init(false))
static cl::opt< std::string > ClDebugFunc("asan-debug-func", cl::Hidden, cl::desc("Debug func"))
static bool isValueValidForType(Type *Ty, uint64_t V)
Determine if the value is in range for the given type.
void push_back(const T &Elt)
static cl::opt< bool > ClStack("asan-stack", cl::desc("Handle stack memory"), cl::Hidden, cl::init(true))
LinkageTypes getLinkage() const
void ReplaceInstWithInst(BasicBlock::InstListType &BIL, BasicBlock::iterator &BI, Instruction *I)
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
LoadInst * CreateLoad(Value *Ptr, const char *Name)
void addIncoming(Value *V, BasicBlock *BB)
Base class for instruction visitors.
static cl::opt< int > ClMappingScale("asan-mapping-scale", cl::desc("scale of asan shadow mapping"), cl::Hidden, cl::init(0))
size_t size() const
size - Get the string size.
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
The main container class for the LLVM Intermediate Representation.
unsigned getAlignment() const
Intrinsic::ID getIntrinsicID() const
static const int kAsanStackLeftRedzoneMagic
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Available for inspection, not emission.
unsigned getNumOperands() const
getNumOperands - Return number of MDNode operands.
size_t find(char C, size_t From=0) const
void appendToGlobalCtors(Module &M, Function *F, int Priority)
static Constant * getGetElementPtr(Constant *C, ArrayRef< Constant * > IdxList, bool InBounds=false)
static const uintptr_t kCurrentStackFrameMagic
static PointerType * get(Type *ElementType, unsigned AddressSpace)
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
Like Internal, but omit from symbol table.
static SpecialCaseList * createOrDie(const StringRef Path)
Externally visible function.
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
static const char *const kAsanMappingScaleName
static cl::opt< int > ClDebug("asan-debug", cl::desc("debug"), cl::Hidden, cl::init(0))
void setSection(StringRef S)
const Function * getParent() const
Return the enclosing method, or null if none.
static const int kAsanStackPartialRedzoneMagic
MDNode - a tuple of other values.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
const Constant * getInitializer() const
const std::string & getTargetTriple() const
void setDebugLoc(const DebugLoc &Loc)
setDebugLoc - Set the debug location information for this instruction.
bool isMinusOne() const
Determine if the value is all ones.
static const char *const kAsanMappingOffsetName
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
LoopInfoBase< BlockT, LoopT > * LI
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
static Constant * getNullValue(Type *Ty)
StringRef getName() const
Value * getOperand(unsigned i) const LLVM_READONLY
getOperand - Return specified operand.
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
bool isArrayAllocation() const
static const uint64_t kDefaultShadowScale
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
static bool GlobalWasGeneratedByAsan(GlobalVariable *G)
void push_back(NodeTy *val)
void dump() const
dump - Support for debugging, callable in GDB: V->dump()
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Base class of casting instructions.
const APInt & getValue() const
Return the constant's value.
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
#define llvm_unreachable(msg)
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
static cl::opt< int > ClDebugMax("asan-debug-max", cl::desc("Debug man inst"), cl::Hidden, cl::init(-1))
unsigned getNumArgOperands() const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=0)
Type * getAllocatedType() const
void setName(const Twine &Name)
static const char *const kAsanModuleCtorName
ID
LLVM Calling Convention Representation.
const std::string & getModuleIdentifier() const
Type * getVoidTy()
Fetch the type representing void.
static cl::opt< bool > ClInitializers("asan-initialization-order", cl::desc("Handle C++ initializer order"), cl::Hidden, cl::init(false))
bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress, DIBuilder &Builder)
global_iterator global_begin()
static cl::opt< std::string > ClBlacklistFile("asan-blacklist", cl::desc("File containing the list of objects to ignore ""during instrumentation"), cl::Hidden)
static const char *const kAsanPoisonStackMemoryName
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
bool LLVM_ATTRIBUTE_UNUSED_RESULT empty() const
enable_if_c< std::numeric_limits< T >::is_integer &&!std::numeric_limits< T >::is_signed, std::size_t >::type countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
static const int kMaxAsanStackMallocSizeClass
static cl::opt< bool > ClOptSameTemp("asan-opt-same-temp", cl::desc("Instrument the same temp just once"), cl::Hidden, cl::init(true))
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
static cl::opt< bool > ClOpt("asan-opt", cl::desc("Optimize instrumentation"), cl::Hidden, cl::init(true))
ModulePass * createAddressSanitizerModulePass(bool CheckInitOrder=true, StringRef BlacklistFile=StringRef(), bool ZeroBaseShadow=false)
static cl::opt< bool > ClCoverage("asan-coverage", cl::desc("ASan coverage"), cl::Hidden, cl::init(false))
void replaceAllUsesWith(Value *V)
static cl::opt< bool > ClAlwaysSlowPath("asan-always-slow-path", cl::desc("use instrumentation with slow path for all accesses"), cl::Hidden, cl::init(false))
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Type * getElementType() const
size_t size() const
size - Get the array size.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
static const uint64_t kDefaultShadowOffset32
Function * getFunction(StringRef Name) const
static cl::opt< bool > ClInstrumentWrites("asan-instrument-writes", cl::desc("instrument write instructions"), cl::Hidden, cl::init(true))
static const size_t kNumberOfAccessSizes
Same, but only replaced by something equivalent.
initializer< Ty > init(const Ty &Val)
* if(!EatIfPresent(lltok::kw_thread_local)) return false
static cl::opt< bool > ClUseAfterReturn("asan-use-after-return", cl::desc("Check return-after-free"), cl::Hidden, cl::init(false))
Value * CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name="")
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
LLVM Basic Block Representation.
TerminatorInst * SplitBlockAndInsertIfThen(Instruction *Cmp, bool Unreachable, MDNode *BranchWeights=0)
static cl::opt< bool > ClMemIntrin("asan-memintrin", cl::desc("Handle memset/memcpy/memmove"), cl::Hidden, cl::init(true))
BasicBlock * getSuccessor(unsigned idx) const
Constant * getOrInsertGlobal(StringRef Name, Type *Ty)
df_iterator< T > df_end(const T &G)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
static const size_t kMinStackMallocSize
LLVM Constant Representation.
PointerType * getType() const
static const char *const kAsanReportStoreN
static const char *const kAsanInitName
static const char *const kAsanStackFreeNameTemplate
static const uint64_t kMIPS32_ShadowOffset32
static Constant * get(ArrayType *T, ArrayRef< Constant * > V)
unsigned getAlignment() const
static Function * checkInterfaceFunction(Constant *FuncOrBitcast)
const DebugLoc & getDebugLoc() const
getDebugLoc - Return the debug location for this node as a DebugLoc.
static cl::opt< bool > ClInstrumentReads("asan-instrument-reads", cl::desc("instrument read instructions"), cl::Hidden, cl::init(true))
static Type * getVoidTy(LLVMContext &C)
static const int kAsanStackAfterReturnMagic
MDNode * getOperand(unsigned i) const
getOperand - Return specified operand.
Value * getOperand(unsigned i) const
static cl::opt< bool > ClOptGlobals("asan-opt-globals", cl::desc("Don't instrument scalar globals"), cl::Hidden, cl::init(true))
static const uintptr_t kRetiredStackFrameMagic
static Constant * get(StructType *T, ArrayRef< Constant * > V)
static cl::opt< bool > ClRealignStack("asan-realign-stack", cl::desc("Realign stack to 32"), cl::Hidden, cl::init(true))
static const char *const kAsanGenPrefix
const std::string & getSection() const
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 std::string itostr(int64_t X)
static cl::opt< bool > ClGlobals("asan-globals", cl::desc("Handle global objects"), cl::Hidden, cl::init(true))
void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope=CrossThread)
PointerType * getPointerTo(unsigned AddrSpace=0)
void appendToGlobalDtors(Module &M, Function *F, int Priority)
Same as appendToGlobalCtors(), but for global dtors.
static const char *const kAsanRegisterGlobalsName
static const char *const Magic
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=0)
global_iterator global_end()
const FunctionListType & getFunctionList() const
Get the Module's list of functions (constant).
static Constant * getPointerCast(Constant *C, Type *Ty)
Create a BitCast or a PtrToInt cast constant expression.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
Get or create an IntegerType instance.
Class for constant integers.
static const char *const kAsanStackMallocNameTemplate
static const char *const kAsanUnpoisonStackMemoryName
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
void setAlignment(unsigned Align)
static size_t TypeSizeToSizeIndex(uint32_t TypeSize)
bool isStaticAlloca() const
void copyAttributesFrom(const GlobalValue *Src)
void setUnnamedAddr(bool Val)
static const uint64_t kDefaultShadowOffset64
Value * getLength() const
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static cl::opt< int > ClDebugStack("asan-debug-stack", cl::desc("debug stack"), cl::Hidden, cl::init(0))
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
const BasicBlock & getEntryBlock() const
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
df_iterator< T > df_begin(const T &G)
Value * getArgOperand(unsigned i) const
static cl::opt< bool > ClShort64BitOffset("asan-short-64bit-mapping-offset", cl::desc("Use short immediate constant as the mapping offset for 64bit"), cl::Hidden, cl::init(true))
static const char *const kAsanReportLoadN
bool hasInitializer() const
LinkageTypes
An enumeration for the kinds of linkage for global values.
static cl::opt< bool > ClCheckLifetime("asan-check-lifetime", cl::desc("Use llvm.lifetime intrinsics to insert extra checks"), cl::Hidden, cl::init(false))
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
static const int kAsanStackMidRedzoneMagic
static const int kAsanStackRightRedzoneMagic
bool isInlineAsm() const
isInlineAsm - Check if this call is an inline asm statement.
FunctionPass * createAddressSanitizerFunctionPass(bool CheckInitOrder=true, bool CheckUseAfterReturn=false, bool CheckLifetime=false, StringRef BlacklistFile=StringRef(), bool ZeroBaseShadow=false)
static const uint64_t kDefaultShort64bitShadowOffset
bool isGEPWithNoNotionalOverIndexing() const
Return true if this is a getelementptr expression and all the index operands are compile-time known i...
STATISTIC(NumInstrumentedReads,"Number of instrumented reads")
Value * getSource() const
PointerType * getType() const
getType - Global values are always pointers.
static cl::opt< int > ClDebugMin("asan-debug-min", cl::desc("Debug min inst"), cl::Hidden, cl::init(-1))
NamedMDNode * getNamedMetadata(const Twine &Name) const
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
static int StackMallocSizeClass(uint64_t LocalStackSize)
void removeFnAttr(Attribute::AttrKind N)
Remove function attributes from this function.
static GlobalVariable * createPrivateGlobalForString(Module &M, StringRef Str)
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
static Value * isInterestingMemoryAccess(Instruction *I, bool *IsWrite)
Function * CloneFunction(const Function *F, ValueToValueMapTy &VMap, bool ModuleLevelChanges, ClonedCodeInfo *CodeInfo=0)
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=0, BasicBlock *InsertBefore=0)
Creates a new BasicBlock.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
INITIALIZE_PASS(AddressSanitizer,"asan","AddressSanitizer: detects use-after-free and out-of-bounds bugs.", false, false) FunctionPass *llvm
Rename collisions when linking (static functions).
static const char *const kAsanOptionDetectUAR
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
virtual void eraseFromParent()
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
static ReturnInst * Create(LLVMContext &C, Value *retVal=0, Instruction *InsertBefore=0)
static const char *const kAsanModuleDtorName
static void PoisonShadowPartialRightRedzone(uint8_t *Shadow, size_t Size, size_t RZSize, size_t ShadowGranularity, uint8_t Magic)
EnvironmentType getEnvironment() const
getEnvironment - Get the parsed environment type of this triple.
static const char *const kAsanUnregisterGlobalsName
static const char *const kAsanUnpoisonGlobalsName
CallInst * CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, const Twine &Name="")
static const char *const kAsanPoisonGlobalsName
LLVM Value Representation.
void setAlignment(unsigned Align)
static const uint64_t kPPC64_ShadowOffset64
CallInst * CreateCall(Value *Callee, const Twine &Name="")
static cl::opt< bool > ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true))
static const Function * getParent(const Value *V)
unsigned getNumOperands() const
getNumOperands - Return the number of NamedMDNode operands.
static const char *const kAsanHandleNoReturnName
static const size_t kMaxStackMallocSize
static cl::opt< int > ClMappingOffsetLog("asan-mapping-offset-log", cl::desc("offset of asan shadow mapping"), cl::Hidden, cl::init(-1))
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
static const int kAsanCtorAndCtorPriority
LLVMContext & getContext() const
static const char *const kAsanCovName
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, const Twine &N="", Module *M=0)
static uint64_t ValueForPoison(uint64_t PoisonByte, size_t ShadowRedzoneSize)
static const char *const kAsanReportErrorTemplate