]>
Commit | Line | Data |
---|---|---|
df36e621 AN |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <test_progs.h> | |
002d3afc | 3 | #include "progs/core_reloc_types.h" |
5051b384 | 4 | #include <sys/mman.h> |
6147a140 | 5 | #include <sys/syscall.h> |
002d3afc AN |
6 | |
7 | #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name) | |
8 | ||
9 | #define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ | |
10 | .a = 42, \ | |
11 | .b = 0xc001, \ | |
12 | .c = 0xbeef, \ | |
13 | } | |
14 | ||
15 | #define FLAVORS_CASE_COMMON(name) \ | |
16 | .case_name = #name, \ | |
17 | .bpf_obj_file = "test_core_reloc_flavors.o", \ | |
18 | .btf_src_file = "btf__core_reloc_" #name ".o" \ | |
19 | ||
20 | #define FLAVORS_CASE(name) { \ | |
21 | FLAVORS_CASE_COMMON(name), \ | |
22 | .input = FLAVORS_DATA(core_reloc_##name), \ | |
23 | .input_len = sizeof(struct core_reloc_##name), \ | |
24 | .output = FLAVORS_DATA(core_reloc_flavors), \ | |
25 | .output_len = sizeof(struct core_reloc_flavors), \ | |
26 | } | |
27 | ||
28 | #define FLAVORS_ERR_CASE(name) { \ | |
29 | FLAVORS_CASE_COMMON(name), \ | |
30 | .fails = true, \ | |
31 | } | |
df36e621 | 32 | |
ec6438a9 AN |
33 | #define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ |
34 | .a = { .a = { .a = 42 } }, \ | |
35 | .b = { .b = { .b = 0xc001 } }, \ | |
36 | } | |
37 | ||
38 | #define NESTING_CASE_COMMON(name) \ | |
39 | .case_name = #name, \ | |
40 | .bpf_obj_file = "test_core_reloc_nesting.o", \ | |
41 | .btf_src_file = "btf__core_reloc_" #name ".o" | |
42 | ||
43 | #define NESTING_CASE(name) { \ | |
44 | NESTING_CASE_COMMON(name), \ | |
45 | .input = NESTING_DATA(core_reloc_##name), \ | |
46 | .input_len = sizeof(struct core_reloc_##name), \ | |
47 | .output = NESTING_DATA(core_reloc_nesting), \ | |
48 | .output_len = sizeof(struct core_reloc_nesting) \ | |
49 | } | |
50 | ||
51 | #define NESTING_ERR_CASE(name) { \ | |
52 | NESTING_CASE_COMMON(name), \ | |
53 | .fails = true, \ | |
54 | } | |
55 | ||
20a9ad2e AN |
56 | #define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ |
57 | .a = { [2] = 1 }, \ | |
58 | .b = { [1] = { [2] = { [3] = 2 } } }, \ | |
59 | .c = { [1] = { .c = 3 } }, \ | |
60 | .d = { [0] = { [0] = { .d = 4 } } }, \ | |
61 | } | |
62 | ||
63 | #define ARRAYS_CASE_COMMON(name) \ | |
64 | .case_name = #name, \ | |
65 | .bpf_obj_file = "test_core_reloc_arrays.o", \ | |
66 | .btf_src_file = "btf__core_reloc_" #name ".o" | |
67 | ||
68 | #define ARRAYS_CASE(name) { \ | |
69 | ARRAYS_CASE_COMMON(name), \ | |
70 | .input = ARRAYS_DATA(core_reloc_##name), \ | |
71 | .input_len = sizeof(struct core_reloc_##name), \ | |
72 | .output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) { \ | |
73 | .a2 = 1, \ | |
74 | .b123 = 2, \ | |
75 | .c1c = 3, \ | |
76 | .d00d = 4, \ | |
77 | }, \ | |
78 | .output_len = sizeof(struct core_reloc_arrays_output) \ | |
79 | } | |
80 | ||
81 | #define ARRAYS_ERR_CASE(name) { \ | |
82 | ARRAYS_CASE_COMMON(name), \ | |
83 | .fails = true, \ | |
84 | } | |
85 | ||
d9db3550 AN |
86 | #define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ |
87 | .a = 1, \ | |
88 | .b = 2, \ | |
89 | .c = 3, \ | |
90 | .d = (void *)4, \ | |
91 | .f = (void *)5, \ | |
92 | } | |
93 | ||
94 | #define PRIMITIVES_CASE_COMMON(name) \ | |
95 | .case_name = #name, \ | |
96 | .bpf_obj_file = "test_core_reloc_primitives.o", \ | |
97 | .btf_src_file = "btf__core_reloc_" #name ".o" | |
98 | ||
99 | #define PRIMITIVES_CASE(name) { \ | |
100 | PRIMITIVES_CASE_COMMON(name), \ | |
101 | .input = PRIMITIVES_DATA(core_reloc_##name), \ | |
102 | .input_len = sizeof(struct core_reloc_##name), \ | |
103 | .output = PRIMITIVES_DATA(core_reloc_primitives), \ | |
104 | .output_len = sizeof(struct core_reloc_primitives), \ | |
105 | } | |
106 | ||
107 | #define PRIMITIVES_ERR_CASE(name) { \ | |
108 | PRIMITIVES_CASE_COMMON(name), \ | |
109 | .fails = true, \ | |
110 | } | |
111 | ||
9654e2ae AN |
112 | #define MODS_CASE(name) { \ |
113 | .case_name = #name, \ | |
114 | .bpf_obj_file = "test_core_reloc_mods.o", \ | |
115 | .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
116 | .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) { \ | |
117 | .a = 1, \ | |
118 | .b = 2, \ | |
119 | .c = (void *)3, \ | |
120 | .d = (void *)4, \ | |
121 | .e = { [2] = 5 }, \ | |
122 | .f = { [1] = 6 }, \ | |
123 | .g = { .x = 7 }, \ | |
124 | .h = { .y = 8 }, \ | |
125 | }, \ | |
126 | .input_len = sizeof(struct core_reloc_##name), \ | |
127 | .output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) { \ | |
128 | .a = 1, .b = 2, .c = 3, .d = 4, \ | |
129 | .e = 5, .f = 6, .g = 7, .h = 8, \ | |
130 | }, \ | |
131 | .output_len = sizeof(struct core_reloc_mods_output), \ | |
132 | } | |
133 | ||
d698f9db AN |
134 | #define PTR_AS_ARR_CASE(name) { \ |
135 | .case_name = #name, \ | |
136 | .bpf_obj_file = "test_core_reloc_ptr_as_arr.o", \ | |
137 | .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
138 | .input = (const char *)&(struct core_reloc_##name []){ \ | |
139 | { .a = 1 }, \ | |
140 | { .a = 2 }, \ | |
141 | { .a = 3 }, \ | |
142 | }, \ | |
143 | .input_len = 3 * sizeof(struct core_reloc_##name), \ | |
144 | .output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) { \ | |
145 | .a = 3, \ | |
146 | }, \ | |
147 | .output_len = sizeof(struct core_reloc_ptr_as_arr), \ | |
148 | } | |
149 | ||
c1f5e7dd AN |
150 | #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \ |
151 | .u8_field = 1, \ | |
152 | .s8_field = 2, \ | |
153 | .u16_field = 3, \ | |
154 | .s16_field = 4, \ | |
155 | .u32_field = 5, \ | |
156 | .s32_field = 6, \ | |
157 | .u64_field = 7, \ | |
158 | .s64_field = 8, \ | |
159 | } | |
160 | ||
161 | #define INTS_CASE_COMMON(name) \ | |
162 | .case_name = #name, \ | |
163 | .bpf_obj_file = "test_core_reloc_ints.o", \ | |
164 | .btf_src_file = "btf__core_reloc_" #name ".o" | |
165 | ||
166 | #define INTS_CASE(name) { \ | |
167 | INTS_CASE_COMMON(name), \ | |
168 | .input = INTS_DATA(core_reloc_##name), \ | |
169 | .input_len = sizeof(struct core_reloc_##name), \ | |
170 | .output = INTS_DATA(core_reloc_ints), \ | |
171 | .output_len = sizeof(struct core_reloc_ints), \ | |
172 | } | |
173 | ||
174 | #define INTS_ERR_CASE(name) { \ | |
175 | INTS_CASE_COMMON(name), \ | |
176 | .fails = true, \ | |
177 | } | |
178 | ||
c7566a69 AN |
179 | #define EXISTENCE_CASE_COMMON(name) \ |
180 | .case_name = #name, \ | |
181 | .bpf_obj_file = "test_core_reloc_existence.o", \ | |
182 | .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
0b163565 | 183 | .relaxed_core_relocs = true |
c7566a69 AN |
184 | |
185 | #define EXISTENCE_ERR_CASE(name) { \ | |
186 | EXISTENCE_CASE_COMMON(name), \ | |
187 | .fails = true, \ | |
188 | } | |
189 | ||
8b1cb1c9 AN |
190 | #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \ |
191 | .case_name = test_name_prefix#name, \ | |
192 | .bpf_obj_file = objfile, \ | |
193 | .btf_src_file = "btf__core_reloc_" #name ".o" | |
194 | ||
195 | #define BITFIELDS_CASE(name, ...) { \ | |
196 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \ | |
197 | "direct:", name), \ | |
198 | .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__, \ | |
199 | .input_len = sizeof(struct core_reloc_##name), \ | |
200 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ | |
201 | __VA_ARGS__, \ | |
202 | .output_len = sizeof(struct core_reloc_bitfields_output), \ | |
203 | }, { \ | |
204 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ | |
205 | "probed:", name), \ | |
206 | .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__, \ | |
207 | .input_len = sizeof(struct core_reloc_##name), \ | |
208 | .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \ | |
209 | __VA_ARGS__, \ | |
210 | .output_len = sizeof(struct core_reloc_bitfields_output), \ | |
211 | .direct_raw_tp = true, \ | |
212 | } | |
213 | ||
214 | ||
215 | #define BITFIELDS_ERR_CASE(name) { \ | |
216 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \ | |
217 | "probed:", name), \ | |
218 | .fails = true, \ | |
219 | }, { \ | |
220 | BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \ | |
221 | "direct:", name), \ | |
222 | .direct_raw_tp = true, \ | |
223 | .fails = true, \ | |
224 | } | |
225 | ||
0b163565 AN |
226 | #define SIZE_CASE_COMMON(name) \ |
227 | .case_name = #name, \ | |
228 | .bpf_obj_file = "test_core_reloc_size.o", \ | |
229 | .btf_src_file = "btf__core_reloc_" #name ".o", \ | |
230 | .relaxed_core_relocs = true | |
231 | ||
232 | #define SIZE_OUTPUT_DATA(type) \ | |
233 | STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \ | |
234 | .int_sz = sizeof(((type *)0)->int_field), \ | |
235 | .struct_sz = sizeof(((type *)0)->struct_field), \ | |
236 | .union_sz = sizeof(((type *)0)->union_field), \ | |
237 | .arr_sz = sizeof(((type *)0)->arr_field), \ | |
238 | .arr_elem_sz = sizeof(((type *)0)->arr_field[0]), \ | |
239 | .ptr_sz = sizeof(((type *)0)->ptr_field), \ | |
240 | .enum_sz = sizeof(((type *)0)->enum_field), \ | |
241 | } | |
242 | ||
243 | #define SIZE_CASE(name) { \ | |
244 | SIZE_CASE_COMMON(name), \ | |
245 | .input_len = 0, \ | |
246 | .output = SIZE_OUTPUT_DATA(struct core_reloc_##name), \ | |
247 | .output_len = sizeof(struct core_reloc_size_output), \ | |
248 | } | |
249 | ||
250 | #define SIZE_ERR_CASE(name) { \ | |
251 | SIZE_CASE_COMMON(name), \ | |
252 | .fails = true, \ | |
253 | } | |
254 | ||
df36e621 AN |
255 | struct core_reloc_test_case { |
256 | const char *case_name; | |
257 | const char *bpf_obj_file; | |
258 | const char *btf_src_file; | |
259 | const char *input; | |
260 | int input_len; | |
261 | const char *output; | |
262 | int output_len; | |
263 | bool fails; | |
c7566a69 | 264 | bool relaxed_core_relocs; |
8b1cb1c9 | 265 | bool direct_raw_tp; |
df36e621 AN |
266 | }; |
267 | ||
268 | static struct core_reloc_test_case test_cases[] = { | |
269 | /* validate we can find kernel image and use its BTF for relocs */ | |
270 | { | |
271 | .case_name = "kernel", | |
272 | .bpf_obj_file = "test_core_reloc_kernel.o", | |
273 | .btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */ | |
274 | .input = "", | |
275 | .input_len = 0, | |
ee2eb063 AN |
276 | .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) { |
277 | .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, | |
d25c5e23 AN |
278 | .comm = "test_progs", |
279 | .comm_len = sizeof("test_progs"), | |
ee2eb063 AN |
280 | }, |
281 | .output_len = sizeof(struct core_reloc_kernel_output), | |
df36e621 | 282 | }, |
002d3afc AN |
283 | |
284 | /* validate BPF program can use multiple flavors to match against | |
285 | * single target BTF type | |
286 | */ | |
287 | FLAVORS_CASE(flavors), | |
288 | ||
289 | FLAVORS_ERR_CASE(flavors__err_wrong_name), | |
ec6438a9 AN |
290 | |
291 | /* various struct/enum nesting and resolution scenarios */ | |
292 | NESTING_CASE(nesting), | |
293 | NESTING_CASE(nesting___anon_embed), | |
294 | NESTING_CASE(nesting___struct_union_mixup), | |
295 | NESTING_CASE(nesting___extra_nesting), | |
296 | NESTING_CASE(nesting___dup_compat_types), | |
297 | ||
298 | NESTING_ERR_CASE(nesting___err_missing_field), | |
299 | NESTING_ERR_CASE(nesting___err_array_field), | |
300 | NESTING_ERR_CASE(nesting___err_missing_container), | |
301 | NESTING_ERR_CASE(nesting___err_nonstruct_container), | |
302 | NESTING_ERR_CASE(nesting___err_array_container), | |
303 | NESTING_ERR_CASE(nesting___err_dup_incompat_types), | |
304 | NESTING_ERR_CASE(nesting___err_partial_match_dups), | |
305 | NESTING_ERR_CASE(nesting___err_too_deep), | |
20a9ad2e AN |
306 | |
307 | /* various array access relocation scenarios */ | |
308 | ARRAYS_CASE(arrays), | |
309 | ARRAYS_CASE(arrays___diff_arr_dim), | |
310 | ARRAYS_CASE(arrays___diff_arr_val_sz), | |
311 | ||
312 | ARRAYS_ERR_CASE(arrays___err_too_small), | |
313 | ARRAYS_ERR_CASE(arrays___err_too_shallow), | |
314 | ARRAYS_ERR_CASE(arrays___err_non_array), | |
315 | ARRAYS_ERR_CASE(arrays___err_wrong_val_type1), | |
316 | ARRAYS_ERR_CASE(arrays___err_wrong_val_type2), | |
d9db3550 AN |
317 | |
318 | /* enum/ptr/int handling scenarios */ | |
319 | PRIMITIVES_CASE(primitives), | |
320 | PRIMITIVES_CASE(primitives___diff_enum_def), | |
321 | PRIMITIVES_CASE(primitives___diff_func_proto), | |
322 | PRIMITIVES_CASE(primitives___diff_ptr_type), | |
323 | ||
324 | PRIMITIVES_ERR_CASE(primitives___err_non_enum), | |
325 | PRIMITIVES_ERR_CASE(primitives___err_non_int), | |
326 | PRIMITIVES_ERR_CASE(primitives___err_non_ptr), | |
9654e2ae AN |
327 | |
328 | /* const/volatile/restrict and typedefs scenarios */ | |
329 | MODS_CASE(mods), | |
330 | MODS_CASE(mods___mod_swap), | |
331 | MODS_CASE(mods___typedefs), | |
d698f9db AN |
332 | |
333 | /* handling "ptr is an array" semantics */ | |
334 | PTR_AS_ARR_CASE(ptr_as_arr), | |
335 | PTR_AS_ARR_CASE(ptr_as_arr___diff_sz), | |
c1f5e7dd AN |
336 | |
337 | /* int signedness/sizing/bitfield handling */ | |
338 | INTS_CASE(ints), | |
339 | INTS_CASE(ints___bool), | |
340 | INTS_CASE(ints___reverse_sign), | |
341 | ||
29e1c668 AN |
342 | /* validate edge cases of capturing relocations */ |
343 | { | |
344 | .case_name = "misc", | |
345 | .bpf_obj_file = "test_core_reloc_misc.o", | |
346 | .btf_src_file = "btf__core_reloc_misc.o", | |
347 | .input = (const char *)&(struct core_reloc_misc_extensible[]){ | |
348 | { .a = 1 }, | |
349 | { .a = 2 }, /* not read */ | |
350 | { .a = 3 }, | |
351 | }, | |
352 | .input_len = 4 * sizeof(int), | |
353 | .output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) { | |
354 | .a = 1, | |
355 | .b = 1, | |
356 | .c = 0, /* BUG in clang, should be 3 */ | |
357 | }, | |
358 | .output_len = sizeof(struct core_reloc_misc_output), | |
359 | }, | |
c7566a69 AN |
360 | |
361 | /* validate field existence checks */ | |
362 | { | |
363 | EXISTENCE_CASE_COMMON(existence), | |
364 | .input = STRUCT_TO_CHAR_PTR(core_reloc_existence) { | |
365 | .a = 1, | |
366 | .b = 2, | |
367 | .c = 3, | |
368 | .arr = { 4 }, | |
369 | .s = { .x = 5 }, | |
370 | }, | |
371 | .input_len = sizeof(struct core_reloc_existence), | |
372 | .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) { | |
373 | .a_exists = 1, | |
374 | .b_exists = 1, | |
375 | .c_exists = 1, | |
376 | .arr_exists = 1, | |
377 | .s_exists = 1, | |
378 | .a_value = 1, | |
379 | .b_value = 2, | |
380 | .c_value = 3, | |
381 | .arr_value = 4, | |
382 | .s_value = 5, | |
383 | }, | |
384 | .output_len = sizeof(struct core_reloc_existence_output), | |
385 | }, | |
386 | { | |
387 | EXISTENCE_CASE_COMMON(existence___minimal), | |
388 | .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) { | |
389 | .a = 42, | |
390 | }, | |
391 | .input_len = sizeof(struct core_reloc_existence), | |
392 | .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) { | |
393 | .a_exists = 1, | |
394 | .b_exists = 0, | |
395 | .c_exists = 0, | |
396 | .arr_exists = 0, | |
397 | .s_exists = 0, | |
398 | .a_value = 42, | |
399 | .b_value = 0xff000002u, | |
400 | .c_value = 0xff000003u, | |
401 | .arr_value = 0xff000004u, | |
402 | .s_value = 0xff000005u, | |
403 | }, | |
404 | .output_len = sizeof(struct core_reloc_existence_output), | |
405 | }, | |
406 | ||
407 | EXISTENCE_ERR_CASE(existence__err_int_sz), | |
408 | EXISTENCE_ERR_CASE(existence__err_int_type), | |
409 | EXISTENCE_ERR_CASE(existence__err_int_kind), | |
410 | EXISTENCE_ERR_CASE(existence__err_arr_kind), | |
411 | EXISTENCE_ERR_CASE(existence__err_arr_value_type), | |
412 | EXISTENCE_ERR_CASE(existence__err_struct_type), | |
8b1cb1c9 AN |
413 | |
414 | /* bitfield relocation checks */ | |
415 | BITFIELDS_CASE(bitfields, { | |
416 | .ub1 = 1, | |
417 | .ub2 = 2, | |
418 | .ub7 = 96, | |
419 | .sb4 = -7, | |
420 | .sb20 = -0x76543, | |
421 | .u32 = 0x80000000, | |
422 | .s32 = -0x76543210, | |
423 | }), | |
424 | BITFIELDS_CASE(bitfields___bit_sz_change, { | |
425 | .ub1 = 6, | |
426 | .ub2 = 0xABCDE, | |
427 | .ub7 = 1, | |
428 | .sb4 = -1, | |
429 | .sb20 = -0x17654321, | |
430 | .u32 = 0xBEEF, | |
431 | .s32 = -0x3FEDCBA987654321, | |
432 | }), | |
433 | BITFIELDS_CASE(bitfields___bitfield_vs_int, { | |
434 | .ub1 = 0xFEDCBA9876543210, | |
435 | .ub2 = 0xA6, | |
436 | .ub7 = -0x7EDCBA987654321, | |
437 | .sb4 = -0x6123456789ABCDE, | |
438 | .sb20 = 0xD00D, | |
439 | .u32 = -0x76543, | |
440 | .s32 = 0x0ADEADBEEFBADB0B, | |
441 | }), | |
442 | BITFIELDS_CASE(bitfields___just_big_enough, { | |
443 | .ub1 = 0xF, | |
444 | .ub2 = 0x0812345678FEDCBA, | |
445 | }), | |
446 | BITFIELDS_ERR_CASE(bitfields___err_too_big_bitfield), | |
0b163565 AN |
447 | |
448 | /* size relocation checks */ | |
449 | SIZE_CASE(size), | |
450 | SIZE_CASE(size___diff_sz), | |
df36e621 AN |
451 | }; |
452 | ||
453 | struct data { | |
454 | char in[256]; | |
455 | char out[256]; | |
6147a140 | 456 | uint64_t my_pid_tgid; |
df36e621 AN |
457 | }; |
458 | ||
5051b384 AN |
459 | static size_t roundup_page(size_t sz) |
460 | { | |
461 | long page_size = sysconf(_SC_PAGE_SIZE); | |
462 | return (sz + page_size - 1) / page_size * page_size; | |
463 | } | |
464 | ||
df36e621 AN |
465 | void test_core_reloc(void) |
466 | { | |
5051b384 | 467 | const size_t mmap_sz = roundup_page(sizeof(struct data)); |
df36e621 AN |
468 | struct bpf_object_load_attr load_attr = {}; |
469 | struct core_reloc_test_case *test_case; | |
8b1cb1c9 | 470 | const char *tp_name, *probe_name; |
df36e621 AN |
471 | int err, duration = 0, i, equal; |
472 | struct bpf_link *link = NULL; | |
473 | struct bpf_map *data_map; | |
474 | struct bpf_program *prog; | |
475 | struct bpf_object *obj; | |
6147a140 | 476 | uint64_t my_pid_tgid; |
5051b384 AN |
477 | struct data *data; |
478 | void *mmap_data = NULL; | |
df36e621 | 479 | |
6147a140 AN |
480 | my_pid_tgid = getpid() | ((uint64_t)syscall(SYS_gettid) << 32); |
481 | ||
df36e621 AN |
482 | for (i = 0; i < ARRAY_SIZE(test_cases); i++) { |
483 | test_case = &test_cases[i]; | |
df36e621 AN |
484 | if (!test__start_subtest(test_case->case_name)) |
485 | continue; | |
486 | ||
e00aca65 | 487 | DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts, |
c7566a69 AN |
488 | .relaxed_core_relocs = test_case->relaxed_core_relocs, |
489 | ); | |
490 | ||
491 | obj = bpf_object__open_file(test_case->bpf_obj_file, &opts); | |
5051b384 | 492 | if (CHECK(IS_ERR(obj), "obj_open", "failed to open '%s': %ld\n", |
df36e621 AN |
493 | test_case->bpf_obj_file, PTR_ERR(obj))) |
494 | continue; | |
495 | ||
8b1cb1c9 AN |
496 | /* for typed raw tracepoints, NULL should be specified */ |
497 | if (test_case->direct_raw_tp) { | |
498 | probe_name = "tp_btf/sys_enter"; | |
499 | tp_name = NULL; | |
500 | } else { | |
501 | probe_name = "raw_tracepoint/sys_enter"; | |
502 | tp_name = "sys_enter"; | |
503 | } | |
504 | ||
df36e621 AN |
505 | prog = bpf_object__find_program_by_title(obj, probe_name); |
506 | if (CHECK(!prog, "find_probe", | |
507 | "prog '%s' not found\n", probe_name)) | |
508 | goto cleanup; | |
df36e621 AN |
509 | |
510 | load_attr.obj = obj; | |
511 | load_attr.log_level = 0; | |
512 | load_attr.target_btf_path = test_case->btf_src_file; | |
513 | err = bpf_object__load_xattr(&load_attr); | |
514 | if (test_case->fails) { | |
515 | CHECK(!err, "obj_load_fail", | |
516 | "should fail to load prog '%s'\n", probe_name); | |
517 | goto cleanup; | |
518 | } else { | |
519 | if (CHECK(err, "obj_load", | |
520 | "failed to load prog '%s': %d\n", | |
521 | probe_name, err)) | |
522 | goto cleanup; | |
523 | } | |
524 | ||
df36e621 AN |
525 | data_map = bpf_object__find_map_by_name(obj, "test_cor.bss"); |
526 | if (CHECK(!data_map, "find_data_map", "data map not found\n")) | |
527 | goto cleanup; | |
528 | ||
5051b384 AN |
529 | mmap_data = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, |
530 | MAP_SHARED, bpf_map__fd(data_map), 0); | |
531 | if (CHECK(mmap_data == MAP_FAILED, "mmap", | |
532 | ".bss mmap failed: %d", errno)) { | |
533 | mmap_data = NULL; | |
df36e621 | 534 | goto cleanup; |
5051b384 AN |
535 | } |
536 | data = mmap_data; | |
537 | ||
538 | memset(mmap_data, 0, sizeof(*data)); | |
539 | memcpy(data->in, test_case->input, test_case->input_len); | |
6147a140 AN |
540 | data->my_pid_tgid = my_pid_tgid; |
541 | ||
542 | link = bpf_program__attach_raw_tracepoint(prog, tp_name); | |
543 | if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", | |
544 | PTR_ERR(link))) | |
545 | goto cleanup; | |
df36e621 AN |
546 | |
547 | /* trigger test run */ | |
548 | usleep(1); | |
549 | ||
5051b384 | 550 | equal = memcmp(data->out, test_case->output, |
df36e621 AN |
551 | test_case->output_len) == 0; |
552 | if (CHECK(!equal, "check_result", | |
553 | "input/output data don't match\n")) { | |
554 | int j; | |
555 | ||
556 | for (j = 0; j < test_case->input_len; j++) { | |
557 | printf("input byte #%d: 0x%02hhx\n", | |
558 | j, test_case->input[j]); | |
559 | } | |
560 | for (j = 0; j < test_case->output_len; j++) { | |
561 | printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n", | |
5051b384 | 562 | j, test_case->output[j], data->out[j]); |
df36e621 AN |
563 | } |
564 | goto cleanup; | |
565 | } | |
566 | ||
567 | cleanup: | |
5051b384 AN |
568 | if (mmap_data) { |
569 | CHECK_FAIL(munmap(mmap_data, mmap_sz)); | |
570 | mmap_data = NULL; | |
571 | } | |
df36e621 AN |
572 | if (!IS_ERR_OR_NULL(link)) { |
573 | bpf_link__destroy(link); | |
574 | link = NULL; | |
575 | } | |
576 | bpf_object__close(obj); | |
577 | } | |
578 | } |