Skip to content

Commit ec277b6

Browse files
committed
[MSAN] Separate id ptr from constant string for variable names used in track origins.
The goal is to reduce the size of the MSAN with track origins binary, by making the variable name locations constant which will allow the linker to compress them. Follows: https://reviews.llvm.org/D131415 Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D131631
1 parent bc56f63 commit ec277b6

File tree

4 files changed

+56
-42
lines changed

4 files changed

+56
-42
lines changed

compiler-rt/lib/msan/msan.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -303,19 +303,21 @@ u32 ChainOrigin(u32 id, StackTrace *stack) {
303303
return chained.raw_id();
304304
}
305305

306-
// 'descr' is created at compile time and contains '----' in the beginning.
307-
// When we see descr for the first time we replace '----' with a uniq id
308-
// and set the origin to (id | (31-th bit)).
309-
static inline void SetAllocaOrigin(void *a, uptr size, char *descr, uptr pc) {
306+
// Current implementation separates the 'id_ptr' from the 'descr' and makes
307+
// 'descr' constant.
308+
// Previous implementation 'descr' is created at compile time and contains
309+
// '----' in the beginning. When we see descr for the first time we replace
310+
// '----' with a uniq id and set the origin to (id | (31-th bit)).
311+
static inline void SetAllocaOrigin(void *a, uptr size, u32 *id_ptr, char *descr,
312+
uptr pc) {
310313
static const u32 dash = '-';
311314
static const u32 first_timer =
312315
dash + (dash << 8) + (dash << 16) + (dash << 24);
313-
u32 *id_ptr = (u32 *)descr;
314316
u32 id = *id_ptr;
315-
if (id == first_timer) {
317+
if (id == 0 || id == first_timer) {
316318
u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed);
317319
CHECK_LT(idx, kNumStackOriginDescrs);
318-
StackOriginDescr[idx] = descr + 4;
320+
StackOriginDescr[idx] = descr;
319321
StackOriginPC[idx] = pc;
320322
id = Origin::CreateStackOrigin(idx).raw_id();
321323
*id_ptr = id;
@@ -602,14 +604,21 @@ void __msan_set_origin(const void *a, uptr size, u32 origin) {
602604
}
603605

604606
void __msan_set_alloca_origin(void *a, uptr size, char *descr) {
605-
SetAllocaOrigin(a, size, descr, GET_CALLER_PC());
607+
SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4,
608+
GET_CALLER_PC());
606609
}
607610

608611
void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) {
609612
// Intentionally ignore pc and use return address. This function is here for
610613
// compatibility, in case program is linked with library instrumented by
611614
// older clang.
612-
SetAllocaOrigin(a, size, descr, GET_CALLER_PC());
615+
SetAllocaOrigin(a, size, reinterpret_cast<u32 *>(descr), descr + 4,
616+
GET_CALLER_PC());
617+
}
618+
619+
void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr,
620+
char *descr) {
621+
SetAllocaOrigin(a, size, id_ptr, descr, GET_CALLER_PC());
613622
}
614623

