diff --git a/compiler-rt/lib/msan/msan.cpp b/compiler-rt/lib/msan/msan.cpp --- a/compiler-rt/lib/msan/msan.cpp +++ b/compiler-rt/lib/msan/msan.cpp @@ -323,10 +323,12 @@ id = Origin::CreateStackOrigin(idx).raw_id(); *id_ptr = id; if (print) - Printf("First time: idx=%d id=%d %s 0x%zx \n", idx, id, descr, pc); + Printf("First time: idx=%d id=%d %s 0x%zx \n", idx, id, + descr == nullptr ? "" : descr, pc); } if (print) - Printf("SetAllocaOrigin: descr=%s id=%x\n", descr, id); + Printf("SetAllocaOrigin: descr=%s id=%x\n", descr == nullptr ? "" : descr, + id); __msan_set_origin(a, size, id); } @@ -627,6 +629,12 @@ StackTrace::GetPreviousInstructionPc(GET_CALLER_PC())); } +void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr, + uptr pc) { + SetAllocaOrigin(a, size, id_ptr, nullptr, + StackTrace::GetPreviousInstructionPc(GET_CALLER_PC())); +} + u32 __msan_chain_origin(u32 id) { GET_CALLER_PC_BP_SP; (void)sp; diff --git a/compiler-rt/lib/msan/msan_interface_internal.h b/compiler-rt/lib/msan/msan_interface_internal.h --- a/compiler-rt/lib/msan/msan_interface_internal.h +++ b/compiler-rt/lib/msan/msan_interface_internal.h @@ -112,6 +112,9 @@ void __msan_set_alloca_origin5(void *a, uptr size, u32 *id_ptr, char *descr, uptr pc); SANITIZER_INTERFACE_ATTRIBUTE +void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr, + uptr pc); +SANITIZER_INTERFACE_ATTRIBUTE u32 __msan_chain_origin(u32 id); SANITIZER_INTERFACE_ATTRIBUTE u32 __msan_get_origin(const void *a); diff --git a/compiler-rt/lib/msan/msan_report.cpp b/compiler-rt/lib/msan/msan_report.cpp --- a/compiler-rt/lib/msan/msan_report.cpp +++ b/compiler-rt/lib/msan/msan_report.cpp @@ -37,10 +37,15 @@ static void DescribeStackOrigin(const char *so, uptr pc) { Decorator d; Printf("%s", d.Origin()); - Printf( - " %sUninitialized value was created by an allocation of '%s%s%s'" - " in the stack frame%s\n", - d.Origin(), d.Name(), so, d.Origin(), d.Default()); + if (so == nullptr) { + Printf(" %sUninitialized value was created in the stack frame%s\n", + d.Origin(), d.Default()); + } else { + Printf( + " %sUninitialized value was created by an allocation of '%s%s%s'" + " in the stack frame%s\n", + d.Origin(), d.Name(), so, d.Origin(), d.Default()); + } if (pc) { // For some reason function address in LLVM IR is 1 less then the address diff --git a/compiler-rt/test/msan/stack-origin.cpp b/compiler-rt/test/msan/stack-origin.cpp --- a/compiler-rt/test/msan/stack-origin.cpp +++ b/compiler-rt/test/msan/stack-origin.cpp @@ -8,13 +8,16 @@ // RUN: FileCheck %s < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefixes=CHECK-ORIGINS,ORIGINS-FAT < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins -O1 %s -o %t && not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefixes=CHECK-ORIGINS,ORIGINS-FAT < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins -O2 %s -o %t && not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefixes=CHECK-ORIGINS,ORIGINS-FAT < %t.out // RUN: %clangxx_msan -fsanitize-memory-track-origins -O3 %s -o %t && not %run %t >%t.out 2>&1 -// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefix=CHECK-ORIGINS < %t.out +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefixes=CHECK-ORIGINS,ORIGINS-FAT < %t.out + +// RUN: %clangxx_msan -fsanitize-memory-track-origins -mllvm -msan-print-stack-names=0 -O0 %s -o %t && not %run %t >%t.out 2>&1 +// RUN: FileCheck %s < %t.out && FileCheck %s --check-prefixes=CHECK-ORIGINS,ORIGINS-LEAN < %t.out #include int main(int argc, char **argv) { @@ -24,8 +27,9 @@ // CHECK: WARNING: MemorySanitizer: use-of-uninitialized-value // CHECK: {{#0 0x.* in main .*stack-origin.cpp:}}[[@LINE-2]] - // CHECK-ORIGINS: Uninitialized value was created by an allocation of 'x' in the stack frame - // CHECK-ORIGINS: {{#0 0x.* in main .*stack-origin.cpp:}}[[@LINE-7]] + // ORIGINS-FAT: Uninitialized value was created by an allocation of 'x' in the stack frame + // ORIGINS-LEAN: Uninitialized value was created in the stack frame + // CHECK-ORIGINS: {{#0 0x.* in main .*stack-origin.cpp:}}[[@LINE-8]] // CHECK: SUMMARY: MemorySanitizer: use-of-uninitialized-value {{.*stack-origin.cpp:.* main}} } 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 @@ -237,6 +237,10 @@ cl::desc("poison uninitialized stack variables with the given pattern"), cl::Hidden, cl::init(0xff)); +static cl::opt ClPrintStackNames("msan-print-stack-names", + cl::desc("Print name of local stack variable"), + cl::Hidden, cl::init(true)); + static cl::opt ClPoisonUndef("msan-poison-undef", cl::desc("poison undef temps"), cl::Hidden, cl::init(true)); @@ -580,6 +584,8 @@ /// Run-time helper that generates a new origin value for a stack /// allocation. FunctionCallee MsanSetAllocaOrigin5Fn; + // No description version + FunctionCallee MsanSetAllocaOriginNoDescriptionFn; /// Run-time helper that poisons stack on function entry. FunctionCallee MsanPoisonStackFn; @@ -826,8 +832,11 @@ } MsanSetAllocaOrigin5Fn = M.getOrInsertFunction( - "__msan_set_alloca_origin5", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy, - IRB.getInt8PtrTy(), IRB.getInt8PtrTy()); + "__msan_set_alloca_origin5", IRB.getVoidTy(), IRB.getInt8PtrTy(), + IntptrTy, IRB.getInt8PtrTy(), IRB.getInt8PtrTy()); + MsanSetAllocaOriginNoDescriptionFn = M.getOrInsertFunction( + "__msan_set_alloca_origin_no_descr", IRB.getVoidTy(), IRB.getInt8PtrTy(), + IntptrTy, IRB.getInt8PtrTy()); MsanPoisonStackFn = M.getOrInsertFunction("__msan_poison_stack", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy); @@ -3894,11 +3903,17 @@ if (PoisonStack && MS.TrackOrigins) { Value *Idptr = getLocalVarIdptr(I); - Value *Descr = getLocalVarDescription(I); - IRB.CreateCall(MS.MsanSetAllocaOrigin5Fn, - {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, - IRB.CreatePointerCast(Idptr, IRB.getInt8PtrTy()), - IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())}); + if (ClPrintStackNames) { + Value *Descr = getLocalVarDescription(I); + IRB.CreateCall(MS.MsanSetAllocaOrigin5Fn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Idptr, IRB.getInt8PtrTy()), + IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())}); + } else { + IRB.CreateCall(MS.MsanSetAllocaOriginNoDescriptionFn, + {IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len, + IRB.CreatePointerCast(Idptr, IRB.getInt8PtrTy())}); + } } } diff --git a/llvm/test/Instrumentation/MemorySanitizer/alloca.ll b/llvm/test/Instrumentation/MemorySanitizer/alloca.ll --- a/llvm/test/Instrumentation/MemorySanitizer/alloca.ll +++ b/llvm/test/Instrumentation/MemorySanitizer/alloca.ll @@ -6,6 +6,8 @@ ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" ; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S \ ; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN" +; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -msan-print-stack-names=false -S \ +; RUN: -passes=msan 2>&1 | FileCheck %s "--check-prefixes=CHECK,ORIGIN-LEAN" ; RUN: opt < %s -S -passes="msan" 2>&1 | FileCheck %s \ ; RUN: "--check-prefixes=CHECK,KMSAN" ; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \ @@ -24,6 +26,7 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -40,6 +43,7 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -53,6 +57,7 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 20, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 20) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 20, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 20, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 20, ; CHECK: ret void @@ -67,6 +72,7 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 %[[A]], +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 %[[A]], ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], ; CHECK: ret void @@ -81,6 +87,7 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) ; CALL: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false) ; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 20, +; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 20, ; KMSAN: call void @__msan_unpoison_alloca(i8* {{.*}}, i64 20) ; CHECK: ret void @@ -110,12 +117,14 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.start ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -137,6 +146,7 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]]) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 %[[A]], +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 %[[A]], ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]], ; CHECK: call void @llvm.lifetime.end ; CHECK: ret void @@ -177,22 +187,26 @@ ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: %y = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: %z = alloca i32 ; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; There're two lifetime intrinsics for %z, but we must instrument it only once. ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK-LABEL: another_bb: @@ -200,12 +214,14 @@ ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end ; CHECK: call void @llvm.lifetime.start ; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false) ; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4) ; ORIGIN-NOT: call void @__msan_set_alloca_origin5(i8* {{.*}}, i64 4, +; ORIGIN-LEAN-NOT: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, ; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: call void @llvm.lifetime.end