xref: /llvm-project/llvm/test/Instrumentation/DataFlowSanitizer/origin_abilist.ll (revision 94473f4db6a6f5f12d7c4081455b5b596094eac5)
1; RUN: opt < %s -passes=dfsan -dfsan-track-origins=1  -dfsan-abilist=%S/Inputs/abilist.txt -S | FileCheck %s
2target 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"
3target triple = "x86_64-unknown-linux-gnu"
4
5; CHECK: @__dfsan_arg_tls = external thread_local(initialexec) global [[TLS_ARR:\[100 x i64\]]]
6define i32 @discard(i32 %a, i32 %b) {
7  ret i32 0
8}
9
10define i32 @call_discard(i32 %a, i32 %b) {
11  ; CHECK: @call_discard.dfsan
12  ; CHECK: %r = call i32 @discard(i32 %a, i32 %b)
13  ; CHECK: store i32 0, ptr @__dfsan_retval_origin_tls, align 4
14  ; CHECK: ret i32 %r
15
16  %r = call i32 @discard(i32 %a, i32 %b)
17  ret i32 %r
18}
19
20; CHECK: i32 @functional(i32 %a, i32 %b)
21define i32 @functional(i32 %a, i32 %b) {
22  %c = add i32 %a, %b
23  ret i32 %c
24}
25
26define i32 @call_functional(i32 %a, i32 %b) {
27  ; CHECK-LABEL: @call_functional.dfsan
28  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
29  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls
30  ; CHECK: [[RO:%.*]] = select i1 {{.*}}, i32 [[BO]], i32 [[AO]]
31  ; CHECK: store i32 [[RO]], ptr @__dfsan_retval_origin_tls, align 4
32
33  %r = call i32 @functional(i32 %a, i32 %b)
34  ret i32 %r
35}
36
37define i32 @uninstrumented(i32 %a, i32 %b) {
38  %c = add i32 %a, %b
39  ret i32 %c
40}
41
42define i32 @call_uninstrumented(i32 %a, i32 %b) {
43  ; CHECK-LABEL: @call_uninstrumented.dfsan
44  ; CHECK: %r = call i32 @uninstrumented(i32 %a, i32 %b)
45  ; CHECK: store i32 0, ptr @__dfsan_retval_origin_tls, align 4
46  ; CHECK: ret i32 %r
47
48  %r = call i32 @uninstrumented(i32 %a, i32 %b)
49  ret i32 %r
50}
51
52define i32 @g(i32 %a, i32 %b) {
53  %c = add i32 %a, %b
54  ret i32 %c
55}
56
57@discardg = alias i32 (i32, i32), ptr @g
58
59define i32 @call_discardg(i32 %a, i32 %b) {
60  ; CHECK: @call_discardg.dfsan
61  ; CHECK: %r = call i32 @discardg(i32 %a, i32 %b)
62  ; CHECK: store i32 0, ptr @__dfsan_retval_origin_tls, align 4
63  ; CHECK: ret i32 %r
64
65  %r = call i32 @discardg(i32 %a, i32 %b)
66  ret i32 %r
67}
68
69define void @custom_without_ret(i32 %a, i32 %b) {
70  ret void
71}
72
73define i32 @custom_with_ret(i32 %a, i32 %b) {
74  %c = add i32 %a, %b
75  ret i32 %c
76}
77
78define void @custom_varg_without_ret(i32 %a, i32 %b, ...) {
79  ret void
80}
81
82define i32 @custom_varg_with_ret(i32 %a, i32 %b, ...) {
83  %c = add i32 %a, %b
84  ret i32 %c
85}
86
87define i32 @custom_cb_with_ret(ptr %cb, i32 %a, i32 %b) {
88  %r = call i32 %cb(i32 %a, i32 %b)
89  ret i32 %r
90}
91
92define i32 @cb_with_ret(i32 %a, i32 %b) {
93  %c = add i32 %a, %b
94  ret i32 %c
95}
96
97define void @custom_cb_without_ret(ptr %cb, i32 %a, i32 %b) {
98  call void %cb(i32 %a, i32 %b)
99  ret void
100}
101
102define void @cb_without_ret(i32 %a, i32 %b) {
103  ret void
104}
105
106define ptr @ret_custom() {
107  ; CHECK: @ret_custom.dfsan
108  ; CHECK: store i32 0, ptr @__dfsan_retval_origin_tls, align 4
109
110  ret ptr @custom_with_ret
111}
112
113define void @call_custom_without_ret(i32 %a, i32 %b) {
114  ; CHECK: @call_custom_without_ret.dfsan
115  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
116  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
117  ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
118  ; CHECK: [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
119  ; CHECK: call void @__dfso_custom_without_ret(i32 %a, i32 %b, i8 zeroext [[AS]], i8 zeroext [[BS]], i32 zeroext [[AO]], i32 zeroext [[BO]])
120  ; CHECK-NEXT: ret void
121
122  call void @custom_without_ret(i32 %a, i32 %b)
123  ret void
124}
125
126define i32 @call_custom_with_ret(i32 %a, i32 %b) {
127  ; CHECK: @call_custom_with_ret.dfsan
128  ; CHECK: %originreturn = alloca i32, align 4
129  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
130  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
131  ; CHECK: %labelreturn = alloca i8, align 1
132  ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
133  ; CHECK: [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
134  ; CHECK: {{.*}} = call i32 @__dfso_custom_with_ret(i32 %a, i32 %b, i8 zeroext [[AS]], i8 zeroext [[BS]], ptr %labelreturn, i32 zeroext [[AO]], i32 zeroext [[BO]], ptr %originreturn)
135  ; CHECK: [[RS:%.*]] = load i8, ptr %labelreturn, align 1
136  ; CHECK: [[RO:%.*]] = load i32, ptr %originreturn, align 4
137  ; CHECK: store i8 [[RS]], ptr @__dfsan_retval_tls, align 2
138  ; CHECK: store i32 [[RO]], ptr @__dfsan_retval_origin_tls, align 4
139
140  %r = call i32 @custom_with_ret(i32 %a, i32 %b)
141  ret i32 %r
142}
143
144define void @call_custom_varg_without_ret(i32 %a, i32 %b) {
145  ; CHECK: @call_custom_varg_without_ret.dfsan
146  ; CHECK: %originva = alloca [1 x i32], align 4
147  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
148  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
149  ; CHECK: %labelva = alloca [1 x i8], align 1
150  ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
151  ; CHECK: [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
152  ; CHECK: [[VS0:%.*]] = getelementptr inbounds nuw [1 x i8], ptr %labelva, i32 0, i32 0
153  ; CHECK: store i8 [[AS]], ptr [[VS0]], align 1
154  ; CHECK: [[VS0:%.*]] = getelementptr inbounds nuw [1 x i8], ptr %labelva, i32 0, i32 0
155  ; CHECK: [[VO0:%.*]] = getelementptr inbounds nuw [1 x i32], ptr %originva, i32 0, i32 0
156  ; CHECK: store i32 [[AO]], ptr [[VO0]], align 4
157  ; CHECK: [[VO0:%.*]] = getelementptr inbounds nuw [1 x i32], ptr %originva, i32 0, i32 0
158  ; CHECK: call void (i32, i32, i8, i8, ptr, i32, i32, ptr, ...) @__dfso_custom_varg_without_ret(i32 %a, i32 %b, i8 zeroext [[AS]], i8 zeroext [[BS]], ptr [[VS0]], i32 zeroext [[AO]], i32 zeroext [[BO]], ptr [[VO0]], i32 %a)
159  ; CHECK-NEXT: ret void
160
161  call void (i32, i32, ...) @custom_varg_without_ret(i32 %a, i32 %b, i32 %a)
162  ret void
163}
164
165define i32 @call_custom_varg_with_ret(i32 %a, i32 %b) {
166  ; CHECK: @call_custom_varg_with_ret.dfsan
167  ; CHECK: %originreturn = alloca i32, align 4
168  ; CHECK: %originva = alloca [1 x i32], align 4
169  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
170  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls
171  ; CHECK: %labelreturn = alloca i8, align 1
172  ; CHECK: %labelva = alloca [1 x i8], align 1
173  ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
174  ; CHECK: [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
175  ; CHECK: [[VS0:%.*]] = getelementptr inbounds nuw [1 x i8], ptr %labelva, i32 0, i32 0
176  ; CHECK: store i8 [[BS]], ptr [[VS0]], align 1
177  ; CHECK: [[VS0:%.*]] = getelementptr inbounds nuw [1 x i8], ptr %labelva, i32 0, i32 0
178  ; CHECK: [[VO0:%.*]] = getelementptr inbounds nuw [1 x i32], ptr %originva, i32 0, i32 0
179  ; CHECK: store i32 [[BO]], ptr [[VO0]], align 4
180  ; CHECK: [[VO0:%.*]] = getelementptr inbounds nuw [1 x i32], ptr %originva, i32 0, i32 0
181  ; CHECK: {{.*}} = call i32 (i32, i32, i8, i8, ptr, ptr, i32, i32, ptr, ptr, ...) @__dfso_custom_varg_with_ret(i32 %a, i32 %b, i8 zeroext [[AS]], i8 zeroext [[BS]], ptr [[VS0]], ptr %labelreturn, i32 zeroext [[AO]], i32 zeroext [[BO]], ptr [[VO0]], ptr %originreturn, i32 %b)
182  ; CHECK: [[RS:%.*]] = load i8, ptr %labelreturn, align 1
183  ; CHECK: [[RO:%.*]] = load i32, ptr %originreturn, align 4
184  ; CHECK: store i8 [[RS]], ptr @__dfsan_retval_tls, align 2
185  ; CHECK: store i32 [[RO]], ptr @__dfsan_retval_origin_tls, align 4
186
187  %r = call i32 (i32, i32, ...) @custom_varg_with_ret(i32 %a, i32 %b, i32 %b)
188  ret i32 %r
189}
190
191define i32 @call_custom_cb_with_ret(i32 %a, i32 %b) {
192  ; CHECK: @call_custom_cb_with_ret.dfsan
193  ; CHECK: %originreturn = alloca i32, align 4
194  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
195  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
196  ; CHECK: %labelreturn = alloca i8, align 1
197  ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
198  ; CHECK: [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
199  ; CHECK: {{.*}} = call i32 @__dfso_custom_cb_with_ret(ptr @cb_with_ret.dfsan, i32 %a, i32 %b, i8 zeroext 0, i8 zeroext [[AS]], i8 zeroext [[BS]], ptr %labelreturn, i32 zeroext 0, i32 zeroext [[AO]], i32 zeroext [[BO]], ptr %originreturn)
200  ; CHECK: [[RS:%.*]] = load i8, ptr %labelreturn, align 1
201  ; CHECK: [[RO:%.*]] = load i32, ptr %originreturn, align 4
202  ; CHECK: store i8 [[RS]], ptr @__dfsan_retval_tls, align 2
203  ; CHECK: store i32 [[RO]], ptr @__dfsan_retval_origin_tls, align 4
204
205  %r = call i32 @custom_cb_with_ret(ptr @cb_with_ret, i32 %a, i32 %b)
206  ret i32 %r
207}
208
209define void @call_custom_cb_without_ret(i32 %a, i32 %b) {
210  ; CHECK-LABEL: @call_custom_cb_without_ret.dfsan
211  ; CHECK: [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
212  ; CHECK: [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
213  ; CHECK: [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
214  ; CHECK: [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
215  ; CHECK: call void @__dfso_custom_cb_without_ret(ptr @cb_without_ret.dfsan, i32 %a, i32 %b, i8 zeroext 0, i8 zeroext [[AS]], i8 zeroext [[BS]], i32 zeroext 0, i32 zeroext [[AO]], i32 zeroext [[BO]])
216  ; CHECK-NEXT: ret void
217
218  call void @custom_cb_without_ret(ptr @cb_without_ret, i32 %a, i32 %b)
219  ret void
220}
221
222; CHECK: define i32 @discardg(i32 %0, i32 %1)
223; CHECK: [[R:%.*]] = call i32 @g.dfsan
224; CHECK-NEXT: %_dfsret = load i8, ptr @__dfsan_retval_tls, align 2
225; CHECK-NEXT: %_dfsret_o = load i32, ptr @__dfsan_retval_origin_tls, align 4
226; CHECK-NEXT: ret i32 [[R]]
227
228; CHECK: define linkonce_odr void @"dfso$custom_without_ret"(i32 %0, i32 %1)
229; CHECK:  [[BO:%.*]]  = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
230; CHECK-NEXT:  [[AO:%.*]]  = load i32, ptr @__dfsan_arg_origin_tls, align 4
231; CHECK-NEXT:  [[BS:%.*]]  = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
232; CHECK-NEXT:  [[AS:%.*]]  = load i8, ptr @__dfsan_arg_tls, align 2
233; CHECK-NEXT:  call void @__dfso_custom_without_ret(i32 %0, i32 %1, i8 zeroext [[AS]], i8 zeroext [[BS]], i32 zeroext [[AO]], i32 zeroext [[BO]])
234; CHECK-NEXT:  ret void
235
236; CHECK: define linkonce_odr i32 @"dfso$custom_with_ret"(i32 %0, i32 %1)
237; CHECK:  %originreturn = alloca i32, align 4
238; CHECK-NEXT:  [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
239; CHECK-NEXT:  [[AO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
240; CHECK-NEXT:  %labelreturn = alloca i8, align 1
241; CHECK-NEXT:  [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
242; CHECK-NEXT:  [[AS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
243; CHECK-NEXT:  [[R:%.*]] = call i32 @__dfso_custom_with_ret(i32 %0, i32 %1, i8 zeroext [[AS]], i8 zeroext [[BS]], ptr %labelreturn, i32 zeroext [[AO]], i32 zeroext [[BO]], ptr %originreturn)
244; CHECK-NEXT:  [[RS:%.*]] = load i8, ptr %labelreturn, align 1
245; CHECK-NEXT:  [[RO:%.*]] = load i32, ptr %originreturn, align 4
246; CHECK-NEXT:  store i8 [[RS]], ptr @__dfsan_retval_tls, align 2
247; CHECK-NEXT:  store i32 [[RO]], ptr @__dfsan_retval_origin_tls, align 4
248; CHECK-NEXT:  ret i32 [[R]]
249
250; CHECK: define linkonce_odr void @"dfso$custom_varg_without_ret"(i32 %0, i32 %1, ...)
251; CHECK:  call void @__dfsan_vararg_wrapper(ptr @0)
252; CHECK-NEXT:  unreachable
253
254; CHECK: define linkonce_odr i32 @"dfso$custom_varg_with_ret"(i32 %0, i32 %1, ...)
255; CHECK:  call void @__dfsan_vararg_wrapper(ptr @1)
256; CHECK-NEXT:  unreachable
257
258; CHECK: define linkonce_odr i32 @"dfso$custom_cb_with_ret"(ptr %0, i32 %1, i32 %2)
259; CHECK:  %originreturn = alloca i32, align 4
260; CHECK-NEXT:  [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 2), align 4
261; CHECK-NEXT:  [[AO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
262; CHECK-NEXT:  [[CO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
263; CHECK-NEXT:  %labelreturn = alloca i8, align 1
264; CHECK-NEXT:  [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align 2
265; CHECK-NEXT:  [[AS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
266; CHECK-NEXT:  [[CS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
267; CHECK-NEXT:  [[R:%.*]] = call i32 @__dfso_custom_cb_with_ret(ptr %0, i32 %1, i32 %2, i8 zeroext [[CS]], i8 zeroext [[AS]], i8 zeroext [[BS]], ptr %labelreturn, i32 zeroext [[CO]], i32 zeroext [[AO]], i32 zeroext [[BO]], ptr %originreturn)
268; CHECK-NEXT:  [[RS:%.*]] = load i8, ptr %labelreturn, align 1
269; CHECK-NEXT:  [[RO:%.*]] = load i32, ptr %originreturn, align 4
270; CHECK-NEXT:  store i8 [[RS]], ptr @__dfsan_retval_tls, align 2
271; CHECK-NEXT:  store i32 [[RO]], ptr @__dfsan_retval_origin_tls, align 4
272; CHECK-NEXT:  ret i32 [[R]]
273
274; CHECK: define linkonce_odr void @"dfso$custom_cb_without_ret"(ptr %0, i32 %1, i32 %2)
275; CHECK:   [[BO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 2), align 4
276; CHECK-NEXT:  [[AO:%.*]] = load i32, ptr getelementptr inbounds ([200 x i32], ptr @__dfsan_arg_origin_tls, i64 0, i64 1), align 4
277; CHECK-NEXT:  [[CO:%.*]] = load i32, ptr @__dfsan_arg_origin_tls, align 4
278; CHECK-NEXT:  [[BS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 4) to ptr), align 2
279; CHECK-NEXT:  [[AS:%.*]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align 2
280; CHECK-NEXT:  [[CS:%.*]] = load i8, ptr @__dfsan_arg_tls, align 2
281; CHECK-NEXT:  call void @__dfso_custom_cb_without_ret(ptr %0, i32 %1, i32 %2, i8 zeroext [[CS]], i8 zeroext [[AS]], i8 zeroext [[BS]], i32 zeroext [[CO]], i32 zeroext [[AO]], i32 zeroext [[BO]])
282; CHECK-NEXT:  ret void
283
284; CHECK: declare void @__dfso_custom_without_ret(i32, i32, i8, i8, i32, i32)
285
286; CHECK: declare i32 @__dfso_custom_with_ret(i32, i32, i8, i8, ptr, i32, i32, ptr)
287
288; CHECK: declare i32 @__dfso_custom_cb_with_ret(ptr, i32, i32, i8, i8, i8, ptr, i32, i32, i32, ptr)
289
290; CHECK: declare void @__dfso_custom_cb_without_ret(ptr, i32, i32, i8, i8, i8, i32, i32, i32)
291
292; CHECK: declare void @__dfso_custom_varg_without_ret(i32, i32, i8, i8, ptr, i32, i32, ptr, ...)
293
294; CHECK: declare i32 @__dfso_custom_varg_with_ret(i32, i32, i8, i8, ptr, ptr, i32, i32, ptr, ptr, ...)
295