615624
u32 __msan_chain_origin(u32 id) {

compiler-rt/lib/msan/msan_interface_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ void __msan_set_alloca_origin(void *a, uptr size, char *descr);
109109
SANITIZER_INTERFACE_ATTRIBUTE
110110
void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc);
111111
SANITIZER_INTERFACE_ATTRIBUTE
112+
void __msan_set_alloca_origin_with_descr(void *a, uptr size, u32 *id_ptr,
113+
char *descr);
114+
SANITIZER_INTERFACE_ATTRIBUTE
112115
u32 __msan_chain_origin(u32 id);
113116
SANITIZER_INTERFACE_ATTRIBUTE
114117
u32 __msan_get_origin(const void *a);

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ class MemorySanitizer {
579579

580580
/// Run-time helper that generates a new origin value for a stack
581581
/// allocation.
582-
FunctionCallee MsanSetAllocaOriginFn;
582+
FunctionCallee MsanSetAllocaOriginWithDescriptionFn;
583583

584584
/// Run-time helper that poisons stack on function entry.
585585
FunctionCallee MsanPoisonStackFn;
@@ -691,10 +691,10 @@ void MemorySanitizerPass::printPipeline(
691691
/// Creates a writable global for Str so that we can pass it to the
692692
/// run-time lib. Runtime uses first 4 bytes of the string to store the
693693
/// frame ID, so the string needs to be mutable.
694-
static GlobalVariable *createPrivateNonConstGlobalForString(Module &M,
695-
StringRef Str) {
694+
static GlobalVariable *createPrivateConstGlobalForString(Module &M,
695+
StringRef Str) {
696696
Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str);
697-
return new GlobalVariable(M, StrConst->getType(), /*isConstant=*/false,
697+
return new GlobalVariable(M, StrConst->getType(), /*isConstant=*/true,
698698
GlobalValue::PrivateLinkage, StrConst, "");
699699
}
700700

@@ -825,9 +825,9 @@ void MemorySanitizer::createUserspaceApi(Module &M) {
825825
IRB.getInt32Ty());
826826
}
827827

828-
MsanSetAllocaOriginFn = M.getOrInsertFunction(
829-
"__msan_set_alloca_origin", IRB.getVoidTy(), IRB.getInt8PtrTy(), IntptrTy,
830-
IRB.getInt8PtrTy());
828+
MsanSetAllocaOriginWithDescriptionFn = M.getOrInsertFunction(
829+
"__msan_set_alloca_origin_with_descr", IRB.getVoidTy(),
830+
IRB.getInt8PtrTy(), IntptrTy, IRB.getInt8PtrTy(), IRB.getInt8PtrTy());
831831
MsanPoisonStackFn =
832832
M.getOrInsertFunction("__msan_poison_stack", IRB.getVoidTy(),
833833
IRB.getInt8PtrTy(), IntptrTy);
@@ -3877,17 +3877,16 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
38773877
"_msphi_o"));
38783878
}
38793879

3880+
Value *getLocalVarIdptr(AllocaInst &I) {
3881+
ConstantInt *IntConst =
3882+
ConstantInt::get(Type::getInt32Ty((*F.getParent()).getContext()), 0);
3883+
return new GlobalVariable(*F.getParent(), IntConst->getType(),
3884+
/*isConstant=*/false, GlobalValue::PrivateLinkage,
3885+
IntConst);
3886+
}
3887+
38803888
Value *getLocalVarDescription(AllocaInst &I) {
3881-
SmallString<2048> StackDescriptionStorage;
3882-
raw_svector_ostream StackDescription(StackDescriptionStorage);
3883-
// We create a string with a description of the stack allocation and
3884-
// pass it into __msan_set_alloca_origin.
3885-
// It will be printed by the run-time if stack-originated UMR is found.
3886-
// The first 4 bytes of the string are set to '----' and will be replaced
3887-
// by __msan_va_arg_overflow_size_tls at the first call.
3888-
StackDescription << "----" << I.getName();
3889-
return createPrivateNonConstGlobalForString(*F.getParent(),
3890-
StackDescription.str());
3889+
return createPrivateConstGlobalForString(*F.getParent(), I.getName());
38913890
}
38923891

