Index: lib/Transforms/Instrumentation/MemorySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -557,6 +557,9 @@ /// MSan runtime replacements for memmove, memcpy and memset. Value *MemmoveFn, *MemcpyFn, *MemsetFn; + /// _nosanitize variants of memmove, memcpy and memset for use in + /// non-sanitized functions. + Value *MemmoveNosanFn, *MemcpyNosanFn, *MemsetNosanFn; /// KMSAN callback for task-local function argument shadow. Value *MsanGetContextStateFn; @@ -773,6 +776,17 @@ MemsetFn = M.getOrInsertFunction( "__msan_memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy); + + MemmoveNosanFn = + M.getOrInsertFunction("__msan_memmove_nosanitize", IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); + MemcpyNosanFn = + M.getOrInsertFunction("__msan_memcpy_nosanitize", IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); + MemsetNosanFn = + M.getOrInsertFunction("__msan_memset_nosanitize", IRB.getInt8PtrTy(), + IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy); + // We insert an empty inline asm after __msan_report* to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), StringRef(""), StringRef(""), @@ -970,6 +984,7 @@ // blacklist contents and command-line options. bool InsertChecks; bool PropagateShadow; + bool InstrumentMemIntrinsics; bool PoisonStack; bool PoisonUndef; bool CheckReturnValue; @@ -990,6 +1005,7 @@ bool SanitizeFunction = F.hasFnAttribute(Attribute::SanitizeMemory); InsertChecks = SanitizeFunction; PropagateShadow = SanitizeFunction; + InstrumentMemIntrinsics = SanitizeFunction; PoisonStack = SanitizeFunction && ClPoisonStack; PoisonUndef = SanitizeFunction && ClPoisonUndef; // FIXME: Consider using SpecialCaseList to specify a list of functions that @@ -2324,7 +2340,7 @@ void visitMemMoveInst(MemMoveInst &I) { IRBuilder<> IRB(&I); IRB.CreateCall( - MS.MemmoveFn, + InstrumentMemIntrinsics ? MS.MemmoveFn : MS.MemmoveNosanFn, {IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()), IRB.CreatePointerCast(I.getArgOperand(1), IRB.getInt8PtrTy()), IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)}); @@ -2338,7 +2354,7 @@ void visitMemCpyInst(MemCpyInst &I) { IRBuilder<> IRB(&I); IRB.CreateCall( - MS.MemcpyFn, + InstrumentMemIntrinsics ? MS.MemcpyFn : MS.MemcpyNosanFn, {IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()), IRB.CreatePointerCast(I.getArgOperand(1), IRB.getInt8PtrTy()), IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)}); @@ -2349,7 +2365,7 @@ void visitMemSetInst(MemSetInst &I) { IRBuilder<> IRB(&I); IRB.CreateCall( - MS.MemsetFn, + InstrumentMemIntrinsics ? MS.MemsetFn : MS.MemsetNosanFn, {IRB.CreatePointerCast(I.getArgOperand(0), IRB.getInt8PtrTy()), IRB.CreateIntCast(I.getArgOperand(1), IRB.getInt32Ty(), false), IRB.CreateIntCast(I.getArgOperand(2), MS.IntptrTy, false)}); Index: test/Instrumentation/MemorySanitizer/msan_basic.ll =================================================================== --- test/Instrumentation/MemorySanitizer/msan_basic.ll +++ test/Instrumentation/MemorySanitizer/msan_basic.ll @@ -210,6 +210,16 @@ ; CHECK: call i8* @__msan_memset ; CHECK: ret void +; _nosanitize version of memset +define void @MemSetNosanitize(i8* nocapture %x) nounwind uwtable { +entry: + call void @llvm.memset.p0i8.i64(i8* %x, i8 42, i64 10, i1 false) + ret void +} + +; CHECK-LABEL: @MemSetNosanitize +; CHECK: call i8* @__msan_memset_nosanitize +; CHECK: ret void ; memcpy define void @MemCpy(i8* nocapture %x, i8* nocapture %y) nounwind uwtable sanitize_memory { @@ -224,6 +234,16 @@ ; CHECK: call i8* @__msan_memcpy ; CHECK: ret void +; _nosanitize version of memcpy +define void @MemCpyNosanitize(i8* nocapture %x, i8* nocapture %y) nounwind uwtable { +entry: + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %x, i8* %y, i64 10, i1 false) + ret void +} + +; CHECK-LABEL: @MemCpyNosanitize +; CHECK: call i8* @__msan_memcpy_nosanitize +; CHECK: ret void ; memmove is lowered to a call define void @MemMove(i8* nocapture %x, i8* nocapture %y) nounwind uwtable sanitize_memory { @@ -238,6 +258,16 @@ ; CHECK: call i8* @__msan_memmove ; CHECK: ret void +define void @MemMoveNosanitize(i8* nocapture %x, i8* nocapture %y) nounwind uwtable { +entry: + call void @llvm.memmove.p0i8.p0i8.i64(i8* %x, i8* %y, i64 10, i1 false) + ret void +} + +; CHECK-LABEL: @MemMoveNosanitize +; CHECK: call i8* @__msan_memmove_nosanitize +; CHECK: ret void + ;; ------------ ;; Placeholder tests that will fail once element atomic @llvm.mem[cpy|move|set] instrinsics have ;; been added to the MemIntrinsic class hierarchy. These will act as a reminder to