[MSAN] add flag to suppress storage of stack variable names with -sanitize-memory-track-origins

Allows for even more savings in the binary image while simultaneously removing the name of the offending stack variable.

Depends on D131631

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D131728
This commit is contained in:
Kevin Athey 2022-08-11 14:53:38 -07:00
parent ec7e7797b1
commit 532564de17
6 changed files with 62 additions and 15 deletions

View File

@ -621,6 +621,10 @@ void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr,
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;

View File

@ -112,6 +112,8 @@ SANITIZER_INTERFACE_ATTRIBUTE
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);

View File

@ -37,10 +37,15 @@ class Decorator: public __sanitizer::SanitizerCommonDecorator {
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();

View File

@ -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 <stdlib.h>
int main(int argc, char **argv) {
@ -24,8 +27,9 @@ int main(int argc, char **argv) {
// 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}}
}

View File

@ -237,6 +237,10 @@ static cl::opt<int> ClPoisonStackPattern("msan-poison-stack-pattern",
cl::desc("poison uninitialized stack variables with the given pattern"),
cl::Hidden, cl::init(0xff));
static cl::opt<bool> ClPrintStackNames("msan-print-stack-names",
cl::desc("Print name of local stack variable"),
cl::Hidden, cl::init(true));
static cl::opt<bool> ClPoisonUndef("msan-poison-undef",
cl::desc("poison undef temps"),
cl::Hidden, cl::init(true));
@ -580,6 +584,8 @@ private:
/// 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 @@ void MemorySanitizer::createUserspaceApi(Module &M) {
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 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
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())});
}
}
}

View File

@ -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<kernel>" 2>&1 | FileCheck %s \
; RUN: "--check-prefixes=CHECK,KMSAN"
; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \
@ -15,6 +17,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
target triple = "x86_64-unknown-linux-gnu"
; 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 {
@ -27,6 +30,7 @@ entry:
; 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* {{.*}} [[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
@ -43,6 +47,7 @@ l:
; 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
@ -56,6 +61,7 @@ entry:
; 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
@ -70,6 +76,7 @@ entry:
; 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
@ -84,6 +91,7 @@ entry:
; 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
@ -113,12 +121,14 @@ another_bb:
; 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
@ -140,6 +150,7 @@ entry:
; 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
@ -180,22 +191,26 @@ another_bb:
; 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:
@ -203,12 +218,14 @@ another_bb:
; 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