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); } @@ -626,6 +628,10 @@ SetAllocaOrigin(a, size, id_ptr, descr, GET_CALLER_PC()); } +void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr) { + SetAllocaOrigin(a, size, id_ptr, nullptr, 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,8 @@ void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr, char *descr); SANITIZER_INTERFACE_ATTRIBUTE +void __msan_set_alloca_origin_no_descr(void *a, uptr size, u32 *id_ptr); +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) StackTrace(&pc, 1).Print(); 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 MsanSetAllocaOriginWithDescriptionFn; + // No description version + FunctionCallee MsanSetAllocaOriginNoDescriptionFn; /// Run-time helper that poisons stack on function entry. FunctionCallee MsanPoisonStackFn; @@ -828,6 +834,9 @@ MsanSetAllocaOriginWithDescriptionFn = M.getOrInsertFunction( "__msan_set_alloca_origin_with_descr", 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); @@ -3904,11 +3913,17 @@ if (PoisonStack && MS.TrackOrigins) { Value *Idptr = getLocalVarIdptr(I); - Value *Descr = getLocalVarDescription(I); - IRB.CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn, - {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.MsanSetAllocaOriginWithDescriptionFn, + {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 \ @@ -14,7 +16,9 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; ORIGIN: [[D:@[0-9]+]] = private constant [9 x i8] c"unique_x\00" +; ORIGIN: [[IDPTR:@[0-9]+]] = private global i32 0 +; ORIGIN-LEAN: [[IDPTR:@[0-9]+]] = private global i32 0 +; ORIGIN: [[DESCR:@[0-9]+]] = private constant [9 x i8] c"unique_x\00" define void @static() sanitize_memory { entry: @@ -25,7 +29,8 @@ ; CHECK-LABEL: define void @static( ; 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_origin_with_descr(i8* {{.*}}, i64 4, i8* {{.*}} [[D]], +; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4, i8* {{.*}} [[IDPTR]] {{.*}}, i8* {{.*}} [[DESCR]], +; ORIGIN-LEAN: call void @__msan_set_alloca_origin_no_descr(i8* {{.*}}, i64 4, i8* {{.*}} [[IDPTR]] ; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4, ; CHECK: ret void @@ -42,6 +47,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_origin_with_descr(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 @@ -55,6 +61,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_origin_with_descr(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 @@ -69,6 +76,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_origin_with_descr(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 @@ -83,6 +91,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_origin_with_descr(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 @@ -112,12 +121,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_origin_with_descr(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_origin_with_descr(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 @@ -139,6 +150,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_origin_with_descr(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 @@ -179,22 +191,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_origin_with_descr(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_origin_with_descr(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_origin_with_descr(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_origin_with_descr(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: @@ -202,12 +218,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_origin_with_descr(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_origin_with_descr(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