X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FInstrumentation%2FMemorySanitizer.cpp;h=9f00d3d6c8243260d6f8d41a393e3fc1365d55da;hb=dd890d5c5e452d6f1247c84056e266bd99fe06b2;hp=496ab4877e0304a42aad3b1c591b44a7cddf8fd0;hpb=e3bf8ea87954e0ab210329ea5711889d94439947;p=oota-llvm.git diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 496ab4877e0..9f00d3d6c82 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -120,13 +120,13 @@ using namespace llvm; #define DEBUG_TYPE "msan" -static const uint64_t kShadowMask32 = 1ULL << 31; -static const uint64_t kShadowMask64 = 1ULL << 46; -static const uint64_t kOriginOffset32 = 1ULL << 30; -static const uint64_t kOriginOffset64 = 1ULL << 45; static const unsigned kMinOriginAlignment = 4; static const unsigned kShadowTLSAlignment = 8; +// These constants must be kept in sync with the ones in msan.h. +static const unsigned kParamTLSSize = 800; +static const unsigned kRetvalTLSSize = 800; + // Accesses sizes are powers of two: 1, 2, 4, 8. static const size_t kNumberOfAccessSizes = 4; @@ -183,20 +183,73 @@ static cl::opt ClInstrumentationWithCallThreshold( "inline checks (-1 means never use callbacks)."), cl::Hidden, cl::init(3500)); -// Experimental. Wraps all indirect calls in the instrumented code with -// a call to the given function. This is needed to assist the dynamic -// helper tool (MSanDR) to regain control on transition between instrumented and -// non-instrumented code. -static cl::opt ClWrapIndirectCalls("msan-wrap-indirect-calls", - cl::desc("Wrap indirect calls with a given function"), - cl::Hidden); - -static cl::opt ClWrapIndirectCallsFast("msan-wrap-indirect-calls-fast", - cl::desc("Do not wrap indirect calls with target in the same module"), - cl::Hidden, cl::init(true)); +// This is an experiment to enable handling of cases where shadow is a non-zero +// compile-time constant. For some unexplainable reason they were silently +// ignored in the instrumentation. +static cl::opt ClCheckConstantShadow("msan-check-constant-shadow", + cl::desc("Insert checks for constant shadow values"), + cl::Hidden, cl::init(false)); namespace { +// Memory map parameters used in application-to-shadow address calculation. +// Offset = (Addr & ~AndMask) ^ XorMask +// Shadow = ShadowBase + Offset +// Origin = OriginBase + Offset +struct MemoryMapParams { + uint64_t AndMask; + uint64_t XorMask; + uint64_t ShadowBase; + uint64_t OriginBase; +}; + +struct PlatformMemoryMapParams { + const MemoryMapParams *bits32; + const MemoryMapParams *bits64; +}; + +// i386 Linux +static const MemoryMapParams LinuxMemoryMapParams32 = { + 0x000080000000, // AndMask + 0, // XorMask (not used) + 0, // ShadowBase (not used) + 0x000040000000, // OriginBase +}; + +// x86_64 Linux +static const MemoryMapParams LinuxMemoryMapParams64 = { + 0x400000000000, // AndMask + 0, // XorMask (not used) + 0, // ShadowBase (not used) + 0x200000000000, // OriginBase +}; + +// i386 FreeBSD +static const MemoryMapParams FreeBSDMemoryMapParams32 = { + 0x000180000000, // AndMask + 0x000040000000, // XorMask + 0x000020000000, // ShadowBase + 0x000700000000, // OriginBase +}; + +// x86_64 FreeBSD +static const MemoryMapParams FreeBSDMemoryMapParams64 = { + 0xc00000000000, // AndMask + 0x200000000000, // XorMask + 0x100000000000, // ShadowBase + 0x380000000000, // OriginBase +}; + +static const PlatformMemoryMapParams LinuxMemoryMapParams = { + &LinuxMemoryMapParams32, + &LinuxMemoryMapParams64, +}; + +static const PlatformMemoryMapParams FreeBSDMemoryMapParams = { + &FreeBSDMemoryMapParams32, + &FreeBSDMemoryMapParams64, +}; + /// \brief An instrumentation pass implementing detection of uninitialized /// reads. /// @@ -208,8 +261,7 @@ class MemorySanitizer : public FunctionPass { : FunctionPass(ID), TrackOrigins(std::max(TrackOrigins, (int)ClTrackOrigins)), DL(nullptr), - WarningFn(nullptr), - WrapIndirectCalls(!ClWrapIndirectCalls.empty()) {} + WarningFn(nullptr) {} const char *getPassName() const override { return "MemorySanitizer"; } bool runOnFunction(Function &F) override; bool doInitialization(Module &M) override; @@ -243,9 +295,6 @@ class MemorySanitizer : public FunctionPass { /// function. GlobalVariable *OriginTLS; - GlobalVariable *MsandrModuleStart; - GlobalVariable *MsandrModuleEnd; - /// \brief The run-time callback to print a warning. Value *WarningFn; // These arrays are indexed by log2(AccessSize). @@ -263,25 +312,15 @@ class MemorySanitizer : public FunctionPass { /// \brief MSan runtime replacements for memmove, memcpy and memset. Value *MemmoveFn, *MemcpyFn, *MemsetFn; - /// \brief Address mask used in application-to-shadow address calculation. - /// ShadowAddr is computed as ApplicationAddr & ~ShadowMask. - uint64_t ShadowMask; - /// \brief Offset of the origin shadow from the "normal" shadow. - /// OriginAddr is computed as (ShadowAddr + OriginOffset) & ~3ULL - uint64_t OriginOffset; - /// \brief Branch weights for error reporting. + /// \brief Memory map parameters used in application-to-shadow calculation. + const MemoryMapParams *MapParams; + MDNode *ColdCallWeights; /// \brief Branch weights for origin store. MDNode *OriginStoreWeights; /// \brief An empty volatile inline asm that prevents callback merge. InlineAsm *EmptyAsm; - bool WrapIndirectCalls; - /// \brief Run-time wrapper for indirect calls. - Value *IndirectCallWrapperFn; - // Argument and return type of IndirectCallWrapperFn: void (*f)(void). - Type *AnyFunctionPtrTy; - friend struct MemorySanitizerVisitor; friend struct VarArgAMD64Helper; }; @@ -321,7 +360,7 @@ void MemorySanitizer::initializeCallbacks(Module &M) { // which is not yet implemented. StringRef WarningFnName = ClKeepGoing ? "__msan_warning" : "__msan_warning_noreturn"; - WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy(), NULL); + WarningFn = M.getOrInsertFunction(WarningFnName, IRB.getVoidTy(), nullptr); for (size_t AccessSizeIndex = 0; AccessSizeIndex < kNumberOfAccessSizes; AccessSizeIndex++) { @@ -329,34 +368,35 @@ void MemorySanitizer::initializeCallbacks(Module &M) { std::string FunctionName = "__msan_maybe_warning_" + itostr(AccessSize); MaybeWarningFn[AccessSizeIndex] = M.getOrInsertFunction( FunctionName, IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), - IRB.getInt32Ty(), NULL); + IRB.getInt32Ty(), nullptr); FunctionName = "__msan_maybe_store_origin_" + itostr(AccessSize); MaybeStoreOriginFn[AccessSizeIndex] = M.getOrInsertFunction( FunctionName, IRB.getVoidTy(), IRB.getIntNTy(AccessSize * 8), - IRB.getInt8PtrTy(), IRB.getInt32Ty(), NULL); + IRB.getInt8PtrTy(), IRB.getInt32Ty(), nullptr); } MsanSetAllocaOrigin4Fn = M.getOrInsertFunction( "__msan_set_alloca_origin4", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, - IRB.getInt8PtrTy(), IntptrTy, NULL); - MsanPoisonStackFn = M.getOrInsertFunction( - "__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, NULL); + IRB.getInt8PtrTy(), IntptrTy, nullptr); + MsanPoisonStackFn = + M.getOrInsertFunction("__msan_poison_stack", IRB.getVoidTy(), + IRB.getInt8PtrTy(), IntptrTy, nullptr); MsanChainOriginFn = M.getOrInsertFunction( - "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty(), NULL); + "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty(), nullptr); MemmoveFn = M.getOrInsertFunction( "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), - IRB.getInt8PtrTy(), IntptrTy, NULL); + IRB.getInt8PtrTy(), IntptrTy, nullptr); MemcpyFn = M.getOrInsertFunction( "__msan_memcpy", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), - IntptrTy, NULL); + IntptrTy, nullptr); MemsetFn = M.getOrInsertFunction( "__msan_memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), - IntptrTy, NULL); + IntptrTy, nullptr); // Create globals. RetvalTLS = new GlobalVariable( - M, ArrayType::get(IRB.getInt64Ty(), 8), false, + M, ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8), false, GlobalVariable::ExternalLinkage, nullptr, "__msan_retval_tls", nullptr, GlobalVariable::InitialExecTLSModel); RetvalOriginTLS = new GlobalVariable( @@ -364,16 +404,16 @@ void MemorySanitizer::initializeCallbacks(Module &M) { "__msan_retval_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel); ParamTLS = new GlobalVariable( - M, ArrayType::get(IRB.getInt64Ty(), 1000), false, + M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, GlobalVariable::ExternalLinkage, nullptr, "__msan_param_tls", nullptr, GlobalVariable::InitialExecTLSModel); ParamOriginTLS = new GlobalVariable( - M, ArrayType::get(OriginTy, 1000), false, GlobalVariable::ExternalLinkage, - nullptr, "__msan_param_origin_tls", nullptr, - GlobalVariable::InitialExecTLSModel); + M, ArrayType::get(OriginTy, kParamTLSSize / 4), false, + GlobalVariable::ExternalLinkage, nullptr, "__msan_param_origin_tls", + nullptr, GlobalVariable::InitialExecTLSModel); VAArgTLS = new GlobalVariable( - M, ArrayType::get(IRB.getInt64Ty(), 1000), false, + M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_tls", nullptr, GlobalVariable::InitialExecTLSModel); VAArgOverflowSizeTLS = new GlobalVariable( @@ -388,24 +428,6 @@ void MemorySanitizer::initializeCallbacks(Module &M) { EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), /*hasSideEffects=*/true); - - if (WrapIndirectCalls) { - AnyFunctionPtrTy = - PointerType::getUnqual(FunctionType::get(IRB.getVoidTy(), false)); - IndirectCallWrapperFn = M.getOrInsertFunction( - ClWrapIndirectCalls, AnyFunctionPtrTy, AnyFunctionPtrTy, NULL); - } - - if (WrapIndirectCalls && ClWrapIndirectCallsFast) { - MsandrModuleStart = new GlobalVariable( - M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage, - nullptr, "__executable_start"); - MsandrModuleStart->setVisibility(GlobalVariable::HiddenVisibility); - MsandrModuleEnd = new GlobalVariable( - M, IRB.getInt32Ty(), false, GlobalValue::ExternalLinkage, - nullptr, "_end"); - MsandrModuleEnd->setVisibility(GlobalVariable::HiddenVisibility); - } } /// \brief Module-level initialization. @@ -417,16 +439,21 @@ bool MemorySanitizer::doInitialization(Module &M) { report_fatal_error("data layout missing"); DL = &DLP->getDataLayout(); + Triple TargetTriple(M.getTargetTriple()); + const PlatformMemoryMapParams *PlatformMapParams; + if (TargetTriple.getOS() == Triple::FreeBSD) + PlatformMapParams = &FreeBSDMemoryMapParams; + else + PlatformMapParams = &LinuxMemoryMapParams; + C = &(M.getContext()); unsigned PtrSize = DL->getPointerSizeInBits(/* AddressSpace */0); switch (PtrSize) { case 64: - ShadowMask = kShadowMask64; - OriginOffset = kOriginOffset64; + MapParams = PlatformMapParams->bits64; break; case 32: - ShadowMask = kShadowMask32; - OriginOffset = kOriginOffset32; + MapParams = PlatformMapParams->bits32; break; default: report_fatal_error("unsupported pointer size"); @@ -442,7 +469,7 @@ bool MemorySanitizer::doInitialization(Module &M) { // Insert a call to __msan_init/__msan_track_origins into the module's CTORs. appendToGlobalCtors(M, cast(M.getOrInsertFunction( - "__msan_init", IRB.getVoidTy(), NULL)), 0); + "__msan_init", IRB.getVoidTy(), nullptr)), 0); if (TrackOrigins) new GlobalVariable(M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage, @@ -525,7 +552,6 @@ struct MemorySanitizerVisitor : public InstVisitor { }; SmallVector InstrumentationList; SmallVector StoreList; - SmallVector IndirectCallList; MemorySanitizerVisitor(Function &F, MemorySanitizer &MS) : F(F), MS(MS), VAHelper(CreateVarArgHelper(F, MS, *this)) { @@ -551,15 +577,18 @@ struct MemorySanitizerVisitor : public InstVisitor { void storeOrigin(IRBuilder<> &IRB, Value *Addr, Value *Shadow, Value *Origin, unsigned Alignment, bool AsCall) { + unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment); if (isa(Shadow->getType())) { - IRB.CreateAlignedStore(updateOrigin(Origin, IRB), getOriginPtr(Addr, IRB), - Alignment); + IRB.CreateAlignedStore(updateOrigin(Origin, IRB), + getOriginPtr(Addr, IRB, Alignment), + OriginAlignment); } else { Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB); // TODO(eugenis): handle non-zero constant shadow by inserting an // unconditional check (can not simply fail compilation as this could // be in the dead code). - if (isa(ConvertedShadow)) return; + if (!ClCheckConstantShadow) + if (isa(ConvertedShadow)) return; unsigned TypeSizeInBits = MS.DL->getTypeSizeInBits(ConvertedShadow->getType()); unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits); @@ -577,7 +606,8 @@ struct MemorySanitizerVisitor : public InstVisitor { Cmp, IRB.GetInsertPoint(), false, MS.OriginStoreWeights); IRBuilder<> IRBNew(CheckTerm); IRBNew.CreateAlignedStore(updateOrigin(Origin, IRBNew), - getOriginPtr(Addr, IRBNew), Alignment); + getOriginPtr(Addr, IRBNew, Alignment), + OriginAlignment); } } } @@ -601,11 +631,9 @@ struct MemorySanitizerVisitor : public InstVisitor { if (SI.isAtomic()) SI.setOrdering(addReleaseOrdering(SI.getOrdering())); - if (MS.TrackOrigins) { - unsigned Alignment = std::max(kMinOriginAlignment, SI.getAlignment()); - storeOrigin(IRB, Addr, Shadow, getOrigin(Val), Alignment, + if (MS.TrackOrigins) + storeOrigin(IRB, Addr, Shadow, getOrigin(Val), SI.getAlignment(), InstrumentWithCalls); - } } } @@ -615,8 +643,9 @@ struct MemorySanitizerVisitor : public InstVisitor { DEBUG(dbgs() << " SHAD0 : " << *Shadow << "\n"); Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB); DEBUG(dbgs() << " SHAD1 : " << *ConvertedShadow << "\n"); - // See the comment in materializeStores(). - if (isa(ConvertedShadow)) return; + // See the comment in storeOrigin(). + if (!ClCheckConstantShadow) + if (isa(ConvertedShadow)) return; unsigned TypeSizeInBits = MS.DL->getTypeSizeInBits(ConvertedShadow->getType()); unsigned SizeIndex = TypeSizeToSizeIndex(TypeSizeInBits); @@ -655,47 +684,6 @@ struct MemorySanitizerVisitor : public InstVisitor { DEBUG(dbgs() << "DONE:\n" << F); } - void materializeIndirectCalls() { - for (auto &CS : IndirectCallList) { - Instruction *I = CS.getInstruction(); - BasicBlock *B = I->getParent(); - IRBuilder<> IRB(I); - Value *Fn0 = CS.getCalledValue(); - Value *Fn = IRB.CreateBitCast(Fn0, MS.AnyFunctionPtrTy); - - if (ClWrapIndirectCallsFast) { - // Check that call target is inside this module limits. - Value *Start = - IRB.CreateBitCast(MS.MsandrModuleStart, MS.AnyFunctionPtrTy); - Value *End = IRB.CreateBitCast(MS.MsandrModuleEnd, MS.AnyFunctionPtrTy); - - Value *NotInThisModule = IRB.CreateOr(IRB.CreateICmpULT(Fn, Start), - IRB.CreateICmpUGE(Fn, End)); - - PHINode *NewFnPhi = - IRB.CreatePHI(Fn0->getType(), 2, "msandr.indirect_target"); - - Instruction *CheckTerm = SplitBlockAndInsertIfThen( - NotInThisModule, NewFnPhi, - /* Unreachable */ false, MS.ColdCallWeights); - - IRB.SetInsertPoint(CheckTerm); - // Slow path: call wrapper function to possibly transform the call - // target. - Value *NewFn = IRB.CreateBitCast( - IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->getType()); - - NewFnPhi->addIncoming(Fn0, B); - NewFnPhi->addIncoming(NewFn, dyn_cast(NewFn)->getParent()); - CS.setCalledFunction(NewFnPhi); - } else { - Value *NewFn = IRB.CreateBitCast( - IRB.CreateCall(MS.IndirectCallWrapperFn, Fn), Fn0->getType()); - CS.setCalledFunction(NewFn); - } - } - } - /// \brief Add MemorySanitizer instrumentation to a function. bool runOnFunction() { MS.initializeCallbacks(*F.getParent()); @@ -738,9 +726,6 @@ struct MemorySanitizerVisitor : public InstVisitor { // Insert shadow value checks. materializeChecks(InstrumentWithCalls); - // Wrap indirect calls. - materializeIndirectCalls(); - return true; } @@ -763,6 +748,10 @@ struct MemorySanitizerVisitor : public InstVisitor { return VectorType::get(IntegerType::get(*MS.C, EltSize), VT->getNumElements()); } + if (ArrayType *AT = dyn_cast(OrigTy)) { + return ArrayType::get(getShadowTy(AT->getElementType()), + AT->getNumElements()); + } if (StructType *ST = dyn_cast(OrigTy)) { SmallVector Elements; for (unsigned i = 0, n = ST->getNumElements(); i < n; i++) @@ -790,32 +779,57 @@ struct MemorySanitizerVisitor : public InstVisitor { return IRB.CreateBitCast(V, NoVecTy); } + /// \brief Compute the integer shadow offset that corresponds to a given + /// application address. + /// + /// Offset = (Addr & ~AndMask) ^ XorMask + Value *getShadowPtrOffset(Value *Addr, IRBuilder<> &IRB) { + uint64_t AndMask = MS.MapParams->AndMask; + assert(AndMask != 0 && "AndMask shall be specified"); + Value *OffsetLong = + IRB.CreateAnd(IRB.CreatePointerCast(Addr, MS.IntptrTy), + ConstantInt::get(MS.IntptrTy, ~AndMask)); + + uint64_t XorMask = MS.MapParams->XorMask; + if (XorMask != 0) + OffsetLong = IRB.CreateXor(OffsetLong, + ConstantInt::get(MS.IntptrTy, XorMask)); + return OffsetLong; + } + /// \brief Compute the shadow address that corresponds to a given application /// address. /// - /// Shadow = Addr & ~ShadowMask. + /// Shadow = ShadowBase + Offset Value *getShadowPtr(Value *Addr, Type *ShadowTy, IRBuilder<> &IRB) { - Value *ShadowLong = - IRB.CreateAnd(IRB.CreatePointerCast(Addr, MS.IntptrTy), - ConstantInt::get(MS.IntptrTy, ~MS.ShadowMask)); + Value *ShadowLong = getShadowPtrOffset(Addr, IRB); + uint64_t ShadowBase = MS.MapParams->ShadowBase; + if (ShadowBase != 0) + ShadowLong = + IRB.CreateAdd(ShadowLong, + ConstantInt::get(MS.IntptrTy, ShadowBase)); return IRB.CreateIntToPtr(ShadowLong, PointerType::get(ShadowTy, 0)); } /// \brief Compute the origin address that corresponds to a given application /// address. /// - /// OriginAddr = (ShadowAddr + OriginOffset) & ~3ULL - Value *getOriginPtr(Value *Addr, IRBuilder<> &IRB) { - Value *ShadowLong = - IRB.CreateAnd(IRB.CreatePointerCast(Addr, MS.IntptrTy), - ConstantInt::get(MS.IntptrTy, ~MS.ShadowMask)); - Value *Add = - IRB.CreateAdd(ShadowLong, - ConstantInt::get(MS.IntptrTy, MS.OriginOffset)); - Value *SecondAnd = - IRB.CreateAnd(Add, ConstantInt::get(MS.IntptrTy, ~3ULL)); - return IRB.CreateIntToPtr(SecondAnd, PointerType::get(IRB.getInt32Ty(), 0)); + /// OriginAddr = (OriginBase + Offset) & ~3ULL + Value *getOriginPtr(Value *Addr, IRBuilder<> &IRB, unsigned Alignment) { + Value *OriginLong = getShadowPtrOffset(Addr, IRB); + uint64_t OriginBase = MS.MapParams->OriginBase; + if (OriginBase != 0) + OriginLong = + IRB.CreateAdd(OriginLong, + ConstantInt::get(MS.IntptrTy, OriginBase)); + if (Alignment < kMinOriginAlignment) { + uint64_t Mask = kMinOriginAlignment - 1; + OriginLong = IRB.CreateAnd(OriginLong, + ConstantInt::get(MS.IntptrTy, ~Mask)); + } + return IRB.CreateIntToPtr(OriginLong, + PointerType::get(IRB.getInt32Ty(), 0)); } /// \brief Compute the shadow address for a given function argument. @@ -882,11 +896,18 @@ struct MemorySanitizerVisitor : public InstVisitor { assert(ShadowTy); if (isa(ShadowTy) || isa(ShadowTy)) return Constant::getAllOnesValue(ShadowTy); - StructType *ST = cast(ShadowTy); - SmallVector Vals; - for (unsigned i = 0, n = ST->getNumElements(); i < n; i++) - Vals.push_back(getPoisonedShadow(ST->getElementType(i))); - return ConstantStruct::get(ST, Vals); + if (ArrayType *AT = dyn_cast(ShadowTy)) { + SmallVector Vals(AT->getNumElements(), + getPoisonedShadow(AT->getElementType())); + return ConstantArray::get(AT, Vals); + } + if (StructType *ST = dyn_cast(ShadowTy)) { + SmallVector Vals; + for (unsigned i = 0, n = ST->getNumElements(); i < n; i++) + Vals.push_back(getPoisonedShadow(ST->getElementType(i))); + return ConstantStruct::get(ST, Vals); + } + llvm_unreachable("Unexpected shadow type"); } /// \brief Create a dirty shadow for a given value. @@ -941,6 +962,7 @@ struct MemorySanitizerVisitor : public InstVisitor { ? MS.DL->getTypeAllocSize(FArg.getType()->getPointerElementType()) : MS.DL->getTypeAllocSize(FArg.getType()); if (A == &FArg) { + bool Overflow = ArgOffset + Size > kParamTLSSize; Value *Base = getShadowPtrForArgument(&FArg, EntryIRB, ArgOffset); if (FArg.hasByValAttr()) { // ByVal pointer itself has clean shadow. We copy the actual @@ -951,25 +973,40 @@ struct MemorySanitizerVisitor : public InstVisitor { Type *EltType = A->getType()->getPointerElementType(); ArgAlign = MS.DL->getABITypeAlignment(EltType); } - unsigned CopyAlign = std::min(ArgAlign, kShadowTLSAlignment); - Value *Cpy = EntryIRB.CreateMemCpy( - getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB), Base, Size, - CopyAlign); - DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n"); - (void)Cpy; + if (Overflow) { + // ParamTLS overflow. + EntryIRB.CreateMemSet( + getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB), + Constant::getNullValue(EntryIRB.getInt8Ty()), Size, ArgAlign); + } else { + unsigned CopyAlign = std::min(ArgAlign, kShadowTLSAlignment); + Value *Cpy = EntryIRB.CreateMemCpy( + getShadowPtr(V, EntryIRB.getInt8Ty(), EntryIRB), Base, Size, + CopyAlign); + DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n"); + (void)Cpy; + } *ShadowPtr = getCleanShadow(V); } else { - *ShadowPtr = EntryIRB.CreateAlignedLoad(Base, kShadowTLSAlignment); + if (Overflow) { + // ParamTLS overflow. + *ShadowPtr = getCleanShadow(V); + } else { + *ShadowPtr = + EntryIRB.CreateAlignedLoad(Base, kShadowTLSAlignment); + } } DEBUG(dbgs() << " ARG: " << FArg << " ==> " << **ShadowPtr << "\n"); - if (MS.TrackOrigins) { + if (MS.TrackOrigins && !Overflow) { Value *OriginPtr = getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset); setOrigin(A, EntryIRB.CreateLoad(OriginPtr)); + } else { + setOrigin(A, getCleanOrigin()); } } - ArgOffset += DataLayout::RoundUpAlignment(Size, kShadowTLSAlignment); + ArgOffset += RoundUpToAlignment(Size, kShadowTLSAlignment); } assert(*ShadowPtr && "Could not find shadow for an argument"); return *ShadowPtr; @@ -986,15 +1023,13 @@ struct MemorySanitizerVisitor : public InstVisitor { /// \brief Get the origin for a value. Value *getOrigin(Value *V) { if (!MS.TrackOrigins) return nullptr; - if (isa(V) || isa(V)) { - Value *Origin = OriginMap[V]; - if (!Origin) { - DEBUG(dbgs() << "NO ORIGIN: " << *V << "\n"); - Origin = getCleanOrigin(); - } - return Origin; - } - return getCleanOrigin(); + if (!PropagateShadow) return getCleanOrigin(); + if (isa(V)) return getCleanOrigin(); + assert((isa(V) || isa(V)) && + "Unexpected value type in getOrigin()"); + Value *Origin = OriginMap[V]; + assert(Origin && "Missing origin"); + return Origin; } /// \brief Get the origin for i-th argument of the instruction I. @@ -1024,9 +1059,16 @@ struct MemorySanitizerVisitor : public InstVisitor { /// UMR warning in runtime if the value is not fully defined. void insertShadowCheck(Value *Val, Instruction *OrigIns) { assert(Val); - Instruction *Shadow = dyn_cast_or_null(getShadow(Val)); - if (!Shadow) return; - Instruction *Origin = dyn_cast_or_null(getOrigin(Val)); + Value *Shadow, *Origin; + if (ClCheckConstantShadow) { + Shadow = getShadow(Val); + if (!Shadow) return; + Origin = getOrigin(Val); + } else { + Shadow = dyn_cast_or_null(getShadow(Val)); + if (!Shadow) return; + Origin = dyn_cast_or_null(getOrigin(Val)); + } insertShadowCheck(Shadow, Origin, OrigIns); } @@ -1075,7 +1117,7 @@ struct MemorySanitizerVisitor : public InstVisitor { IRBuilder<> IRB(I.getNextNode()); Type *ShadowTy = getShadowTy(&I); Value *Addr = I.getPointerOperand(); - if (PropagateShadow) { + if (PropagateShadow && !I.getMetadata("nosanitize")) { Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB); setShadow(&I, IRB.CreateAlignedLoad(ShadowPtr, I.getAlignment(), "_msld")); @@ -1091,9 +1133,10 @@ struct MemorySanitizerVisitor : public InstVisitor { if (MS.TrackOrigins) { if (PropagateShadow) { - unsigned Alignment = std::max(kMinOriginAlignment, I.getAlignment()); - setOrigin(&I, - IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB), Alignment)); + unsigned Alignment = I.getAlignment(); + unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment); + setOrigin(&I, IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB, Alignment), + OriginAlignment)); } else { setOrigin(&I, getCleanOrigin()); } @@ -1127,6 +1170,7 @@ struct MemorySanitizerVisitor : public InstVisitor { IRB.CreateStore(getCleanShadow(&I), ShadowPtr); setShadow(&I, getCleanShadow(&I)); + setOrigin(&I, getCleanOrigin()); } void visitAtomicRMWInst(AtomicRMWInst &I) { @@ -1744,7 +1788,7 @@ struct MemorySanitizerVisitor : public InstVisitor { // FIXME: use ClStoreCleanOrigin // FIXME: factor out common code from materializeStores if (MS.TrackOrigins) - IRB.CreateStore(getOrigin(&I, 1), getOriginPtr(Addr, IRB)); + IRB.CreateStore(getOrigin(&I, 1), getOriginPtr(Addr, IRB, 1)); return true; } @@ -1771,7 +1815,7 @@ struct MemorySanitizerVisitor : public InstVisitor { if (MS.TrackOrigins) { if (PropagateShadow) - setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB))); + setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB, 1))); else setOrigin(&I, getCleanOrigin()); } @@ -1859,7 +1903,7 @@ struct MemorySanitizerVisitor : public InstVisitor { Value *Op = I.getArgOperand(0); Type *OpType = Op->getType(); Function *BswapFunc = Intrinsic::getDeclaration( - F.getParent(), Intrinsic::bswap, ArrayRef(&OpType, 1)); + F.getParent(), Intrinsic::bswap, makeArrayRef(&OpType, 1)); setShadow(&I, IRB.CreateCall(BswapFunc, getShadow(Op))); setOrigin(&I, getOrigin(Op)); } @@ -1935,6 +1979,7 @@ struct MemorySanitizerVisitor : public InstVisitor { setOrigin(&I, getOrigin(CopyOp)); } else { setShadow(&I, getCleanShadow(&I)); + setOrigin(&I, getCleanOrigin()); } } @@ -2291,9 +2336,6 @@ struct MemorySanitizerVisitor : public InstVisitor { } IRBuilder<> IRB(&I); - if (MS.WrapIndirectCalls && !CS.getCalledFunction()) - IndirectCallList.push_back(CS); - unsigned ArgOffset = 0; DEBUG(dbgs() << " CallSite: " << I << "\n"); for (CallSite::arg_iterator ArgIt = CS.arg_begin(), End = CS.arg_end(); @@ -2313,26 +2355,32 @@ struct MemorySanitizerVisitor : public InstVisitor { Value *ArgShadowBase = getShadowPtrForArgument(A, IRB, ArgOffset); DEBUG(dbgs() << " Arg#" << i << ": " << *A << " Shadow: " << *ArgShadow << "\n"); + bool ArgIsInitialized = false; if (CS.paramHasAttr(i + 1, Attribute::ByVal)) { assert(A->getType()->isPointerTy() && "ByVal argument is not a pointer!"); Size = MS.DL->getTypeAllocSize(A->getType()->getPointerElementType()); - unsigned Alignment = CS.getParamAlignment(i + 1); + if (ArgOffset + Size > kParamTLSSize) break; + unsigned ParamAlignment = CS.getParamAlignment(i + 1); + unsigned Alignment = std::min(ParamAlignment, kShadowTLSAlignment); Store = IRB.CreateMemCpy(ArgShadowBase, getShadowPtr(A, Type::getInt8Ty(*MS.C), IRB), Size, Alignment); } else { Size = MS.DL->getTypeAllocSize(A->getType()); + if (ArgOffset + Size > kParamTLSSize) break; Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase, kShadowTLSAlignment); + Constant *Cst = dyn_cast(ArgShadow); + if (Cst && Cst->isNullValue()) ArgIsInitialized = true; } - if (MS.TrackOrigins) + if (MS.TrackOrigins && !ArgIsInitialized) IRB.CreateStore(getOrigin(A), getOriginPtrForArgument(A, IRB, ArgOffset)); (void)Store; assert(Size != 0 && Store != nullptr); DEBUG(dbgs() << " Param:" << *Store << "\n"); - ArgOffset += DataLayout::RoundUpAlignment(Size, 8); + ArgOffset += RoundUpToAlignment(Size, 8); } DEBUG(dbgs() << " done with call args\n"); @@ -2396,6 +2444,7 @@ struct MemorySanitizerVisitor : public InstVisitor { IRBuilder<> IRB(&I); if (!PropagateShadow) { setShadow(&I, getCleanShadow(&I)); + setOrigin(&I, getCleanOrigin()); return; } @@ -2409,6 +2458,7 @@ struct MemorySanitizerVisitor : public InstVisitor { void visitAllocaInst(AllocaInst &I) { setShadow(&I, getCleanShadow(&I)); + setOrigin(&I, getCleanOrigin()); IRBuilder<> IRB(I.getNextNode()); uint64_t Size = MS.DL->getTypeAllocSize(I.getAllocatedType()); if (PoisonStack && ClPoisonStackWithCall) { @@ -2422,7 +2472,6 @@ struct MemorySanitizerVisitor : public InstVisitor { } if (PoisonStack && MS.TrackOrigins) { - setOrigin(&I, getCleanOrigin()); SmallString<2048> StackDescriptionStorage; raw_svector_ostream StackDescription(StackDescriptionStorage); // We create a string with a description of the stack allocation and @@ -2488,9 +2537,10 @@ struct MemorySanitizerVisitor : public InstVisitor { } // a = select b, c, d // Oa = Sb ? Ob : (b ? Oc : Od) - setOrigin(&I, IRB.CreateSelect( - Sb, getOrigin(I.getCondition()), - IRB.CreateSelect(B, getOrigin(C), getOrigin(D)))); + setOrigin( + &I, IRB.CreateSelect(Sb, getOrigin(I.getCondition()), + IRB.CreateSelect(B, getOrigin(I.getTrueValue()), + getOrigin(I.getFalseValue())))); } } @@ -2613,7 +2663,7 @@ struct VarArgAMD64Helper : public VarArgHelper { Type *RealTy = A->getType()->getPointerElementType(); uint64_t ArgSize = MS.DL->getTypeAllocSize(RealTy); Value *Base = getShadowPtrForVAArgument(RealTy, IRB, OverflowOffset); - OverflowOffset += DataLayout::RoundUpAlignment(ArgSize, 8); + OverflowOffset += RoundUpToAlignment(ArgSize, 8); IRB.CreateMemCpy(Base, MSV.getShadowPtr(A, IRB.getInt8Ty(), IRB), ArgSize, kShadowTLSAlignment); } else { @@ -2635,7 +2685,7 @@ struct VarArgAMD64Helper : public VarArgHelper { case AK_Memory: uint64_t ArgSize = MS.DL->getTypeAllocSize(A->getType()); Base = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset); - OverflowOffset += DataLayout::RoundUpAlignment(ArgSize, 8); + OverflowOffset += RoundUpToAlignment(ArgSize, 8); } IRB.CreateAlignedStore(MSV.getShadow(A), Base, kShadowTLSAlignment); }