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