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