diff options
author | Alexander Potapenko <glider@google.com> | 2018-09-06 15:14:36 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2018-09-06 15:14:36 +0000 |
commit | 7f270fcf0a9841795670e2763952a0dd562ba4ba (patch) | |
tree | 29f7d3e1adbdbcaeef20dfb76e73c165f83e176f /llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | |
parent | 05a15afe6fa8fa1375f26532f741d48cc048ac65 (diff) | |
download | bcm5719-llvm-7f270fcf0a9841795670e2763952a0dd562ba4ba.tar.gz bcm5719-llvm-7f270fcf0a9841795670e2763952a0dd562ba4ba.zip |
[MSan] store origins for variadic function parameters in __msan_va_arg_origin_tls
Add the __msan_va_arg_origin_tls TLS array to keep the origins for variadic function parameters.
Change the instrumentation pass to store parameter origins in this array.
This is a reland of r341528.
test/msan/vararg.cc doesn't work on Mips, PPC and AArch64 (because this
patch doesn't touch them), XFAIL these arches.
Also turned out Clang crashed on i80 vararg arguments because of
incorrect origin type returned by getOriginPtrForVAArgument() - fixed it
and added a test.
llvm-svn: 341554
Diffstat (limited to 'llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp')
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp | 65 |
1 files changed, 61 insertions, 4 deletions
diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index b3c31f5d53b..9a9bbff715a 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -448,6 +448,10 @@ private: /// parameters (x86_64-specific). GlobalVariable *VAArgTLS; + /// Thread-local shadow storage for in-register va_arg function + /// parameters (x86_64-specific). + GlobalVariable *VAArgOriginTLS; + /// Thread-local shadow storage for va_arg overflow area /// (x86_64-specific). GlobalVariable *VAArgOverflowSizeTLS; @@ -560,6 +564,12 @@ void MemorySanitizer::createUserspaceApi(Module &M) { M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_tls", nullptr, GlobalVariable::InitialExecTLSModel); + + VAArgOriginTLS = new GlobalVariable( + M, ArrayType::get(OriginTy, kParamTLSSize / 4), false, + GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_origin_tls", + nullptr, GlobalVariable::InitialExecTLSModel); + VAArgOverflowSizeTLS = new GlobalVariable( M, IRB.getInt64Ty(), false, GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_overflow_size_tls", nullptr, @@ -3258,6 +3268,7 @@ struct VarArgAMD64Helper : public VarArgHelper { MemorySanitizer &MS; MemorySanitizerVisitor &MSV; Value *VAArgTLSCopy = nullptr; + Value *VAArgTLSOriginCopy = nullptr; Value *VAArgOverflowSize = nullptr; SmallVector<CallInst*, 16> VAStartInstrumentationList; @@ -3320,6 +3331,9 @@ struct VarArgAMD64Helper : public VarArgHelper { uint64_t ArgSize = DL.getTypeAllocSize(RealTy); Value *ShadowBase = getShadowPtrForVAArgument( RealTy, IRB, OverflowOffset, alignTo(ArgSize, 8)); + Value *OriginBase = nullptr; + if (MS.TrackOrigins) + OriginBase = getOriginPtrForVAArgument(RealTy, IRB, OverflowOffset); OverflowOffset += alignTo(ArgSize, 8); if (!ShadowBase) continue; @@ -3330,22 +3344,31 @@ struct VarArgAMD64Helper : public VarArgHelper { IRB.CreateMemCpy(ShadowBase, kShadowTLSAlignment, ShadowPtr, kShadowTLSAlignment, ArgSize); + if (MS.TrackOrigins) + IRB.CreateMemCpy(OriginBase, kShadowTLSAlignment, OriginPtr, + kShadowTLSAlignment, ArgSize); } else { ArgKind AK = classifyArgument(A); if (AK == AK_GeneralPurpose && GpOffset >= AMD64GpEndOffset) AK = AK_Memory; if (AK == AK_FloatingPoint && FpOffset >= AMD64FpEndOffset) AK = AK_Memory; - Value *ShadowBase; + Value *ShadowBase, *OriginBase = nullptr; switch (AK) { case AK_GeneralPurpose: ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, GpOffset, 8); + if (MS.TrackOrigins) + OriginBase = + getOriginPtrForVAArgument(A->getType(), IRB, GpOffset); GpOffset += 8; break; case AK_FloatingPoint: ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, FpOffset, 16); + if (MS.TrackOrigins) + OriginBase = + getOriginPtrForVAArgument(A->getType(), IRB, FpOffset); FpOffset += 16; break; case AK_Memory: @@ -3354,16 +3377,26 @@ struct VarArgAMD64Helper : public VarArgHelper { uint64_t ArgSize = DL.getTypeAllocSize(A->getType()); ShadowBase = getShadowPtrForVAArgument(A->getType(), IRB, OverflowOffset, 8); + if (MS.TrackOrigins) + OriginBase = + getOriginPtrForVAArgument(A->getType(), IRB, OverflowOffset); OverflowOffset += alignTo(ArgSize, 8); } // Take fixed arguments into account for GpOffset and FpOffset, // but don't actually store shadows for them. + // TODO(glider): don't call get*PtrForVAArgument() for them. if (IsFixed) continue; if (!ShadowBase) continue; - IRB.CreateAlignedStore(MSV.getShadow(A), ShadowBase, - kShadowTLSAlignment); + Value *Shadow = MSV.getShadow(A); + IRB.CreateAlignedStore(Shadow, ShadowBase, kShadowTLSAlignment); + if (MS.TrackOrigins) { + Value *Origin = MSV.getOrigin(A); + unsigned StoreSize = DL.getTypeStoreSize(Shadow->getType()); + MSV.paintOrigin(IRB, Origin, OriginBase, StoreSize, + std::max(kShadowTLSAlignment, kMinOriginAlignment)); + } } } Constant *OverflowSize = @@ -3380,7 +3413,18 @@ struct VarArgAMD64Helper : public VarArgHelper { Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), - "_msarg"); + "_msarg_va_s"); + } + + /// Compute the origin address for a given va_arg. + Value *getOriginPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, int ArgOffset) { + Value *Base = IRB.CreatePointerCast(MS.VAArgOriginTLS, MS.IntptrTy); + // getOriginPtrForVAArgument() is always called after + // getShadowPtrForVAArgument(), so __msan_va_arg_origin_tls can never + // overflow. + Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); + return IRB.CreateIntToPtr(Base, PointerType::get(MS.OriginTy, 0), + "_msarg_va_o"); } void unpoisonVAListTagForInst(IntrinsicInst &I) { @@ -3425,6 +3469,10 @@ struct VarArgAMD64Helper : public VarArgHelper { VAArgOverflowSize); VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize); IRB.CreateMemCpy(VAArgTLSCopy, 8, MS.VAArgTLS, 8, CopySize); + if (MS.TrackOrigins) { + VAArgTLSOriginCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize); + IRB.CreateMemCpy(VAArgTLSOriginCopy, 8, MS.VAArgOriginTLS, 8, CopySize); + } } // Instrument va_start. @@ -3446,6 +3494,9 @@ struct VarArgAMD64Helper : public VarArgHelper { Alignment, /*isStore*/ true); IRB.CreateMemCpy(RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment, AMD64FpEndOffset); + if (MS.TrackOrigins) + IRB.CreateMemCpy(RegSaveAreaOriginPtr, Alignment, VAArgTLSOriginCopy, + Alignment, AMD64FpEndOffset); Value *OverflowArgAreaPtrPtr = IRB.CreateIntToPtr( IRB.CreateAdd(IRB.CreatePtrToInt(VAListTag, MS.IntptrTy), ConstantInt::get(MS.IntptrTy, 8)), @@ -3459,6 +3510,12 @@ struct VarArgAMD64Helper : public VarArgHelper { AMD64FpEndOffset); IRB.CreateMemCpy(OverflowArgAreaShadowPtr, Alignment, SrcPtr, Alignment, VAArgOverflowSize); + if (MS.TrackOrigins) { + SrcPtr = IRB.CreateConstGEP1_32(IRB.getInt8Ty(), VAArgTLSOriginCopy, + AMD64FpEndOffset); + IRB.CreateMemCpy(OverflowArgAreaOriginPtr, Alignment, SrcPtr, Alignment, + VAArgOverflowSize); + } } } }; |