38933892
void poisonAllocaUserspace(AllocaInst &I, IRBuilder<> &IRB, Value *Len) {
@@ -3904,9 +3903,11 @@ struct MemorySanitizerVisitor : public InstVisitor<MemorySanitizerVisitor> {
39043903
}
39053904

39063905
if (PoisonStack && MS.TrackOrigins) {
3906+
Value *Idptr = getLocalVarIdptr(I);
39073907
Value *Descr = getLocalVarDescription(I);
3908-
IRB.CreateCall(MS.MsanSetAllocaOriginFn,
3908+
IRB.CreateCall(MS.MsanSetAllocaOriginWithDescriptionFn,
39093909
{IRB.CreatePointerCast(&I, IRB.getInt8PtrTy()), Len,
3910+
IRB.CreatePointerCast(Idptr, IRB.getInt8PtrTy()),
39103911
IRB.CreatePointerCast(Descr, IRB.getInt8PtrTy())});
39113912
}
39123913
}

llvm/test/Instrumentation/MemorySanitizer/alloca.ll

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
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"
1515
target triple = "x86_64-unknown-linux-gnu"
1616

17-
; ORIGIN: [[D:@[0-9]+]] = private global [13 x i8] c"----unique_x\00"
17+
; ORIGIN: [[IDPTR:@[0-9]+]] = private global i32 0
18+
; ORIGIN: [[DESCR:@[0-9]+]] = private constant [9 x i8] c"unique_x\00"
1819

1920
define void @static() sanitize_memory {
2021
entry:
@@ -25,7 +26,7 @@ entry:
2526
; CHECK-LABEL: define void @static(
2627
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
2728
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
28-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4, i8* {{.*}} [[D]],
29+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4, i8* {{.*}} [[IDPTR]] {{.*}}, i8* {{.*}} [[DESCR]],
2930
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
3031
; CHECK: ret void
3132

@@ -41,7 +42,7 @@ l:
4142
; CHECK-LABEL: define void @dynamic(
4243
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
4344
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
44-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
45+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
4546
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
4647
; CHECK: ret void
4748

@@ -54,7 +55,7 @@ entry:
5455
; CHECK-LABEL: define void @array(
5556
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 20, i1 false)
5657
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 20)
57-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 20,
58+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 20,
5859
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 20,
5960
; CHECK: ret void
6061

@@ -68,7 +69,7 @@ entry:
6869
; CHECK: %[[A:.*]] = mul i64 4, %cnt
6970
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false)
7071
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]])
71-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 %[[A]],
72+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 %[[A]],
7273
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]],
7374
; CHECK: ret void
7475

@@ -82,7 +83,7 @@ entry:
8283
; CHECK-LABEL: define void @unpoison_local(
8384
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false)
8485
; CALL: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 0, i64 20, i1 false)
85-
; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 20,
86+
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 20,
8687
; KMSAN: call void @__msan_unpoison_alloca(i8* {{.*}}, i64 20)
8788
; CHECK: ret void
8889

@@ -111,13 +112,13 @@ another_bb:
111112
; CHECK: call void @llvm.lifetime.start
112113
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
113114
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
114-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
115+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
115116
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
116117

117118
; CHECK: call void @llvm.lifetime.start
118119
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
119120
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
120-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
121+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
121122
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
122123
; CHECK: ret void
123124

@@ -138,7 +139,7 @@ entry:
138139
; CHECK: %[[A:.*]] = mul i64 4, %cnt
139140
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 %[[A]], i1 false)
140141
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 %[[A]])
141-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 %[[A]],
142+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 %[[A]],
142143
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 %[[A]],
143144
; CHECK: call void @llvm.lifetime.end
144145
; CHECK: ret void
@@ -178,36 +179,36 @@ another_bb:
178179
; CHECK: %x = alloca i32
179180
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
180181
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
181-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
182+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
182183
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
183184
; CHECK: %y = alloca i32
184185
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
185186
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
186-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
187+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
187188
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
188189
; CHECK: %z = alloca i32
189190
; INLINE: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
190191
; CALL: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
191-
; ORIGIN: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
192+
; ORIGIN: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
192193
; KMSAN: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
193194

194195
; There're two lifetime intrinsics for %z, but we must instrument it only once.
195196
; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
196197
; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
197-
; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
198+
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
198199
; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
199200
; CHECK-LABEL: another_bb:
200201

201202
; CHECK: call void @llvm.lifetime.start
202203
; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
203204
; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
204-
; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
205+
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
205206
; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
206207
; CHECK: call void @llvm.lifetime.end
207208
; CHECK: call void @llvm.lifetime.start
208209
; INLINE-NOT: call void @llvm.memset.p0i8.i64(i8* align 4 {{.*}}, i8 -1, i64 4, i1 false)
209210
; CALL-NOT: call void @__msan_poison_stack(i8* {{.*}}, i64 4)
210-
; ORIGIN-NOT: call void @__msan_set_alloca_origin(i8* {{.*}}, i64 4,
211+
; ORIGIN-NOT: call void @__msan_set_alloca_origin_with_descr(i8* {{.*}}, i64 4,
211212
; KMSAN-NOT: call void @__msan_poison_alloca(i8* {{.*}}, i64 4,
212213
; CHECK: call void @llvm.lifetime.end
213214

0 commit comments

Comments
 (0)