1 ; KMSAN instrumentation tests
2 ; RUN: opt < %s -msan-kernel=1 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK
4 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"
5 target triple = "x86_64-unknown-linux-gnu"
7 ; Check the instrumentation prologue.
8 define void @Empty() nounwind uwtable sanitize_memory {
15 ; CHECK: @__msan_get_context_state()
17 ; CHECK: getelementptr {{.*}} i32 0, i32 0
19 ; CHECK: getelementptr {{.*}} i32 0, i32 1
21 ; CHECK: getelementptr {{.*}} i32 0, i32 2
23 ; CHECK: getelementptr {{.*}} i32 0, i32 3
24 ; %va_arg_overflow_size:
25 ; CHECK: getelementptr {{.*}} i32 0, i32 4
27 ; CHECK: getelementptr {{.*}} i32 0, i32 5
29 ; CHECK: getelementptr {{.*}} i32 0, i32 6
31 ; Check instrumentation of stores
33 define void @Store1(ptr nocapture %p, i8 %x) nounwind uwtable sanitize_memory {
39 ; CHECK-LABEL: @Store1
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]]
51 ; CHECK: @__msan_metadata_ptr_for_store_1(ptr %p)
53 ; If the new shadow is non-zero, jump to __msan_chain_origin()
57 ; CHECK: @__msan_chain_origin
58 ; Storing origin here:
65 define void @Store2(ptr nocapture %p, i16 %x) nounwind uwtable sanitize_memory {
71 ; CHECK-LABEL: @Store2
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
81 ; CHECK: @__msan_metadata_ptr_for_store_2(ptr %p)
83 ; If the new shadow is non-zero, jump to __msan_chain_origin()
87 ; CHECK: @__msan_chain_origin
88 ; Storing origin here:
96 define void @Store4(ptr nocapture %p, i32 %x) nounwind uwtable sanitize_memory {
102 ; CHECK-LABEL: @Store4
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
111 ; CHECK: {{^[0-9]+}}:
112 ; CHECK: @__msan_metadata_ptr_for_store_4(ptr %p)
114 ; If the new shadow is non-zero, jump to __msan_chain_origin()
117 ; CHECK: {{^[0-9]+}}:
118 ; CHECK: @__msan_chain_origin
119 ; Storing origin here:
122 ; CHECK: {{^[0-9]+}}:
126 define void @Store8(ptr nocapture %p, i64 %x) nounwind uwtable sanitize_memory {
132 ; CHECK-LABEL: @Store8
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
141 ; CHECK: {{^[0-9]+}}:
142 ; CHECK: @__msan_metadata_ptr_for_store_8(ptr %p)
144 ; If the new shadow is non-zero, jump to __msan_chain_origin()
147 ; CHECK: {{^[0-9]+}}:
148 ; CHECK: @__msan_chain_origin
149 ; Storing origin here:
152 ; CHECK: {{^[0-9]+}}:
156 define void @Store16(ptr nocapture %p, i128 %x) nounwind uwtable sanitize_memory {
158 store i128 %x, ptr %p
162 ; CHECK-LABEL: @Store16
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
171 ; CHECK: {{^[0-9]+}}:
172 ; CHECK: @__msan_metadata_ptr_for_store_n(ptr %p, i64 16)
174 ; If the new shadow is non-zero, jump to __msan_chain_origin()
177 ; CHECK: {{^[0-9]+}}:
178 ; CHECK: @__msan_chain_origin
179 ; Storing origin here:
182 ; CHECK: {{^[0-9]+}}:
187 ; Check instrumentation of loads
189 define i8 @Load1(ptr nocapture %p) nounwind uwtable sanitize_memory {
195 ; CHECK-LABEL: @Load1
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
204 ; CHECK: {{^[0-9]+}}:
205 ; Load the value from %p. This is done before accessing the shadow
206 ; to ease atomic handling.
208 ; CHECK: @__msan_metadata_ptr_for_load_1(ptr %p)
209 ; Load the shadow and origin.
214 define i16 @Load2(ptr nocapture %p) nounwind uwtable sanitize_memory {
216 %0 = load i16, ptr %p
220 ; CHECK-LABEL: @Load2
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
229 ; CHECK: {{^[0-9]+}}:
230 ; Load the value from %p. This is done before accessing the shadow
231 ; to ease atomic handling.
233 ; CHECK: @__msan_metadata_ptr_for_load_2(ptr %p)
234 ; Load the shadow and origin.
239 define i32 @Load4(ptr nocapture %p) nounwind uwtable sanitize_memory {
241 %0 = load i32, ptr %p
245 ; CHECK-LABEL: @Load4
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
254 ; CHECK: {{^[0-9]+}}:
255 ; Load the value from %p. This is done before accessing the shadow
256 ; to ease atomic handling.
258 ; CHECK: @__msan_metadata_ptr_for_load_4(ptr %p)
259 ; Load the shadow and origin.
263 define i64 @Load8(ptr nocapture %p) nounwind uwtable sanitize_memory {
265 %0 = load i64, ptr %p
269 ; CHECK-LABEL: @Load8
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
278 ; CHECK: {{^[0-9]+}}:
279 ; Load the value from %p. This is done before accessing the shadow
280 ; to ease atomic handling.
282 ; CHECK: @__msan_metadata_ptr_for_load_8(ptr %p)
283 ; Load the shadow and origin.
287 define i128 @Load16(ptr nocapture %p) nounwind uwtable sanitize_memory {
289 %0 = load i128, ptr %p
293 ; CHECK-LABEL: @Load16
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
302 ; CHECK: {{^[0-9]+}}:
303 ; Load the value from %p. This is done before accessing the shadow
304 ; to ease atomic handling.
306 ; CHECK: @__msan_metadata_ptr_for_load_n(ptr %p, i64 16)
307 ; Load the shadow and origin.
312 ; Test kernel-specific va_list instrumentation
314 %struct.__va_list_tag = type { i32, i32, ptr, ptr }
315 declare void @llvm.va_start(ptr) nounwind
316 declare void @llvm.va_end(ptr)
317 @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1
318 declare dso_local i32 @VAListFn(ptr, ptr) local_unnamed_addr
320 ; Function Attrs: nounwind uwtable
321 define dso_local i32 @VarArgFn(ptr %fmt, ...) local_unnamed_addr sanitize_memory #0 {
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)
330 ; Kernel is built without SSE support.
331 attributes #0 = { "target-features"="+fxsr,+x87,-sse" }
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
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
350 ; Function Attrs: nounwind uwtable
351 define dso_local void @VarArgCaller() local_unnamed_addr sanitize_memory {
353 %call = tail call i32 (ptr, ...) @VarArgFn(ptr @.str, i32 123)
357 ; CHECK-LABEL: @VarArgCaller
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
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]]
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
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
377 ; Shadow for 123 is 0.
378 ; CHECK: store i32 0, ptr [[ARG1_S]]
380 ; CHECK: store i64 0, ptr [[VA_ARG_OVERFLOW_SIZE]]
381 ; CHECK: call i32 (ptr, ...) @VarArgFn({{.*}} @.str{{.*}} i32 123)