xref: /llvm-project/llvm/test/Instrumentation/MemorySanitizer/msan_kernel_basic.ll (revision fe7f5f9126cea9ceba703d5bd07b766181f2bd72)
1; KMSAN instrumentation tests
2; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK
3
4target 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"
5target triple = "x86_64-unknown-linux-gnu"
6
7; Check the instrumentation prologue.
8define void @Empty() nounwind uwtable sanitize_memory {
9entry:
10  ret void
11}
12
13; CHECK-LABEL: @Empty
14; CHECK: entry:
15; CHECK: @__msan_get_context_state()
16; %param_shadow:
17; CHECK: getelementptr {{.*}} i32 0, i32 0
18; %retval_shadow:
19; CHECK: getelementptr {{.*}} i32 0, i32 1
20; %va_arg_shadow:
21; CHECK: getelementptr {{.*}} i32 0, i32 2
22; %va_arg_origin:
23; CHECK: getelementptr {{.*}} i32 0, i32 3
24; %va_arg_overflow_size:
25; CHECK: getelementptr {{.*}} i32 0, i32 4
26; %param_origin:
27; CHECK: getelementptr {{.*}} i32 0, i32 5
28; %retval_origin:
29; CHECK: getelementptr {{.*}} i32 0, i32 6
30
31; Check instrumentation of stores
32
33define void @Store1(ptr nocapture %p, i8 %x) nounwind uwtable sanitize_memory {
34entry:
35  store i8 %x, ptr %p
36  ret void
37}
38
39; CHECK-LABEL: @Store1
40; CHECK: entry:
41; CHECK: @__msan_get_context_state()
42; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
43; CHECK: [[BASE:%[0-9]+]] = ptrtoint {{.*}} [[PARAM_SHADOW]]
44; CHECK: [[SHADOW_PTR:%[a-z0-9_]+]] = inttoptr {{.*}} [[BASE]]
45; CHECK: [[SHADOW:%[a-z0-9]+]] = load i64, ptr [[SHADOW_PTR]]
46; CHECK: [[BASE2:%[0-9]+]] = ptrtoint {{.*}} [[PARAM_SHADOW]]
47; Load the shadow of %p and check it
48; CHECK: icmp ne i64 [[SHADOW]]
49; CHECK: br i1
50; CHECK: {{^[0-9]+}}:
51; CHECK: @__msan_metadata_ptr_for_store_1(ptr %p)
52; CHECK: store i8
53; If the new shadow is non-zero, jump to __msan_chain_origin()
54; CHECK: icmp
55; CHECK: br i1
56; CHECK: {{^[0-9]+}}:
57; CHECK: @__msan_chain_origin
58; Storing origin here:
59; CHECK: store i32
60; CHECK: br label
61; CHECK: {{^[0-9]+}}:
62; CHECK: store i8
63; CHECK: ret void
64
65define void @Store2(ptr nocapture %p, i16 %x) nounwind uwtable sanitize_memory {
66entry:
67  store i16 %x, ptr %p
68  ret void
69}
70
71; CHECK-LABEL: @Store2
72; CHECK: entry:
73; CHECK: @__msan_get_context_state()
74; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
75; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
76; Load the shadow of %p and check it
77; CHECK: load i64
78; CHECK: icmp
79; CHECK: br i1
80; CHECK: {{^[0-9]+}}:
81; CHECK: @__msan_metadata_ptr_for_store_2(ptr %p)
82; CHECK: store i16
83; If the new shadow is non-zero, jump to __msan_chain_origin()
84; CHECK: icmp
85; CHECK: br i1
86; CHECK: {{^[0-9]+}}:
87; CHECK: @__msan_chain_origin
88; Storing origin here:
89; CHECK: store i32
90; CHECK: br label
91; CHECK: {{^[0-9]+}}:
92; CHECK: store i16
93; CHECK: ret void
94
95
96define void @Store4(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
97entry:
98  store i32 %x, ptr %p
99  ret void
100}
101
102; CHECK-LABEL: @Store4
103; CHECK: entry:
104; CHECK: @__msan_get_context_state()
105; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
106; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
107; Load the shadow of %p and check it
108; CHECK: load i32
109; CHECK: icmp
110; CHECK: br i1
111; CHECK: {{^[0-9]+}}:
112; CHECK: @__msan_metadata_ptr_for_store_4(ptr %p)
113; CHECK: store i32
114; If the new shadow is non-zero, jump to __msan_chain_origin()
115; CHECK: icmp
116; CHECK: br i1
117; CHECK: {{^[0-9]+}}:
118; CHECK: @__msan_chain_origin
119; Storing origin here:
120; CHECK: store i32
121; CHECK: br label
122; CHECK: {{^[0-9]+}}:
123; CHECK: store i32
124; CHECK: ret void
125
126define void @Store8(ptr nocapture %p, i64 %x) nounwind uwtable sanitize_memory {
127entry:
128  store i64 %x, ptr %p
129  ret void
130}
131
132; CHECK-LABEL: @Store8
133; CHECK: entry:
134; CHECK: @__msan_get_context_state()
135; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
136; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
137; Load the shadow of %p and check it
138; CHECK: load i64
139; CHECK: icmp
140; CHECK: br i1
141; CHECK: {{^[0-9]+}}:
142; CHECK: @__msan_metadata_ptr_for_store_8(ptr %p)
143; CHECK: store i64
144; If the new shadow is non-zero, jump to __msan_chain_origin()
145; CHECK: icmp
146; CHECK: br i1
147; CHECK: {{^[0-9]+}}:
148; CHECK: @__msan_chain_origin
149; Storing origin here:
150; CHECK: store i64
151; CHECK: br label
152; CHECK: {{^[0-9]+}}:
153; CHECK: store i64
154; CHECK: ret void
155
156define void @Store16(ptr nocapture %p, i128 %x) nounwind uwtable sanitize_memory {
157entry:
158  store i128 %x, ptr %p
159  ret void
160}
161
162; CHECK-LABEL: @Store16
163; CHECK: entry:
164; CHECK: @__msan_get_context_state()
165; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
166; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
167; Load the shadow of %p and check it
168; CHECK: load i64
169; CHECK: icmp
170; CHECK: br i1
171; CHECK: {{^[0-9]+}}:
172; CHECK: @__msan_metadata_ptr_for_store_n(ptr %p, i64 16)
173; CHECK: store i128
174; If the new shadow is non-zero, jump to __msan_chain_origin()
175; CHECK: icmp
176; CHECK: br i1
177; CHECK: {{^[0-9]+}}:
178; CHECK: @__msan_chain_origin
179; Storing origin here:
180; CHECK: store i64
181; CHECK: br label
182; CHECK: {{^[0-9]+}}:
183; CHECK: store i128
184; CHECK: ret void
185
186
187; Check instrumentation of loads
188
189define i8 @Load1(ptr nocapture %p) nounwind uwtable sanitize_memory {
190entry:
191  %0 = load i8, ptr %p
192  ret i8 %0
193}
194
195; CHECK-LABEL: @Load1
196; CHECK: entry:
197; CHECK: @__msan_get_context_state()
198; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
199; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
200; Load the shadow of %p and check it
201; CHECK: load i64
202; CHECK: icmp
203; CHECK: br i1
204; CHECK: {{^[0-9]+}}:
205; Load the value from %p. This is done before accessing the shadow
206; to ease atomic handling.
207; CHECK: load i8
208; CHECK: @__msan_metadata_ptr_for_load_1(ptr %p)
209; Load the shadow and origin.
210; CHECK: load i8
211; CHECK: load i32
212
213
214define i16 @Load2(ptr nocapture %p) nounwind uwtable sanitize_memory {
215entry:
216  %0 = load i16, ptr %p
217  ret i16 %0
218}
219
220; CHECK-LABEL: @Load2
221; CHECK: entry:
222; CHECK: @__msan_get_context_state()
223; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
224; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
225; Load the shadow of %p and check it
226; CHECK: load i64
227; CHECK: icmp
228; CHECK: br i1
229; CHECK: {{^[0-9]+}}:
230; Load the value from %p. This is done before accessing the shadow
231; to ease atomic handling.
232; CHECK: load i16
233; CHECK: @__msan_metadata_ptr_for_load_2(ptr %p)
234; Load the shadow and origin.
235; CHECK: load i16
236; CHECK: load i32
237
238
239define i32 @Load4(ptr nocapture %p) nounwind uwtable sanitize_memory {
240entry:
241  %0 = load i32, ptr %p
242  ret i32 %0
243}
244
245; CHECK-LABEL: @Load4
246; CHECK: entry:
247; CHECK: @__msan_get_context_state()
248; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
249; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
250; Load the shadow of %p and check it
251; CHECK: load i64
252; CHECK: icmp
253; CHECK: br i1
254; CHECK: {{^[0-9]+}}:
255; Load the value from %p. This is done before accessing the shadow
256; to ease atomic handling.
257; CHECK: load i32
258; CHECK: @__msan_metadata_ptr_for_load_4(ptr %p)
259; Load the shadow and origin.
260; CHECK: load i32
261; CHECK: load i32
262
263define i64 @Load8(ptr nocapture %p) nounwind uwtable sanitize_memory {
264entry:
265  %0 = load i64, ptr %p
266  ret i64 %0
267}
268
269; CHECK-LABEL: @Load8
270; CHECK: entry:
271; CHECK: @__msan_get_context_state()
272; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
273; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
274; Load the shadow of %p and check it
275; CHECK: load i64
276; CHECK: icmp
277; CHECK: br i1
278; CHECK: {{^[0-9]+}}:
279; Load the value from %p. This is done before accessing the shadow
280; to ease atomic handling.
281; CHECK: load i64
282; CHECK: @__msan_metadata_ptr_for_load_8(ptr %p)
283; Load the shadow and origin.
284; CHECK: load i64
285; CHECK: load i32
286
287define i128 @Load16(ptr nocapture %p) nounwind uwtable sanitize_memory {
288entry:
289  %0 = load i128, ptr %p
290  ret i128 %0
291}
292
293; CHECK-LABEL: @Load16
294; CHECK: entry:
295; CHECK: @__msan_get_context_state()
296; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
297; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
298; Load the shadow of %p and check it
299; CHECK: load i64
300; CHECK: icmp
301; CHECK: br i1
302; CHECK: {{^[0-9]+}}:
303; Load the value from %p. This is done before accessing the shadow
304; to ease atomic handling.
305; CHECK: load i128
306; CHECK: @__msan_metadata_ptr_for_load_n(ptr %p, i64 16)
307; Load the shadow and origin.
308; CHECK: load i128
309; CHECK: load i32
310
311
312; Test kernel-specific va_list instrumentation
313
314%struct.__va_list_tag = type { i32, i32, ptr, ptr }
315declare void @llvm.va_start(ptr) nounwind
316declare void @llvm.va_end(ptr)
317@.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
318declare dso_local i32 @VAListFn(ptr, ptr) local_unnamed_addr
319
320; Function Attrs: nounwind uwtable
321define dso_local i32 @VarArgFn(ptr %fmt, ...) local_unnamed_addr sanitize_memory #0 {
322entry:
323  %args = alloca [1 x %struct.__va_list_tag], align 16
324  call void @llvm.va_start(ptr nonnull %args)
325  %call = call i32 @VAListFn(ptr %fmt, ptr nonnull %args)
326  call void @llvm.va_end(ptr nonnull %args)
327  ret i32 %call
328}
329
330; Kernel is built without SSE support.
331attributes #0 = { "target-features"="+fxsr,+x87,-sse" }
332
333; CHECK-LABEL: @VarArgFn
334; CHECK: @__msan_get_context_state()
335; CHECK: [[VA_ARG_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 2
336; CHECK: [[VA_ARG_ORIGIN:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 3
337; CHECK: [[VA_ARG_OVERFLOW_SIZE:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 4
338
339; CHECK: [[OSIZE:%[0-9]+]] = load i64, ptr [[VA_ARG_OVERFLOW_SIZE]]
340; Register save area is 48 bytes for non-SSE builds.
341; CHECK: [[SIZE:%[0-9]+]] = add i64 48, [[OSIZE]]
342; CHECK: [[SHADOWS:%[0-9]+]] = alloca i8, i64 [[SIZE]]
343; CHECK: call void @llvm.memset{{.*}}(ptr align 8 [[SHADOWS]], i8 0, i64 [[SIZE]], i1 false)
344; CHECK: [[COPYSZ:%[0-9]+]] = call i64 @llvm.umin.i64(i64 [[SIZE]], i64 800)
345; CHECK: call void @llvm.memcpy{{.*}}(ptr align 8 [[SHADOWS]], ptr align 8 [[VA_ARG_SHADOW]], i64 [[COPYSZ]]
346; CHECK: [[ORIGINS:%[0-9]+]] = alloca i8, i64 [[SIZE]]
347; CHECK: call void @llvm.memcpy{{.*}}(ptr align 8 [[ORIGINS]], ptr align 8 [[VA_ARG_ORIGIN]], i64 [[COPYSZ]]
348; CHECK: call i32 @VAListFn
349
350; Function Attrs: nounwind uwtable
351define dso_local void @VarArgCaller() local_unnamed_addr sanitize_memory {
352entry:
353  %call = tail call i32 (ptr, ...) @VarArgFn(ptr @.str, i32 123)
354  ret void
355}
356
357; CHECK-LABEL: @VarArgCaller
358
359; CHECK: entry:
360; CHECK: @__msan_get_context_state()
361; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
362; CHECK: [[VA_ARG_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 2
363; CHECK: [[VA_ARG_OVERFLOW_SIZE:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 4
364
365; CHECK: [[PARAM_SI:%[_a-z0-9]+]] = ptrtoint {{.*}} [[PARAM_SHADOW]]
366; CHECK: [[ARG1_S:%[_a-z0-9]+]] = inttoptr i64 [[PARAM_SI]] to ptr
367; First argument is initialized
368; CHECK: store i64 0, ptr [[ARG1_S]]
369
370; Dangling cast of va_arg_shadow[0], unused because the first argument is fixed.
371; CHECK: [[VA_CAST0:%[_a-z0-9]+]] = ptrtoint {{.*}} [[VA_ARG_SHADOW]] to i64
372
373; CHECK: [[VA_CAST1:%[_a-z0-9]+]] = ptrtoint {{.*}} [[VA_ARG_SHADOW]] to i64
374; CHECK: [[ARG1_SI:%[_a-z0-9]+]] = add i64 [[VA_CAST1]], 8
375; CHECK: [[PARG1_S:%[_a-z0-9]+]] = inttoptr i64 [[ARG1_SI]] to ptr
376
377; Shadow for 123 is 0.
378; CHECK: store i32 0, ptr [[ARG1_S]]
379
380; CHECK: store i64 0, ptr [[VA_ARG_OVERFLOW_SIZE]]
381; CHECK: call i32 (ptr, ...) @VarArgFn({{.*}} @.str{{.*}} i32 123)
382