diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -1718,11 +1718,10 @@ // 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 +1734,13 @@ CopyAlign, Size); LLVM_DEBUG(dbgs() << " ByValCpy: " << *Cpy << "\n"); (void)Cpy; + + if (MS.TrackOrigins) { + Value *OriginPtr = + getOriginPtrForArgument(&FArg, EntryIRB, ArgOffset); + EntryIRB.CreateMemCpy(CpOriginPtr, CopyAlign, OriginPtr, + CopyAlign, Size); + } } } @@ -3701,7 +3707,6 @@ 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,14 +3727,19 @@ 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); Store = IRB.CreateMemCpy(ArgShadowBase, Alignment, AShadowPtr, Alignment, Size); - // TODO(glider): need to copy origins. + if (MS.TrackOrigins) { + Value *ArgOriginBase = getOriginPtrForArgument(A, IRB, ArgOffset); + + Store = IRB.CreateMemCpy(ArgOriginBase, Alignment, AOriginPtr, + Alignment, Size); + } } else { // Any other parameters mean we need bit-grained tracking of uninit // data @@ -3739,12 +3749,11 @@ 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 --- a/llvm/test/Instrumentation/MemorySanitizer/byval.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/byval.ll @@ -11,6 +11,7 @@ ; CHECK-LABEL: @ByValArgument( ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} @__msan_param_tls to i64), i64 8) to i8*), i64 16, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} @__msan_param_origin_tls to i64), i64 8) to i8*), i64 16, i1 false) ; CHECK: %x = load i128, i128* %p ; CHECK: load i128 ; CHECK: load i32 @@ -37,11 +38,11 @@ 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({{.*}} @__msan_param_tls to i64), i64 8) to i8*), i64 16, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} @__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) ; CHECK-NEXT: call void @Fn( ; CHECK-NEXT: ret void @@ -64,13 +65,13 @@ 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({{.*}} @__msan_param_tls to i64), i64 8) to i8*), i64 16, i1 false) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}} @__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 {{.*}}, i32* getelementptr inbounds ([200 x i32], [200 x i32]* @__msan_param_origin_tls, i32 0, i32 0) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([200 x i32]* @__msan_param_origin_tls to i8*), i8* {{.*}}, i64 16, i1 false) ; CHECK-NEXT: call void @FnByVal( ; CHECK-NEXT: ret void ; @@ -85,7 +86,7 @@ ; CHECK-NEXT: entry: ; CHECK: call void @llvm.memset.p0i8.i64(i8* align 8 {{.*}}, i8 0, 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) +; CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([200 x i32]* @__msan_param_origin_tls to i8*), i8* {{.*}}, i64 16, i1 false) ; CHECK-NEXT: call void @FnByVal( ; CHECK-NEXT: ret void ;