1 ; KMSAN instrumentation tests
2 ; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s \
3 ; RUN: -check-prefixes=CHECK
5 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"
6 target triple = "x86_64-unknown-linux-gnu"
8 ; Check the instrumentation prologue.
9 define void @Empty() nounwind uwtable sanitize_memory {
16 ; CHECK: @__msan_get_context_state()
18 ; CHECK: getelementptr {{.*}} i32 0, i32 0
20 ; CHECK: getelementptr {{.*}} i32 0, i32 1
22 ; CHECK: getelementptr {{.*}} i32 0, i32 2
24 ; CHECK: getelementptr {{.*}} i32 0, i32 3
25 ; %va_arg_overflow_size:
26 ; CHECK: getelementptr {{.*}} i32 0, i32 4
28 ; CHECK: getelementptr {{.*}} i32 0, i32 5
30 ; CHECK: getelementptr {{.*}} i32 0, i32 6
32 ; Check instrumentation of stores
34 define void @Store1(ptr nocapture %p, i8 %x) nounwind uwtable sanitize_memory {
40 ; CHECK-LABEL: @Store1
42 ; CHECK: @__msan_get_context_state()
43 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
44 ; CHECK: [[BASE:%[0-9]+]] = ptrtoint {{.*}} [[PARAM_SHADOW]]
45 ; CHECK: [[SHADOW_PTR:%[a-z0-9_]+]] = inttoptr {{.*}} [[BASE]]
46 ; CHECK: [[SHADOW:%[a-z0-9]+]] = load i64, ptr [[SHADOW_PTR]]
47 ; CHECK: [[BASE2:%[0-9]+]] = ptrtoint {{.*}} [[PARAM_SHADOW]]
48 ; Load the shadow of %p and check it
49 ; CHECK: icmp ne i64 [[SHADOW]]
52 ; CHECK: @__msan_metadata_ptr_for_store_1(ptr %p)
54 ; If the new shadow is non-zero, jump to __msan_chain_origin()
58 ; CHECK: @__msan_chain_origin
59 ; Storing origin here:
66 define void @Store2(ptr nocapture %p, i16 %x) nounwind uwtable sanitize_memory {
72 ; CHECK-LABEL: @Store2
74 ; CHECK: @__msan_get_context_state()
75 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
76 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
77 ; Load the shadow of %p and check it
82 ; CHECK: @__msan_metadata_ptr_for_store_2(ptr %p)
84 ; If the new shadow is non-zero, jump to __msan_chain_origin()
88 ; CHECK: @__msan_chain_origin
89 ; Storing origin here:
97 define void @Store4(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
103 ; CHECK-LABEL: @Store4
105 ; CHECK: @__msan_get_context_state()
106 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
107 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
108 ; Load the shadow of %p and check it
112 ; CHECK: {{^[0-9]+}}:
113 ; CHECK: @__msan_metadata_ptr_for_store_4(ptr %p)
115 ; If the new shadow is non-zero, jump to __msan_chain_origin()
118 ; CHECK: {{^[0-9]+}}:
119 ; CHECK: @__msan_chain_origin
120 ; Storing origin here:
123 ; CHECK: {{^[0-9]+}}:
127 define void @Store8(ptr nocapture %p, i64 %x) nounwind uwtable sanitize_memory {
133 ; CHECK-LABEL: @Store8
135 ; CHECK: @__msan_get_context_state()
136 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
137 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
138 ; Load the shadow of %p and check it
142 ; CHECK: {{^[0-9]+}}:
143 ; CHECK: @__msan_metadata_ptr_for_store_8(ptr %p)
145 ; If the new shadow is non-zero, jump to __msan_chain_origin()
148 ; CHECK: {{^[0-9]+}}:
149 ; CHECK: @__msan_chain_origin
150 ; Storing origin here:
153 ; CHECK: {{^[0-9]+}}:
157 define void @Store16(ptr nocapture %p, i128 %x) nounwind uwtable sanitize_memory {
159 store i128 %x, ptr %p
163 ; CHECK-LABEL: @Store16
165 ; CHECK: @__msan_get_context_state()
166 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
167 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
168 ; Load the shadow of %p and check it
172 ; CHECK: {{^[0-9]+}}:
173 ; CHECK: @__msan_metadata_ptr_for_store_n(ptr %p, i64 16)
175 ; If the new shadow is non-zero, jump to __msan_chain_origin()
178 ; CHECK: {{^[0-9]+}}:
179 ; CHECK: @__msan_chain_origin
180 ; Storing origin here:
183 ; CHECK: {{^[0-9]+}}:
188 ; Check instrumentation of loads
190 define i8 @Load1(ptr nocapture %p) nounwind uwtable sanitize_memory {
196 ; CHECK-LABEL: @Load1
198 ; CHECK: @__msan_get_context_state()
199 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
200 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
201 ; Load the shadow of %p and check it
205 ; CHECK: {{^[0-9]+}}:
206 ; Load the value from %p. This is done before accessing the shadow
207 ; to ease atomic handling.
209 ; CHECK: @__msan_metadata_ptr_for_load_1(ptr %p)
210 ; Load the shadow and origin.
215 define i16 @Load2(ptr nocapture %p) nounwind uwtable sanitize_memory {
217 %0 = load i16, ptr %p
221 ; CHECK-LABEL: @Load2
223 ; CHECK: @__msan_get_context_state()
224 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
225 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
226 ; Load the shadow of %p and check it
230 ; CHECK: {{^[0-9]+}}:
231 ; Load the value from %p. This is done before accessing the shadow
232 ; to ease atomic handling.
234 ; CHECK: @__msan_metadata_ptr_for_load_2(ptr %p)
235 ; Load the shadow and origin.
240 define i32 @Load4(ptr nocapture %p) nounwind uwtable sanitize_memory {
242 %0 = load i32, ptr %p
246 ; CHECK-LABEL: @Load4
248 ; CHECK: @__msan_get_context_state()
249 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
250 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
251 ; Load the shadow of %p and check it
255 ; CHECK: {{^[0-9]+}}:
256 ; Load the value from %p. This is done before accessing the shadow
257 ; to ease atomic handling.
259 ; CHECK: @__msan_metadata_ptr_for_load_4(ptr %p)
260 ; Load the shadow and origin.
264 define i64 @Load8(ptr nocapture %p) nounwind uwtable sanitize_memory {
266 %0 = load i64, ptr %p
270 ; CHECK-LABEL: @Load8
272 ; CHECK: @__msan_get_context_state()
273 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
274 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
275 ; Load the shadow of %p and check it
279 ; CHECK: {{^[0-9]+}}:
280 ; Load the value from %p. This is done before accessing the shadow
281 ; to ease atomic handling.
283 ; CHECK: @__msan_metadata_ptr_for_load_8(ptr %p)
284 ; Load the shadow and origin.
288 define i128 @Load16(ptr nocapture %p) nounwind uwtable sanitize_memory {
290 %0 = load i128, ptr %p
294 ; CHECK-LABEL: @Load16
296 ; CHECK: @__msan_get_context_state()
297 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
298 ; CHECK: ptrtoint {{.*}} [[PARAM_SHADOW]]
299 ; Load the shadow of %p and check it
303 ; CHECK: {{^[0-9]+}}:
304 ; Load the value from %p. This is done before accessing the shadow
305 ; to ease atomic handling.
307 ; CHECK: @__msan_metadata_ptr_for_load_n(ptr %p, i64 16)
308 ; Load the shadow and origin.
313 ; Test kernel-specific va_list instrumentation
315 %struct.__va_list_tag = type { i32, i32, ptr, ptr }
316 declare void @llvm.va_start(ptr) nounwind
317 declare void @llvm.va_end(ptr)
318 @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
319 declare dso_local i32 @VAListFn(ptr, ptr) local_unnamed_addr
321 ; Function Attrs: nounwind uwtable
322 define dso_local i32 @VarArgFn(ptr %fmt, ...) local_unnamed_addr sanitize_memory #0 {
324 %args = alloca [1 x %struct.__va_list_tag], align 16
325 call void @llvm.va_start(ptr nonnull %args)
326 %call = call i32 @VAListFn(ptr %fmt, ptr nonnull %args)
327 call void @llvm.va_end(ptr nonnull %args)
331 ; Kernel is built without SSE support.
332 attributes #0 = { "target-features"="+fxsr,+x87,-sse" }
334 ; CHECK-LABEL: @VarArgFn
335 ; CHECK: @__msan_get_context_state()
336 ; CHECK: [[VA_ARG_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 2
337 ; CHECK: [[VA_ARG_ORIGIN:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 3
338 ; CHECK: [[VA_ARG_OVERFLOW_SIZE:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 4
340 ; CHECK: [[OSIZE:%[0-9]+]] = load i64, ptr [[VA_ARG_OVERFLOW_SIZE]]
341 ; Register save area is 48 bytes for non-SSE builds.
342 ; CHECK: [[SIZE:%[0-9]+]] = add i64 48, [[OSIZE]]
343 ; CHECK: [[SHADOWS:%[0-9]+]] = alloca i8, i64 [[SIZE]]
344 ; CHECK: call void @llvm.memset{{.*}}(ptr align 8 [[SHADOWS]], i8 0, i64 [[SIZE]], i1 false)
345 ; CHECK: [[COPYSZ:%[0-9]+]] = call i64 @llvm.umin.i64(i64 [[SIZE]], i64 800)
346 ; CHECK: call void @llvm.memcpy{{.*}}(ptr align 8 [[SHADOWS]], ptr align 8 [[VA_ARG_SHADOW]], i64 [[COPYSZ]]
347 ; CHECK: [[ORIGINS:%[0-9]+]] = alloca i8, i64 [[SIZE]]
348 ; CHECK: call void @llvm.memcpy{{.*}}(ptr align 8 [[ORIGINS]], ptr align 8 [[VA_ARG_ORIGIN]], i64 [[COPYSZ]]
349 ; CHECK: call i32 @VAListFn
351 ; Function Attrs: nounwind uwtable
352 define dso_local void @VarArgCaller() local_unnamed_addr sanitize_memory {
354 %call = tail call i32 (ptr, ...) @VarArgFn(ptr @.str, i32 123)
358 ; CHECK-LABEL: @VarArgCaller
361 ; CHECK: @__msan_get_context_state()
362 ; CHECK: [[PARAM_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 0
363 ; CHECK: [[VA_ARG_SHADOW:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 2
364 ; CHECK: [[VA_ARG_OVERFLOW_SIZE:%[a-z0-9_]+]] = getelementptr {{.*}} i32 0, i32 4
366 ; CHECK: [[PARAM_SI:%[_a-z0-9]+]] = ptrtoint {{.*}} [[PARAM_SHADOW]]
367 ; CHECK: [[ARG1_S:%[_a-z0-9]+]] = inttoptr i64 [[PARAM_SI]] to ptr
368 ; First argument is initialized
369 ; CHECK: store i64 0, ptr [[ARG1_S]]
371 ; Dangling cast of va_arg_shadow[0], unused because the first argument is fixed.
372 ; CHECK: [[VA_CAST0:%[_a-z0-9]+]] = ptrtoint {{.*}} [[VA_ARG_SHADOW]] to i64
374 ; CHECK: [[VA_CAST1:%[_a-z0-9]+]] = ptrtoint {{.*}} [[VA_ARG_SHADOW]] to i64
375 ; CHECK: [[ARG1_SI:%[_a-z0-9]+]] = add i64 [[VA_CAST1]], 8
376 ; CHECK: [[PARG1_S:%[_a-z0-9]+]] = inttoptr i64 [[ARG1_SI]] to ptr
378 ; Shadow for 123 is 0.
379 ; CHECK: store i32 0, ptr [[ARG1_S]]
381 ; CHECK: store i64 0, ptr [[VA_ARG_OVERFLOW_SIZE]]
382 ; CHECK: call i32 (ptr, ...) @VarArgFn({{.*}} @.str{{.*}} i32 123)