96 #define DEBUG_TYPE "msan"
123 using namespace llvm;
137 cl::desc(
"Track origins (allocation sites) of poisoned memory"),
140 cl::desc(
"keep going after reporting a UMR"),
143 cl::desc(
"poison uninitialized stack variables"),
146 cl::desc(
"poison uninitialized stack variables with a call"),
149 cl::desc(
"poison uninitialized stack variables with the given patter"),
156 cl::desc(
"propagate shadow through ICmpEQ and ICmpNE"),
160 cl::desc(
"exact handling of relational integer ICmp"),
164 cl::desc(
"store origin for clean (fully initialized) values"),
174 cl::desc(
"report accesses through a pointer which has poisoned shadow"),
178 cl::desc(
"print out instructions with default strict semantics"),
182 cl::desc(
"File containing the list of functions where MemorySanitizer "
190 cl::desc(
"Wrap indirect calls with a given function"),
194 cl::desc(
"Do not wrap indirect calls with target in the same module"),
206 MemorySanitizer(
bool TrackOrigins =
false,
212 BlacklistFile(BlacklistFile.empty() ?
ClBlacklistFile : BlacklistFile),
214 const char *getPassName()
const {
return "MemorySanitizer"; }
216 bool doInitialization(
Module &M);
220 void initializeCallbacks(
Module &M);
253 Value *MsanCopyOriginFn;
256 Value *MsanSetAllocaOrigin4Fn;
258 Value *MsanPoisonStackFn;
260 Value *MemmoveFn, *MemcpyFn, *MemsetFn;
267 uint64_t OriginOffset;
271 MDNode *OriginStoreWeights;
279 bool WrapIndirectCalls;
281 Value *IndirectCallWrapperFn;
283 Type *AnyFunctionPtrTy;
285 friend struct MemorySanitizerVisitor;
286 friend struct VarArgAMD64Helper;
292 "MemorySanitizer: detects uninitialized reads.",
297 return new MemorySanitizer(TrackOrigins, BlacklistFile);
314 void MemorySanitizer::initializeCallbacks(
Module &M) {
324 :
"__msan_warning_noreturn";
328 "__msan_copy_origin", IRB.getVoidTy(), IRB.getInt8PtrTy(),
329 IRB.getInt8PtrTy(), IntptrTy, NULL);
331 "__msan_set_alloca_origin4", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy,
332 IRB.getInt8PtrTy(), IntptrTy, NULL);
334 "__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, NULL);
336 "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
337 IRB.getInt8PtrTy(), IntptrTy, NULL);
339 "__msan_memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(),
342 "__msan_memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(),
368 "__msan_va_arg_overflow_size_tls", 0,
379 if (WrapIndirectCalls) {
389 0,
"__executable_start");
401 bool MemorySanitizer::doInitialization(
Module &M) {
402 TD = getAnalysisIfAvailable<DataLayout>();
407 unsigned PtrSize =
TD->getPointerSizeInBits(0);
423 IntptrTy = IRB.getIntPtrTy(
TD);
424 OriginTy = IRB.getInt32Ty();
431 "__msan_init", IRB.getVoidTy(), NULL)), 0);
435 IRB.getInt32(TrackOrigins),
"__msan_track_origins");
454 struct VarArgHelper {
468 virtual void finalizeInstrumentation() = 0;
470 virtual ~VarArgHelper() {}
473 struct MemorySanitizerVisitor;
476 CreateVarArgHelper(
Function &
Func, MemorySanitizer &Msan,
477 MemorySanitizerVisitor &Visitor);
485 struct MemorySanitizerVisitor :
public InstVisitor<MemorySanitizerVisitor> {
498 bool CheckReturnValue;
500 struct ShadowOriginAndInsertPoint {
505 : Shadow(S), Origin(O), OrigIns(I) { }
506 ShadowOriginAndInsertPoint() : Shadow(0), Origin(0), OrigIns(0) { }
512 MemorySanitizerVisitor(
Function &
F, MemorySanitizer &MS)
513 : F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) {
515 AttributeSet::FunctionIndex,
517 InsertChecks = SanitizeFunction;
518 LoadShadow = SanitizeFunction;
523 CheckReturnValue = SanitizeFunction && (F.
getName() ==
"main");
525 DEBUG(
if (!InsertChecks)
526 dbgs() <<
"MemorySanitizer is not inserting checks into '"
530 void materializeStores() {
531 for (
size_t i = 0, n = StoreList.size(); i < n; i++) {
537 Value *Shadow = I.
isAtomic() ? getCleanShadow(Val) : getShadow(Val);
538 Value *ShadowPtr = getShadowPtr(Addr, Shadow->
getType(), IRB);
541 IRB.CreateAlignedStore(Shadow, ShadowPtr, I.
getAlignment());
542 DEBUG(
dbgs() <<
" STORE: " << *NewSI <<
"\n");
546 insertShadowCheck(Addr, &I);
551 if (MS.TrackOrigins) {
554 IRB.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRB),
557 Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB);
562 if (isa<Constant>(ConvertedShadow))
565 Value *Cmp = IRB.CreateICmpNE(ConvertedShadow,
566 getCleanShadow(ConvertedShadow),
"_mscmp");
569 MS.OriginStoreWeights);
571 IRBNew.CreateAlignedStore(getOrigin(Val), getOriginPtr(Addr, IRBNew),
578 void materializeChecks() {
579 for (
size_t i = 0, n = InstrumentationList.size(); i < n; i++) {
580 Value *Shadow = InstrumentationList[i].Shadow;
581 Instruction *OrigIns = InstrumentationList[i].OrigIns;
583 DEBUG(
dbgs() <<
" SHAD0 : " << *Shadow <<
"\n");
584 Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB);
585 DEBUG(
dbgs() <<
" SHAD1 : " << *ConvertedShadow <<
"\n");
587 if (isa<Constant>(ConvertedShadow))
589 Value *Cmp = IRB.CreateICmpNE(ConvertedShadow,
590 getCleanShadow(ConvertedShadow),
"_mscmp");
596 IRB.SetInsertPoint(CheckTerm);
597 if (MS.TrackOrigins) {
598 Value *Origin = InstrumentationList[i].Origin;
599 IRB.CreateStore(Origin ? (
Value*)Origin : (
Value*)IRB.getInt32(0),
604 IRB.CreateCall(MS.EmptyAsm);
605 DEBUG(
dbgs() <<
" CHECK: " << *Cmp <<
"\n");
610 void materializeIndirectCalls() {
611 for (
size_t i = 0, n = IndirectCallList.size(); i < n; i++) {
617 Value *Fn = IRB.CreateBitCast(Fn0, MS.AnyFunctionPtrTy);
622 IRB.CreateBitCast(MS.MsandrModuleStart, MS.AnyFunctionPtrTy);
623 Value *End = IRB.CreateBitCast(MS.MsandrModuleEnd, MS.AnyFunctionPtrTy);
625 Value *NotInThisModule = IRB.CreateOr(IRB.CreateICmpULT(Fn, Start),
626 IRB.CreateICmpUGE(Fn, End));
629 IRB.CreatePHI(Fn0->
getType(), 2,
"msandr.indirect_target");
632 cast<Instruction>(NotInThisModule),
633 false, MS.ColdCallWeights);
635 IRB.SetInsertPoint(CheckTerm);
638 Value *NewFn = IRB.CreateBitCast(
639 IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->
getType());
645 Value *NewFn = IRB.CreateBitCast(
646 IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->
getType());
653 bool runOnFunction() {
655 if (!MS.TD)
return false;
673 for (
size_t i = 0, n = ShadowPHINodes.size(); i < n; i++) {
674 PHINode *PN = ShadowPHINodes[i];
675 PHINode *PNS = cast<PHINode>(getShadow(PN));
676 PHINode *PNO = MS.TrackOrigins ? cast<PHINode>(getOrigin(PN)) : 0;
678 for (
size_t v = 0; v < NumValues; v++) {
685 VAHelper->finalizeInstrumentation();
695 materializeIndirectCalls();
702 return getShadowTy(V->
getType());
714 if (
VectorType *VT = dyn_cast<VectorType>(OrigTy)) {
715 uint32_t EltSize = MS.TD->getTypeSizeInBits(VT->getElementType());
717 VT->getNumElements());
721 for (
unsigned i = 0, n =
ST->getNumElements(); i < n; i++)
722 Elements.
push_back(getShadowTy(
ST->getElementType(i)));
724 DEBUG(
dbgs() <<
"getShadowTy: " << *
ST <<
" ===> " << *Res <<
"\n");
727 uint32_t TypeSize = MS.TD->getTypeSizeInBits(OrigTy);
733 if (
VectorType *vt = dyn_cast<VectorType>(ty))
741 Type *NoVecTy = getShadowTyNoVec(Ty);
742 if (Ty == NoVecTy)
return V;
788 if (!MS.TrackOrigins)
return 0;
805 return MS.RetvalOriginTLS;
810 assert(!ShadowMap.count(V) &&
"Values may only have one shadow");
816 if (!MS.TrackOrigins)
return;
817 assert(!OriginMap.count(V) &&
"Values may only have one origin");
818 DEBUG(
dbgs() <<
"ORIGIN: " << *V <<
" ==> " << *Origin <<
"\n");
819 OriginMap[V] = Origin;
827 Type *ShadowTy = getShadowTy(V);
836 if (isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy))
847 Type *ShadowTy = getShadowTy(V);
850 return getPoisonedShadow(ShadowTy);
854 Value *getCleanOrigin() {
865 Value *Shadow = ShadowMap[V];
869 assert(Shadow &&
"No shadow for a value");
873 if (
UndefValue *U = dyn_cast<UndefValue>(V)) {
874 Value *AllOnes = PoisonUndef ? getPoisonedShadow(V) : getCleanShadow(V);
875 DEBUG(
dbgs() <<
"Undef: " << *U <<
" ==> " << *AllOnes <<
"\n");
879 if (
Argument *A = dyn_cast<Argument>(V)) {
881 Value **ShadowPtr = &ShadowMap[V];
886 unsigned ArgOffset = 0;
889 if (!AI->getType()->isSized()) {
893 unsigned Size = AI->hasByValAttr()
894 ? MS.TD->getTypeAllocSize(AI->getType()->getPointerElementType())
895 : MS.TD->getTypeAllocSize(AI->getType());
897 Value *Base = getShadowPtrForArgument(AI, EntryIRB, ArgOffset);
898 if (AI->hasByValAttr()) {
902 unsigned ArgAlign = AI->getParamAlignment();
905 ArgAlign = MS.TD->getABITypeAlignment(EltType);
908 Value *Cpy = EntryIRB.CreateMemCpy(
909 getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB), Base, Size,
911 DEBUG(
dbgs() <<
" ByValCpy: " << *Cpy <<
"\n");
913 *ShadowPtr = getCleanShadow(V);
917 DEBUG(
dbgs() <<
" ARG: " << *AI <<
" ==> " <<
918 **ShadowPtr <<
"\n");
919 if (MS.TrackOrigins) {
920 Value* OriginPtr = getOriginPtrForArgument(AI, EntryIRB, ArgOffset);
921 setOrigin(A, EntryIRB.CreateLoad(OriginPtr));
926 assert(*ShadowPtr &&
"Could not find shadow for an argument");
930 return getCleanShadow(V);
940 if (!MS.TrackOrigins)
return 0;
941 if (isa<Instruction>(V) || isa<Argument>(V)) {
942 Value *Origin = OriginMap[V];
944 DEBUG(
dbgs() <<
"NO ORIGIN: " << *V <<
"\n");
945 Origin = getCleanOrigin();
949 return getCleanOrigin();
963 if (!InsertChecks)
return;
966 assert((isa<IntegerType>(ShadowTy) || isa<VectorType>(ShadowTy)) &&
967 "Can only insert checks for integer and vector shadow types");
969 InstrumentationList.push_back(
970 ShadowOriginAndInsertPoint(Shadow, Origin, OrigIns));
979 Instruction *Shadow = dyn_cast_or_null<Instruction>(getShadow(Val));
981 Instruction *Origin = dyn_cast_or_null<Instruction>(getOrigin(Val));
982 insertShadowCheck(Shadow, Origin, OrigIns);
1028 Type *ShadowTy = getShadowTy(&I);
1031 Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
1035 setShadow(&I, getCleanShadow(&I));
1044 if (MS.TrackOrigins) {
1050 setOrigin(&I, getCleanOrigin());
1060 StoreList.push_back(&I);
1064 assert(isa<AtomicRMWInst>(I) || isa<AtomicCmpXchgInst>(I));
1068 Value *ShadowPtr = getShadowPtr(Addr, I.
getType(), IRB);
1071 insertShadowCheck(Addr, &I);
1076 if (isa<AtomicCmpXchgInst>(I))
1081 setShadow(&I, getCleanShadow(&I));
1100 setOrigin(&I, getOrigin(&I, 0));
1108 setOriginForNaryOp(I);
1116 setOriginForNaryOp(I);
1123 setOrigin(&I, getOrigin(&I, 0));
1129 setOrigin(&I, getOrigin(&I, 0));
1135 setOrigin(&I, getOrigin(&I, 0));
1140 setShadow(&I, IRB.
CreateBitCast(getShadow(&I, 0), getShadowTy(&I)));
1141 setOrigin(&I, getOrigin(&I, 0));
1146 setShadow(&I, IRB.
CreateIntCast(getShadow(&I, 0), getShadowTy(&I),
false,
1147 "_msprop_ptrtoint"));
1148 setOrigin(&I, getOrigin(&I, 0));
1153 setShadow(&I, IRB.
CreateIntCast(getShadow(&I, 0), getShadowTy(&I),
false,
1154 "_msprop_inttoptr"));
1155 setOrigin(&I, getOrigin(&I, 0));
1158 void visitFPToSIInst(
CastInst& I) { handleShadowOr(I); }
1159 void visitFPToUIInst(
CastInst& I) { handleShadowOr(I); }
1160 void visitSIToFPInst(
CastInst& I) { handleShadowOr(I); }
1161 void visitUIToFPInst(
CastInst& I) { handleShadowOr(I); }
1162 void visitFPExtInst(
CastInst& I) { handleShadowOr(I); }
1163 void visitFPTruncInst(
CastInst& I) { handleShadowOr(I); }
1177 Value *S1 = getShadow(&I, 0);
1178 Value *S2 = getShadow(&I, 1);
1189 setOriginForNaryOp(I);
1199 Value *S1 = getShadow(&I, 0);
1200 Value *S2 = getShadow(&I, 1);
1211 setOriginForNaryOp(I);
1229 template <
bool CombineShadow>
1234 MemorySanitizerVisitor *MSV;
1237 Combiner(MemorySanitizerVisitor *MSV,
IRBuilder<> &IRB) :
1238 Shadow(0), Origin(0), IRB(IRB), MSV(MSV) {}
1241 Combiner &Add(
Value *OpShadow,
Value *OpOrigin) {
1242 if (CombineShadow) {
1247 OpShadow = MSV->CreateShadowCast(IRB, OpShadow, Shadow->
getType());
1248 Shadow = IRB.
CreateOr(Shadow, OpShadow,
"_msprop");
1252 if (MSV->MS.TrackOrigins) {
1257 Value *FlatShadow = MSV->convertToShadowTyNoVec(OpShadow, IRB);
1259 MSV->getCleanShadow(FlatShadow));
1267 Combiner &Add(
Value *V) {
1268 Value *OpShadow = MSV->getShadow(V);
1269 Value *OpOrigin = MSV->MS.TrackOrigins ? MSV->getOrigin(V) : 0;
1270 return Add(OpShadow, OpOrigin);
1276 if (CombineShadow) {
1278 Shadow = MSV->CreateShadowCast(IRB, Shadow, MSV->getShadowTy(I));
1279 MSV->setShadow(I, Shadow);
1281 if (MSV->MS.TrackOrigins) {
1283 MSV->setOrigin(I, Origin);
1288 typedef Combiner<true> ShadowAndOriginCombiner;
1289 typedef Combiner<false> OriginCombiner;
1293 if (!MS.TrackOrigins)
return;
1295 OriginCombiner
OC(
this, IRB);
1301 size_t VectorOrPrimitiveTypeSizeInBits(
Type *Ty) {
1303 "Vector of pointers is not a valid shadow type");
1319 size_t srcSizeInBits = VectorOrPrimitiveTypeSizeInBits(srcTy);
1320 size_t dstSizeInBits = VectorOrPrimitiveTypeSizeInBits(dstTy);
1331 ShadowAndOriginCombiner
SC(
this, IRB);
1349 setShadow(&I, getShadow(&I, 0));
1350 setOrigin(&I, getOrigin(&I, 0));
1364 void handleEqualityComparison(
ICmpInst &I) {
1368 Value *Sa = getShadow(A);
1369 Value *Sb = getShadow(B);
1395 setOriginForNaryOp(I);
1437 void handleRelationalComparisonExact(
ICmpInst &I) {
1441 Value *Sa = getShadow(A);
1442 Value *Sb = getShadow(B);
1455 getLowestPossibleValue(IRB, A, Sa, IsSigned),
1456 getHighestPossibleValue(IRB, B, Sb, IsSigned));
1458 getHighestPossibleValue(IRB, A, Sa, IsSigned),
1459 getLowestPossibleValue(IRB, B, Sb, IsSigned));
1462 setOriginForNaryOp(I);
1470 void handleSignedRelationalComparison(
ICmpInst &I) {
1478 }
else if (constOp1 && constOp1->isNullValue() &&
1485 IRB.
CreateICmpSLT(getShadow(op), getCleanShadow(op),
"_msprop_icmpslt");
1486 setShadow(&I, Shadow);
1487 setOrigin(&I, getOrigin(op));
1499 handleEqualityComparison(I);
1505 handleRelationalComparisonExact(I);
1509 handleSignedRelationalComparison(I);
1515 handleRelationalComparisonExact(I);
1530 Value *S1 = getShadow(&I, 0);
1531 Value *S2 = getShadow(&I, 1);
1536 setShadow(&I, IRB.
CreateOr(Shift, S2Conv));
1537 setOriginForNaryOp(I);
1590 VAHelper->visitVAStartInst(I);
1594 VAHelper->visitVACopyInst(I);
1597 enum IntrinsicKind {
1598 IK_DoesNotAccessMemory,
1604 const int DoesNotAccessMemory = IK_DoesNotAccessMemory;
1605 const int OnlyReadsArgumentPointees = IK_OnlyReadsMemory;
1606 const int OnlyReadsMemory = IK_OnlyReadsMemory;
1607 const int OnlyAccessesArgumentPointees = IK_WritesMemory;
1608 const int UnknownModRefBehavior = IK_WritesMemory;
1609 #define GET_INTRINSIC_MODREF_BEHAVIOR
1610 #define ModRefBehavior IntrinsicKind
1611 #include "llvm/IR/Intrinsics.gen"
1612 #undef ModRefBehavior
1613 #undef GET_INTRINSIC_MODREF_BEHAVIOR
1623 Value *Shadow = getShadow(&I, 1);
1624 Value *ShadowPtr = getShadowPtr(Addr, Shadow->
getType(), IRB);
1631 insertShadowCheck(Addr, &I);
1635 if (MS.TrackOrigins)
1636 IRB.
CreateStore(getOrigin(&I, 1), getOriginPtr(Addr, IRB));
1648 Type *ShadowTy = getShadowTy(&I);
1650 Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
1655 setShadow(&I, getCleanShadow(&I));
1659 insertShadowCheck(Addr, &I);
1661 if (MS.TrackOrigins) {
1663 setOrigin(&I, IRB.
CreateLoad(getOriginPtr(Addr, IRB)));
1665 setOrigin(&I, getCleanOrigin());
1685 for (
unsigned i = 0; i < NumArgOperands; ++i) {
1692 ShadowAndOriginCombiner
SC(
this, IRB);
1693 for (
unsigned i = 0; i < NumArgOperands; ++i)
1712 if (NumArgOperands == 0)
1716 IntrinsicKind IK = getIntrinsicKind(iid);
1717 bool OnlyReadsMemory = IK == IK_OnlyReadsMemory;
1718 bool WritesMemory = IK == IK_WritesMemory;
1719 assert(!(OnlyReadsMemory && WritesMemory));
1721 if (NumArgOperands == 2 &&
1727 return handleVectorStoreIntrinsic(I);
1730 if (NumArgOperands == 1 &&
1735 return handleVectorLoadIntrinsic(I);
1738 if (!OnlyReadsMemory && !WritesMemory)
1739 if (maybeHandleSimpleNomemIntrinsic(I))
1752 setShadow(&I, IRB.
CreateCall(BswapFunc, getShadow(Op)));
1753 setOrigin(&I, getOrigin(Op));
1771 void handleVectorConvertIntrinsic(
IntrinsicInst &I,
int NumUsedElements) {
1773 Value *CopyOp, *ConvertOp;
1795 Value *ConvertShadow = getShadow(ConvertOp);
1796 Value *AggShadow = 0;
1800 for (
int i = 1; i < NumUsedElements; ++i) {
1803 AggShadow = IRB.
CreateOr(AggShadow, MoreShadow);
1806 AggShadow = ConvertShadow;
1809 insertShadowCheck(AggShadow, getOrigin(ConvertOp), &I);
1816 Value *ResultShadow = getShadow(CopyOp);
1818 for (
int i = 0; i < NumUsedElements; ++i) {
1823 setShadow(&I, ResultShadow);
1824 setOrigin(&I, getOrigin(CopyOp));
1826 setShadow(&I, getCleanShadow(&I));
1861 handleVectorConvertIntrinsic(I, 1);
1867 handleVectorConvertIntrinsic(I, 2);
1870 if (!handleUnknownIntrinsic(I))
1871 visitInstruction(I);
1878 assert((CS.
isCall() || CS.
isInvoke()) &&
"Unknown type of CallSite");
1886 visitInstruction(I);
1896 assert(!isa<IntrinsicInst>(&I) &&
"intrinsics are handled elsewhere");
1907 Func->removeAttributes(AttributeSet::FunctionIndex,
1908 AttributeSet::get(
Func->getContext(),
1909 AttributeSet::FunctionIndex,
1916 IndirectCallList.push_back(CS);
1918 unsigned ArgOffset = 0;
1919 DEBUG(
dbgs() <<
" CallSite: " << I <<
"\n");
1921 ArgIt != End; ++ArgIt) {
1925 DEBUG(
dbgs() <<
"Arg " << i <<
" is not sized: " << I <<
"\n");
1933 Value *ArgShadow = getShadow(A);
1934 Value *ArgShadowBase = getShadowPtrForArgument(A, IRB, ArgOffset);
1935 DEBUG(
dbgs() <<
" Arg#" << i <<
": " << *A <<
1936 " Shadow: " << *ArgShadow <<
"\n");
1939 "ByVal argument is not a pointer!");
1946 Size = MS.TD->getTypeAllocSize(A->
getType());
1950 if (MS.TrackOrigins)
1952 getOriginPtrForArgument(A, IRB, ArgOffset));
1954 assert(Size != 0 && Store != 0);
1955 DEBUG(
dbgs() <<
" Param:" << *Store <<
"\n");
1958 DEBUG(
dbgs() <<
" done with call args\n");
1963 VAHelper->visitCallSite(CS, IRB);
1970 Value *Base = getShadowPtrForRetval(&I, IRBBefore);
1976 BasicBlock *NormalDest = cast<InvokeInst>(&
I)->getNormalDest();
1981 setShadow(&I, getCleanShadow(&I));
1982 setOrigin(&I, getCleanOrigin());
1987 "Could not find insertion point for retval shadow load");
1990 Value *RetvalShadow =
1991 IRBAfter.CreateAlignedLoad(getShadowPtrForRetval(&I, IRBAfter),
1993 setShadow(&I, RetvalShadow);
1994 if (MS.TrackOrigins)
1995 setOrigin(&I, IRBAfter.CreateLoad(getOriginPtrForRetval(IRBAfter)));
2001 if (!RetVal)
return;
2002 Value *ShadowPtr = getShadowPtrForRetval(RetVal, IRB);
2003 if (CheckReturnValue) {
2004 insertShadowCheck(RetVal, &I);
2005 Value *Shadow = getCleanShadow(RetVal);
2008 Value *Shadow = getShadow(RetVal);
2011 if (MS.TrackOrigins)
2012 IRB.
CreateStore(getOrigin(RetVal), getOriginPtrForRetval(IRB));
2016 void visitPHINode(
PHINode &I) {
2018 ShadowPHINodes.push_back(&I);
2021 if (MS.TrackOrigins)
2027 setShadow(&I, getCleanShadow(&I));
2040 if (PoisonStack && MS.TrackOrigins) {
2041 setOrigin(&I, getCleanOrigin());
2052 StackDescription.str());
2072 getPoisonedShadow(getShadowTy(I.
getType())), S,
2073 "_msprop_select_agg");
2081 if (MS.TrackOrigins) {
2086 Value *ConvertedShadow = convertToShadowTyNoVec(Cond, IRB);
2088 getCleanShadow(ConvertedShadow),
"_mso_select");
2098 setShadow(&I, getCleanShadow(&I));
2099 setOrigin(&I, getCleanOrigin());
2109 DEBUG(
dbgs() <<
"ExtractValue: " << I <<
"\n");
2110 Value *AggShadow = getShadow(Agg);
2111 DEBUG(
dbgs() <<
" AggShadow: " << *AggShadow <<
"\n");
2113 DEBUG(
dbgs() <<
" ResShadow: " << *ResShadow <<
"\n");
2114 setShadow(&I, ResShadow);
2115 setOriginForNaryOp(I);
2120 DEBUG(
dbgs() <<
"InsertValue: " << I <<
"\n");
2123 DEBUG(
dbgs() <<
" AggShadow: " << *AggShadow <<
"\n");
2124 DEBUG(
dbgs() <<
" InsShadow: " << *InsShadow <<
"\n");
2126 DEBUG(
dbgs() <<
" Res: " << *Res <<
"\n");
2128 setOriginForNaryOp(I);
2132 if (
CallInst *CI = dyn_cast<CallInst>(&I)) {
2133 errs() <<
"ZZZ call " << CI->getCalledFunction()->getName() <<
"\n";
2137 errs() <<
"QQQ " << I <<
"\n";
2141 DEBUG(
dbgs() <<
"Resume: " << I <<
"\n");
2149 DEBUG(
dbgs() <<
"DEFAULT: " << I <<
"\n");
2152 setShadow(&I, getCleanShadow(&I));
2153 setOrigin(&I, getCleanOrigin());
2158 struct VarArgAMD64Helper :
public VarArgHelper {
2161 static const unsigned AMD64GpEndOffset = 48;
2162 static const unsigned AMD64FpEndOffset = 176;
2165 MemorySanitizer &MS;
2166 MemorySanitizerVisitor &MSV;
2167 Value *VAArgTLSCopy;
2168 Value *VAArgOverflowSize;
2172 VarArgAMD64Helper(
Function &F, MemorySanitizer &MS,
2173 MemorySanitizerVisitor &MSV)
2174 : F(F), MS(MS), MSV(MSV), VAArgTLSCopy(0), VAArgOverflowSize(0) { }
2176 enum ArgKind { AK_GeneralPurpose, AK_FloatingPoint, AK_Memory };
2178 ArgKind classifyArgument(
Value* arg) {
2182 return AK_FloatingPoint;
2184 return AK_GeneralPurpose;
2186 return AK_GeneralPurpose;
2199 unsigned GpOffset = 0;
2200 unsigned FpOffset = AMD64GpEndOffset;
2201 unsigned OverflowOffset = AMD64FpEndOffset;
2203 ArgIt != End; ++ArgIt) {
2205 ArgKind AK = classifyArgument(A);
2206 if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset)
2208 if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset)
2212 case AK_GeneralPurpose:
2213 Base = getShadowPtrForVAArgument(A, IRB, GpOffset);
2216 case AK_FloatingPoint:
2217 Base = getShadowPtrForVAArgument(A, IRB, FpOffset);
2221 uint64_t ArgSize = MS.TD->getTypeAllocSize(A->
getType());
2222 Base = getShadowPtrForVAArgument(A, IRB, OverflowOffset);
2229 IRB.
CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS);
2243 VAStartInstrumentationList.push_back(&I);
2245 Value *ShadowPtr = MSV.getShadowPtr(VAListTag, IRB.
getInt8Ty(), IRB);
2256 Value *ShadowPtr = MSV.getShadowPtr(VAListTag, IRB.
getInt8Ty(), IRB);
2264 void finalizeInstrumentation() {
2265 assert(!VAArgOverflowSize && !VAArgTLSCopy &&
2266 "finalizeInstrumentation called twice");
2267 if (!VAStartInstrumentationList.empty()) {
2271 VAArgOverflowSize = IRB.
CreateLoad(MS.VAArgOverflowSizeTLS);
2276 IRB.
CreateMemCpy(VAArgTLSCopy, MS.VAArgTLS, CopySize, 8);
2281 for (
size_t i = 0, n = VAStartInstrumentationList.size(); i < n; i++) {
2282 CallInst *OrigInst = VAStartInstrumentationList[i];
2286 Value *RegSaveAreaPtrPtr =
2292 Value *RegSaveAreaShadowPtr =
2293 MSV.getShadowPtr(RegSaveAreaPtr, IRB.
getInt8Ty(), IRB);
2295 AMD64FpEndOffset, 16);
2297 Value *OverflowArgAreaPtrPtr =
2303 Value *OverflowArgAreaShadowPtr =
2304 MSV.getShadowPtr(OverflowArgAreaPtr, IRB.
getInt8Ty(), IRB);
2306 IRB.
CreateMemCpy(OverflowArgAreaShadowPtr, SrcPtr, VAArgOverflowSize, 16);
2312 struct VarArgNoOpHelper :
public VarArgHelper {
2313 VarArgNoOpHelper(
Function &F, MemorySanitizer &MS,
2314 MemorySanitizerVisitor &MSV) {}
2322 void finalizeInstrumentation() {}
2325 VarArgHelper *CreateVarArgHelper(
Function &
Func, MemorySanitizer &Msan,
2326 MemorySanitizerVisitor &Visitor) {
2331 return new VarArgAMD64Helper(Func, Msan, Visitor);
2333 return new VarArgNoOpHelper(Func, Msan, Visitor);
2338 bool MemorySanitizer::runOnFunction(
Function &F) {
2339 MemorySanitizerVisitor Visitor(F, *
this);
2347 AttributeSet::FunctionIndex, B));
2349 return Visitor.runOnFunction();
void setVisibility(VisibilityTypes V)
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
static const uint64_t kShadowMask64
Value * getValueOperand()
void push_back(const T &Elt)
static Constant * getString(LLVMContext &Context, StringRef Initializer, bool AddNull=true)
AtomicOrdering getOrdering() const
Returns the ordering constraint on this cmpxchg.
LoadInst * CreateLoad(Value *Ptr, const char *Name)
void addIncoming(Value *V, BasicBlock *BB)
LLVMContext & getContext() const
LLVM Argument representation.
static const uint64_t kOriginOffset32
Base class for instruction visitors.
Value * getAggregateOperand()
Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")
ArrayRef< unsigned > getIndices() const
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
unsigned getScalarSizeInBits()
The main container class for the LLVM Intermediate Representation.
void setOrdering(AtomicOrdering Ordering)
Set the ordering constraint on this RMW.
Same, but only replaced by something equivalent.
Intrinsic::ID getIntrinsicID() const
Value * CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name="")
static cl::opt< int > ClPoisonStackPattern("msan-poison-stack-pattern", cl::desc("poison uninitialized stack variables with the given patter"), cl::Hidden, cl::init(0xff))
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static cl::opt< bool > ClPoisonStackWithCall("msan-poison-stack-with-call", cl::desc("poison uninitialized stack variables with a call"), cl::Hidden, cl::init(false))
This class represents zero extension of integer types.
unsigned getNumOperands() const
void appendToGlobalCtors(Module &M, Function *F, int Priority)
void setCalledFunction(Value *V)
void setOrdering(AtomicOrdering Ordering)
static PointerType * get(Type *ElementType, unsigned AddressSpace)
Value * CreatePointerCast(Value *V, Type *DestTy, const Twine &Name="")
bool isSigned() const
Determine if this instruction is using a signed comparison.
Like Internal, but omit from symbol table.
void setOrdering(AtomicOrdering Ordering)
Set the ordering constraint on this cmpxchg.
static SpecialCaseList * createOrDie(const StringRef Path)
Externally visible function.
static bool isEquality(Predicate P)
MDNode - a tuple of other values.
This class represents a sign extension of integer types.
static cl::opt< std::string > ClWrapIndirectCalls("msan-wrap-indirect-calls", cl::desc("Wrap indirect calls with a given function"), cl::Hidden)
AttrBuilder & addAttribute(Attribute::AttrKind Val)
Add an attribute to the builder.
Value * CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name="")
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
Value * CreateShuffleVector(Value *V1, Value *V2, Value *Mask, const Twine &Name="")
MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight)
Return metadata containing two branch weights.
const std::string & getTargetTriple() const
void setDebugLoc(const DebugLoc &Loc)
setDebugLoc - Set the debug location information for this instruction.
static cl::opt< bool > ClHandleICmp("msan-handle-icmp", cl::desc("propagate shadow through ICmpEQ and ICmpNE"), cl::Hidden, cl::init(true))
static PointerType * getInt64PtrTy(LLVMContext &C, unsigned AS=0)
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
static const uint64_t kShadowMask32
Type * getPointerElementType() const
Value * CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, const Twine &Name="")
static Constant * getNullValue(Type *Ty)
StringRef getName() const
IntegerType * getInt32Ty()
Fetch the type representing a 32-bit integer.
Value * CreateExtractValue(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &Name="")
PHINode * CreatePHI(Type *Ty, unsigned NumReservedValues, const Twine &Name="")
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
static cl::opt< bool > ClDumpStrictInstructions("msan-dump-strict-instructions", cl::desc("print out instructions with default strict semantics"), cl::Hidden, cl::init(false))
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT,"arm-default-it","Generate IT block based on arch"), clEnumValN(RestrictedIT,"arm-restrict-it","Disallow deprecated IT based on ARMv8"), clEnumValN(NoRestrictedIT,"arm-no-restrict-it","Allow IT blocks based on ARMv7"), clEnumValEnd))
static cl::opt< bool > ClStoreCleanOrigin("msan-store-clean-origin", cl::desc("store origin for clean (fully initialized) values"), cl::Hidden, cl::init(false))
IntegerType * getInt64Ty()
Fetch the type representing a 64-bit integer.
Base class of casting instructions.
NodeTy * getNextNode()
Get the next node, or 0 for the list tail.
#define llvm_unreachable(msg)
Value * CreateIntToPtr(Value *V, Type *DestTy, const Twine &Name="")
static cl::opt< bool > ClCheckAccessAddress("msan-check-access-address", cl::desc("report accesses through a pointer which has poisoned shadow"), cl::Hidden, cl::init(true))
unsigned getNumArgOperands() const
Instruction * getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Type * getAllocatedType() const
void setName(const Twine &Name)
ID
LLVM Calling Convention Representation.
Type * getVectorElementType() const
Function does not access memory.
AllocaInst * CreateAlloca(Type *Ty, Value *ArraySize=0, const Twine &Name="")
This class represents a cast from a pointer to an integer.
void dumpInst(Value *base, char *instName)
AtomicOrdering getOrdering() const
Returns the ordering constraint on this RMW.
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment)
Represents a floating point comparison operator.
This class represents a no-op cast from one type to another.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
Value * getInsertedValueOperand()
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=None)
ValTy * getCalledValue() const
uint16_t getParamAlignment(uint16_t i) const
Extract the alignment for a call or parameter (0=unknown).
CallInst * CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, Value *Arg4, const Twine &Name="")
Value * CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name="")
static cl::opt< bool > ClPoisonStack("msan-poison-stack", cl::desc("poison uninitialized stack variables"), cl::Hidden, cl::init(true))
void removeAttributes(unsigned i, AttributeSet attr)
removes the attributes from the list of attributes.
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
const char * getOpcodeName() const
This class represents a truncation of integer types.
unsigned getNumIncomingValues() const
static const unsigned kMinOriginAlignment
User::op_iterator arg_iterator
bool isX86_MMXTy() const
isX86_MMXTy - Return true if this is X86 MMX.
bool isIntOrIntVectorTy() const
initializer< Ty > init(const Ty &Val)
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="")
unsigned getAlignment() const
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeSet AttributeList)
LLVM Basic Block Representation.
TerminatorInst * SplitBlockAndInsertIfThen(Instruction *Cmp, bool Unreachable, MDNode *BranchWeights=0)
InstrTy * getInstruction() const
Value * CreateNot(Value *V, const Twine &Name="")
df_iterator< T > df_end(const T &G)
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Type * getContainedType(unsigned i) const
Type * getElementType(unsigned N) const
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
LLVM Constant Representation.
const Value * getCondition() const
unsigned getAlignment() const
const DebugLoc & getDebugLoc() const
getDebugLoc - Return the debug location for this node as a DebugLoc.
BasicBlock * getIncomingBlock(unsigned i) const
Represent an integer comparison operator.
static const unsigned kShadowTLSAlignment
Value * getOperand(unsigned i) const
Value * getPointerOperand()
Integer representation type.
Predicate getPredicate() const
Return the predicate for this instruction.
static Constant * get(StructType *T, ArrayRef< Constant * > V)
This class represents a cast from an integer to a pointer.
static Constant * getAllOnesValue(Type *Ty)
Get the all ones value.
void setTailCall(bool isTC=true)
bool isFPOrFPVectorTy() const
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
StoreInst * CreateAlignedStore(Value *Val, Value *Ptr, unsigned Align, bool isVolatile=false)
LoadInst * CreateAlignedLoad(Value *Ptr, unsigned Align, const char *Name)
const Value * getTrueValue() const
static cl::opt< bool > ClTrackOrigins("msan-track-origins", cl::desc("Track origins (allocation sites) of poisoned memory"), cl::Hidden, cl::init(false))
Track origins of uninitialized values.
bool isRelational() const
BinaryOps getOpcode() const
static IntegerType * get(LLVMContext &C, unsigned NumBits)
Get or create an IntegerType instance.
AtomicOrdering getOrdering() const
Returns the ordering effect of this store.
static PointerType * getUnqual(Type *ElementType)
Value * CreateExtractElement(Value *Vec, Value *Idx, const Twine &Name="")
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="")
unsigned getVectorNumElements() const
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
static cl::opt< std::string > ClBlacklistFile("msan-blacklist", cl::desc("File containing the list of functions where MemorySanitizer ""should not report bugs"), cl::Hidden)
static const uint64_t kOriginOffset64
static IntegerType * getIntNTy(LLVMContext &C, unsigned N)
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
Function * getCalledFunction() const
AtomicOrdering getOrdering() const
Returns the ordering effect of this fence.
const BasicBlock & getEntryBlock() const
static GlobalVariable * createPrivateNonConstGlobalForString(Module &M, StringRef Str)
Create a non-const global initialized with the given string.
static cl::opt< bool > ClKeepGoing("msan-keep-going", cl::desc("keep going after reporting a UMR"), cl::Hidden, cl::init(false))
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
AttributeSet getAttributes() const
Return the attribute list for this Function.
df_iterator< T > df_begin(const T &G)
Value * getArgOperand(unsigned i) const
static cl::opt< bool > ClWrapIndirectCallsFast("msan-wrap-indirect-calls-fast", cl::desc("Do not wrap indirect calls with target in the same module"), cl::Hidden, cl::init(true))
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="")
BasicBlock * getSinglePredecessor()
Return this block if it has a single predecessor block. Otherwise return a null pointer.
Function only reads from memory.
IntegerType * getInt8Ty()
Fetch the type representing an 8-bit integer.
bool isInlineAsm() const
isInlineAsm - Check if this call is an inline asm statement.
Value * CreateInsertValue(Value *Agg, Value *Val, ArrayRef< unsigned > Idxs, const Twine &Name="")
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
void setOrdering(AtomicOrdering Ordering)
static cl::opt< bool > ClHandleICmpExact("msan-handle-icmp-exact", cl::desc("exact handling of relational integer ICmp"), cl::Hidden, cl::init(false))
bool isAggregateType() const
INITIALIZE_PASS(MemorySanitizer,"msan","MemorySanitizer: detects uninitialized reads.", false, false) FunctionPass *llvm
unsigned getAlignment() const
Value * CreateSExt(Value *V, Type *DestTy, const Twine &Name="")
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const
Return true if the call or the callee has the given attribute.
static ArrayType * get(Type *ElementType, uint64_t NumElements)
CallInst * CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, bool isVolatile=false, MDNode *TBAATag=0)
Create and insert a memset to the specified pointer and the specified value.
const Type * getScalarType() const
Value * CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name="")
unsigned getPrimitiveSizeInBits() const
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
bool isUnsigned() const
Determine if this instruction is using an unsigned comparison.
CallInst * CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, const Twine &Name="")
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="")
LLVM Value Representation.
CallInst * CreateCall(Value *Callee, const Twine &Name="")
static VectorType * get(Type *ElementType, unsigned NumElements)
static const Function * getParent(const Value *V)
FunctionPass * createMemorySanitizerPass(bool TrackOrigins=false, StringRef BlacklistFile=StringRef())
static cl::opt< bool > ClPoisonUndef("msan-poison-undef", cl::desc("poison undef temps"), cl::Hidden, cl::init(true))
ConstantInt * getInt8(uint8_t C)
Get a constant 8-bit value.
const Value * getFalseValue() const
bool removeUnreachableBlocks(Function &F)
Remove all blocks that can not be reached from the function's entry.
iterator getFirstInsertionPt()
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
unsigned getNumElements() const
Random access to the elements.
Value * getPointerOperand()
static IntegerType * getInt8Ty(LLVMContext &C)
const BasicBlock * getParent() const
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
CallInst * CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, bool isVolatile=false, MDNode *TBAATag=0, MDNode *TBAAStructTag=0)
Create and insert a memcpy between the specified pointers.
LLVMContext & getContext() const
bool isVoidTy() const
isVoidTy - Return true if this is 'void'.
FunTy * getCalledFunction() const
CallInst * CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, const Twine &Name="")