diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index cfe993dedbc2e..c51acdf52f14d 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -182,6 +182,7 @@ #include "llvm/IR/ValueMap.h" #include "llvm/InitializePasses.h" #include "llvm/Pass.h" +#include "llvm/Support/Alignment.h" #include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -1718,11 +1719,10 @@ struct MemorySanitizerVisitor : public InstVisitor { // Figure out maximal valid memcpy alignment. const Align ArgAlign = DL.getValueOrABITypeAlignment( MaybeAlign(FArg.getParamAlignment()), FArg.getParamByValType()); - Value *CpShadowPtr = + Value *CpShadowPtr, *CpOriginPtr; + std::tie(CpShadowPtr, CpOriginPtr) = getShadowOriginPtr(V, EntryIRB, EntryIRB.getInt8Ty(), ArgAlign, - /*isStore*/ true) - .first; - // TODO(glider): need to copy origins. + /*isStore*/ true); if (!PropagateShadow || Overflow) { // ParamTLS overflow. EntryIRB.CreateMemSet( @@ -1735,6 +1735,19 @@ struct MemorySanitizerVisitor : public InstVisitor { CopyAlign, Size); LLVM_DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n"); (void)Cpy; + + if (MS.TrackOrigins) { + Value *OriginPtr = + getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset); + // FIXME: OriginSize should be: + // alignTo(V % kMinOriginAlignment + Size, kMinOriginAlignment) + unsigned OriginSize = alignTo(Size, kMinOriginAlignment); + EntryIRB.CreateMemCpy( + CpOriginPtr, + /* by getShadowOriginPtr */ kMinOriginAlignment, OriginPtr, + /* by origin_tls[ArgOffset] */ kMinOriginAlignment, + OriginSize); + } } } @@ -3701,7 +3714,6 @@ struct MemorySanitizerVisitor : public InstVisitor { insertShadowCheck(A, &CB); Size = DL.getTypeAllocSize(A->getType()); } else { - bool ArgIsInitialized = false; Value *Store = nullptr; // Compute the Shadow for arg even if it is ByVal, because // in that case getShadow() will copy the actual arg shadow to @@ -3722,10 +3734,10 @@ struct MemorySanitizerVisitor : public InstVisitor { MaybeAlign Alignment = llvm::None; if (ParamAlignment) Alignment = std::min(*ParamAlignment, kShadowTLSAlignment); - Value *AShadowPtr = + Value *AShadowPtr, *AOriginPtr; + std::tie(AShadowPtr, AOriginPtr) = getShadowOriginPtr(A, IRB, IRB.getInt8Ty(), Alignment, - /*isStore*/ false) - .first; + /*isStore*/ false); if (!PropagateShadow) { Store = IRB.CreateMemSet(ArgShadowBase, Constant::getNullValue(IRB.getInt8Ty()), @@ -3733,6 +3745,17 @@ struct MemorySanitizerVisitor : public InstVisitor { } else { Store = IRB.CreateMemCpy(ArgShadowBase, Alignment, AShadowPtr, Alignment, Size); + if (MS.TrackOrigins) { + Value *ArgOriginBase = getOriginPtrForArgument(A, IRB, ArgOffset); + // FIXME: OriginSize should be: + // alignTo(A % kMinOriginAlignment + Size, kMinOriginAlignment) + unsigned OriginSize = alignTo(Size, kMinOriginAlignment); + IRB.CreateMemCpy( + ArgOriginBase, + /* by origin_tls[ArgOffset] */ kMinOriginAlignment, + AOriginPtr, + /* by getShadowOriginPtr */ kMinOriginAlignment, OriginSize); + } } } else { // Any other parameters mean we need bit-grained tracking of uninit @@ -3743,12 +3766,11 @@ struct MemorySanitizerVisitor : public InstVisitor { Store = IRB.CreateAlignedStore(ArgShadow, ArgShadowBase, kShadowTLSAlignment); Constant *Cst = dyn_cast(ArgShadow); - if (Cst && Cst->isNullValue()) - ArgIsInitialized = true; + if (MS.TrackOrigins && !(Cst && Cst->isNullValue())) { + IRB.CreateStore(getOrigin(A), + getOriginPtrForArgument(A, IRB, ArgOffset)); + } } - if (MS.TrackOrigins && !ArgIsInitialized) - IRB.CreateStore(getOrigin(A), - getOriginPtrForArgument(A, IRB, ArgOffset)); (void)Store; assert(Store != nullptr); LLVM_DEBUG(dbgs() << " Param:" << *Store << "\n"); diff --git a/llvm/test/Instrumentation/MemorySanitizer/byval.ll b/llvm/test/Instrumentation/MemorySanitizer/byval.ll index efc03af25674c..8f150e9b1a6db 100644 --- a/llvm/test/Instrumentation/MemorySanitizer/byval.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/byval.ll @@ -1,4 +1,3 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -S -passes="msan" 2>&1 | FileCheck %s --implicit-check-not "call void @llvm.mem" --implicit-check-not " load" --implicit-check-not " store" ; RUN: opt < %s -S -msan -msan-track-origins=1 | FileCheck %s --implicit-check-not "call void @llvm.mem" --implicit-check-not " load" --implicit-check-not " store" @@ -12,6 +11,7 @@ define i128 @ByValArgument(i32, i128* byval(i128) %p) sanitize_memory { ; CHECK-LABEL: @ByValArgument( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[#]], i8* align 8 inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i8*), i64 16, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[#]], i8* align 4 inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i8*), i64 16, i1 false) ; CHECK: [[X:%.*]] = load i128, i128* %p, align 8 ; CHECK: [[_MSLD:%.*]] = load i128, i128* %[[#]], align 8 ; CHECK: %[[#]] = load i32, i32* %[[#]], align 8 @@ -38,11 +38,11 @@ entry: ret i128 %x } -; FIXME: Origin of byval pointee is not propagated. define void @ByValForward(i32, i128* byval(i128) %p) sanitize_memory { ; CHECK-LABEL: @ByValForward( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[#]], i8* align 8 inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i8*), i64 16, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[#]], i8* align 4 inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i8*), i64 16, i1 false) ; CHECK: store i64 0, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @__msan_param_tls, i32 0, i32 0), align 8 ; CHECK: call void @Fn(i128* %p) ; CHECK: ret void @@ -65,13 +65,13 @@ entry: ret void } -; FIXME: Origin of %p byval pointee is not propagated. define void @ByValForwardByVal(i32, i128* byval(i128) %p) sanitize_memory { ; CHECK-LABEL: @ByValForwardByVal( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %[[#]], i8* align 8 inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i8*), i64 16, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[#]], i8* align 4 inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i8*), i64 16, i1 false) ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([100 x i64]* @__msan_param_tls to i8*), i8* %[[#]], i64 16, i1 false) -; CHECK: store i32 0, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__msan_param_origin_tls, i32 0, i32 0), align 4 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast ([200 x i32]* @__msan_param_origin_tls to i8*), i8* align 4 %[[#]], i64 16, i1 false) ; CHECK: call void @FnByVal(i128* byval(i128) %p) ; CHECK: ret void ; @@ -85,7 +85,6 @@ define void @ByValForwardByValNoSanitize(i32, i128* byval(i128) %p) { ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 %[[#]], i8 0, i64 16, i1 false) ; CHECK: call void @llvm.memset.p0i8.i64(i8* bitcast ([100 x i64]* @__msan_param_tls to i8*), i8 0, i64 16, i1 false) -; CHECK: store i32 0, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__msan_param_origin_tls, i32 0, i32 0), align 4 ; CHECK: call void @FnByVal(i128* byval(i128) %p) ; CHECK: ret void ; @@ -101,6 +100,7 @@ define i8 @ByValArgument8(i32, i8* byval(i8) %p) sanitize_memory { ; CHECK-LABEL: @ByValArgument8( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %[[#]], i8* align 1 inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i8*), i64 1, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[#]], i8* align 4 inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i8*), i64 4, i1 false) ; CHECK: [[X:%.*]] = load i8, i8* %p, align 1 ; CHECK: [[_MSLD:%.*]] = load i8, i8* %[[#]], align 1 ; CHECK: %[[#]] = load i32, i32* %[[#]], align 4 @@ -131,6 +131,7 @@ define void @ByValForward8(i32, i8* byval(i8) %p) sanitize_memory { ; CHECK-LABEL: @ByValForward8( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %[[#]], i8* align 1 inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i8*), i64 1, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[#]], i8* align 4 inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i8*), i64 4, i1 false) ; CHECK: store i64 0, i64* getelementptr inbounds ([100 x i64], [100 x i64]* @__msan_param_tls, i32 0, i32 0), align 8 ; CHECK: call void @Fn8(i8* %p) ; CHECK: ret void @@ -157,8 +158,9 @@ define void @ByValForwardByVal8(i32, i8* byval(i8) %p) sanitize_memory { ; CHECK-LABEL: @ByValForwardByVal8( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %[[#]], i8* align 1 inttoptr (i64 add (i64 ptrtoint ([100 x i64]* @__msan_param_tls to i64), i64 8) to i8*), i64 1, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %[[#]], i8* align 4 inttoptr (i64 add (i64 ptrtoint ([200 x i32]* @__msan_param_origin_tls to i64), i64 8) to i8*), i64 4, i1 false) ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([100 x i64]* @__msan_param_tls to i8*), i8* %[[#]], i64 1, i1 false) -; CHECK: store i32 0, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__msan_param_origin_tls, i32 0, i32 0), align 4 +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 bitcast ([200 x i32]* @__msan_param_origin_tls to i8*), i8* align 4 %[[#]], i64 4, i1 false) ; CHECK: call void @FnByVal8(i8* byval(i8) %p) ; CHECK: ret void ; @@ -167,13 +169,11 @@ entry: ret void } -; FIXME: Shadow for byval should be reset not copied before the call. define void @ByValForwardByValNoSanitize8(i32, i8* byval(i8) %p) { ; CHECK-LABEL: @ByValForwardByValNoSanitize8( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memset.p0i8.i64(i8* align 1 %[[#]], i8 0, i64 1, i1 false) ; CHECK: call void @llvm.memset.p0i8.i64(i8* bitcast ([100 x i64]* @__msan_param_tls to i8*), i8 0, i64 1, i1 false) -; CHECK: store i32 0, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__msan_param_origin_tls, i32 0, i32 0), align 4 ; CHECK: call void @FnByVal8(i8* byval(i8) %p) ; CHECK: ret void ;