xref: /linux/tools/testing/selftests/bpf/prog_tests/core_reloc.c (revision ce36e38beb6863664994f5676122359c8d323203)
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include <test_progs.h>
4 #include "progs/core_reloc_types.h"
5 #include "test_kmods/bpf_testmod.h"
6 #include <linux/limits.h>
7 #include <sys/mman.h>
8 #include <sys/syscall.h>
9 #include <bpf/btf.h>
10 #include "bpftool_helpers.h"
11 
12 static int duration = 0;
13 
14 #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
15 
16 #define MODULES_CASE(name, pg_name, tp_name) {				\
17 	.case_name = name,						\
18 	.bpf_obj_file = "test_core_reloc_module.bpf.o",			\
19 	.btf_src_file = NULL, /* find in kernel module BTFs */		\
20 	.input = "",							\
21 	.input_len = 0,							\
22 	.output = STRUCT_TO_CHAR_PTR(core_reloc_module_output) {	\
23 		.read_ctx_sz = sizeof(struct bpf_testmod_test_read_ctx),\
24 		.read_ctx_exists = true,				\
25 		.buf_exists = true,					\
26 		.len_exists = true,					\
27 		.off_exists = true,					\
28 		.len = 123,						\
29 		.off = 0,						\
30 		.comm = "test_progs",					\
31 		.comm_len = sizeof("test_progs"),			\
32 	},								\
33 	.output_len = sizeof(struct core_reloc_module_output),		\
34 	.prog_name = pg_name,						\
35 	.raw_tp_name = tp_name,						\
36 	.trigger = __trigger_module_test_read,				\
37 	.needs_testmod = true,						\
38 }
39 
40 #define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {	\
41 	.a = 42,							\
42 	.b = 0xc001,							\
43 	.c = 0xbeef,							\
44 }
45 
46 #define FLAVORS_CASE_COMMON(name)					\
47 	.case_name = #name,						\
48 	.bpf_obj_file = "test_core_reloc_flavors.bpf.o",		\
49 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
50 	.raw_tp_name = "sys_enter",					\
51 	.prog_name = "test_core_flavors"				\
52 
53 #define FLAVORS_CASE(name) {						\
54 	FLAVORS_CASE_COMMON(name),					\
55 	.input = FLAVORS_DATA(core_reloc_##name),			\
56 	.input_len = sizeof(struct core_reloc_##name),			\
57 	.output = FLAVORS_DATA(core_reloc_flavors),			\
58 	.output_len = sizeof(struct core_reloc_flavors),		\
59 }
60 
61 #define FLAVORS_ERR_CASE(name) {					\
62 	FLAVORS_CASE_COMMON(name),					\
63 	.fails = true,							\
64 }
65 
66 #define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {	\
67 	.a = { .a = { .a = 42 } },					\
68 	.b = { .b = { .b = 0xc001 } },					\
69 }
70 
71 #define NESTING_CASE_COMMON(name)					\
72 	.case_name = #name,						\
73 	.bpf_obj_file = "test_core_reloc_nesting.bpf.o",		\
74 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
75 	.raw_tp_name = "sys_enter",					\
76 	.prog_name = "test_core_nesting"				\
77 
78 #define NESTING_CASE(name) {						\
79 	NESTING_CASE_COMMON(name),					\
80 	.input = NESTING_DATA(core_reloc_##name),			\
81 	.input_len = sizeof(struct core_reloc_##name),			\
82 	.output = NESTING_DATA(core_reloc_nesting),			\
83 	.output_len = sizeof(struct core_reloc_nesting)			\
84 }
85 
86 #define NESTING_ERR_CASE(name) {					\
87 	NESTING_CASE_COMMON(name),					\
88 	.fails = true,							\
89 	.run_btfgen_fails = true,					\
90 }
91 
92 #define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {	\
93 	.a = { [2] = 1, [3] = 11 },					\
94 	.b = { [1] = { [2] = { [3] = 2 } } },				\
95 	.c = { [1] = { .c =  3 } },					\
96 	.d = { [0] = { [0] = { .d = 4 } } },				\
97 }
98 
99 #define ARRAYS_CASE_COMMON(name)					\
100 	.case_name = #name,						\
101 	.bpf_obj_file = "test_core_reloc_arrays.bpf.o",			\
102 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
103 	.raw_tp_name = "sys_enter",					\
104 	.prog_name = "test_core_arrays"					\
105 
106 #define ARRAYS_CASE(name) {						\
107 	ARRAYS_CASE_COMMON(name),					\
108 	.input = ARRAYS_DATA(core_reloc_##name),			\
109 	.input_len = sizeof(struct core_reloc_##name),			\
110 	.output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) {	\
111 		.a2   = 1,						\
112 		.a3   = 12,						\
113 		.b123 = 2,						\
114 		.c1c  = 3,						\
115 		.d00d = 4,						\
116 		.f10c = 0,						\
117 	},								\
118 	.output_len = sizeof(struct core_reloc_arrays_output)		\
119 }
120 
121 #define ARRAYS_ERR_CASE(name) {						\
122 	ARRAYS_CASE_COMMON(name),					\
123 	.fails = true,							\
124 }
125 
126 #define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {	\
127 	.a = 1,								\
128 	.b = 2,								\
129 	.c = 3,								\
130 	.d = (void *)4,							\
131 	.f = (void *)5,							\
132 }
133 
134 #define PRIMITIVES_CASE_COMMON(name)					\
135 	.case_name = #name,						\
136 	.bpf_obj_file = "test_core_reloc_primitives.bpf.o",		\
137 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
138 	.raw_tp_name = "sys_enter",					\
139 	.prog_name = "test_core_primitives"				\
140 
141 #define PRIMITIVES_CASE(name) {						\
142 	PRIMITIVES_CASE_COMMON(name),					\
143 	.input = PRIMITIVES_DATA(core_reloc_##name),			\
144 	.input_len = sizeof(struct core_reloc_##name),			\
145 	.output = PRIMITIVES_DATA(core_reloc_primitives),		\
146 	.output_len = sizeof(struct core_reloc_primitives),		\
147 }
148 
149 #define PRIMITIVES_ERR_CASE(name) {					\
150 	PRIMITIVES_CASE_COMMON(name),					\
151 	.fails = true,							\
152 }
153 
154 #define MODS_CASE(name) {						\
155 	.case_name = #name,						\
156 	.bpf_obj_file = "test_core_reloc_mods.bpf.o",			\
157 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
158 	.input = STRUCT_TO_CHAR_PTR(core_reloc_##name) {		\
159 		.a = 1,							\
160 		.b = 2,							\
161 		.c = (void *)3,						\
162 		.d = (void *)4,						\
163 		.e = { [2] = 5 },					\
164 		.f = { [1] = 6 },					\
165 		.g = { .x = 7 },					\
166 		.h = { .y = 8 },					\
167 	},								\
168 	.input_len = sizeof(struct core_reloc_##name),			\
169 	.output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) {		\
170 		.a = 1, .b = 2, .c = 3, .d = 4,				\
171 		.e = 5, .f = 6, .g = 7, .h = 8,				\
172 	},								\
173 	.output_len = sizeof(struct core_reloc_mods_output),		\
174 	.raw_tp_name = "sys_enter",					\
175 	.prog_name = "test_core_mods",					\
176 }
177 
178 #define PTR_AS_ARR_CASE(name) {						\
179 	.case_name = #name,						\
180 	.bpf_obj_file = "test_core_reloc_ptr_as_arr.bpf.o",		\
181 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
182 	.input = (const char *)&(struct core_reloc_##name []){		\
183 		{ .a = 1 },						\
184 		{ .a = 2 },						\
185 		{ .a = 3 },						\
186 	},								\
187 	.input_len = 3 * sizeof(struct core_reloc_##name),		\
188 	.output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) {		\
189 		.a = 3,							\
190 	},								\
191 	.output_len = sizeof(struct core_reloc_ptr_as_arr),		\
192 	.raw_tp_name = "sys_enter",					\
193 	.prog_name = "test_core_ptr_as_arr",				\
194 }
195 
196 #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) {	\
197 	.u8_field = 1,							\
198 	.s8_field = 2,							\
199 	.u16_field = 3,							\
200 	.s16_field = 4,							\
201 	.u32_field = 5,							\
202 	.s32_field = 6,							\
203 	.u64_field = 7,							\
204 	.s64_field = 8,							\
205 }
206 
207 #define INTS_CASE_COMMON(name)						\
208 	.case_name = #name,						\
209 	.bpf_obj_file = "test_core_reloc_ints.bpf.o",			\
210 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
211 	.raw_tp_name = "sys_enter",					\
212 	.prog_name = "test_core_ints"
213 
214 #define INTS_CASE(name) {						\
215 	INTS_CASE_COMMON(name),						\
216 	.input = INTS_DATA(core_reloc_##name),				\
217 	.input_len = sizeof(struct core_reloc_##name),			\
218 	.output = INTS_DATA(core_reloc_ints),				\
219 	.output_len = sizeof(struct core_reloc_ints),			\
220 }
221 
222 #define INTS_ERR_CASE(name) {						\
223 	INTS_CASE_COMMON(name),						\
224 	.fails = true,							\
225 }
226 
227 #define FIELD_EXISTS_CASE_COMMON(name)					\
228 	.case_name = #name,						\
229 	.bpf_obj_file = "test_core_reloc_existence.bpf.o",		\
230 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
231 	.raw_tp_name = "sys_enter",					\
232 	.prog_name = "test_core_existence"
233 
234 #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix,  name)		\
235 	.case_name = test_name_prefix#name,				\
236 	.bpf_obj_file = objfile,					\
237 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o"
238 
239 #define BITFIELDS_CASE(name, ...) {					\
240 	BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.bpf.o",	\
241 			      "probed:", name),				\
242 	.input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__,	\
243 	.input_len = sizeof(struct core_reloc_##name),			\
244 	.output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output)	\
245 		__VA_ARGS__,						\
246 	.output_len = sizeof(struct core_reloc_bitfields_output),	\
247 	.raw_tp_name = "sys_enter",					\
248 	.prog_name = "test_core_bitfields",				\
249 }, {									\
250 	BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.bpf.o",	\
251 			      "direct:", name),				\
252 	.input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__,	\
253 	.input_len = sizeof(struct core_reloc_##name),			\
254 	.output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output)	\
255 		__VA_ARGS__,						\
256 	.output_len = sizeof(struct core_reloc_bitfields_output),	\
257 	.prog_name = "test_core_bitfields_direct",			\
258 }
259 
260 
261 #define BITFIELDS_ERR_CASE(name) {					\
262 	BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.bpf.o",	\
263 			      "probed:", name),				\
264 	.fails = true,							\
265 	.run_btfgen_fails = true,					\
266 	.raw_tp_name = "sys_enter",					\
267 	.prog_name = "test_core_bitfields",				\
268 }, {									\
269 	BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.bpf.o",	\
270 			      "direct:", name),				\
271 	.fails = true,							\
272 	.run_btfgen_fails = true,							\
273 	.prog_name = "test_core_bitfields_direct",			\
274 }
275 
276 #define SIZE_CASE_COMMON(name)						\
277 	.case_name = #name,						\
278 	.bpf_obj_file = "test_core_reloc_size.bpf.o",			\
279 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
280 	.raw_tp_name = "sys_enter",					\
281 	.prog_name = "test_core_size"
282 
283 #define SIZE_OUTPUT_DATA(type)						\
284 	STRUCT_TO_CHAR_PTR(core_reloc_size_output) {			\
285 		.int_sz = sizeof(((type *)0)->int_field),		\
286 		.int_off = offsetof(type, int_field),			\
287 		.struct_sz = sizeof(((type *)0)->struct_field),		\
288 		.struct_off = offsetof(type, struct_field),		\
289 		.union_sz = sizeof(((type *)0)->union_field),		\
290 		.union_off = offsetof(type, union_field),		\
291 		.arr_sz = sizeof(((type *)0)->arr_field),		\
292 		.arr_off = offsetof(type, arr_field),			\
293 		.arr_elem_sz = sizeof(((type *)0)->arr_field[1]),	\
294 		.arr_elem_off = offsetof(type, arr_field[1]),		\
295 		.ptr_sz = 8, /* always 8-byte pointer for BPF */	\
296 		.ptr_off = offsetof(type, ptr_field),			\
297 		.enum_sz = sizeof(((type *)0)->enum_field),		\
298 		.enum_off = offsetof(type, enum_field),			\
299 		.float_sz = sizeof(((type *)0)->float_field),		\
300 		.float_off = offsetof(type, float_field),		\
301 	}
302 
303 #define SIZE_CASE(name) {						\
304 	SIZE_CASE_COMMON(name),						\
305 	.input_len = 0,							\
306 	.output = SIZE_OUTPUT_DATA(struct core_reloc_##name),		\
307 	.output_len = sizeof(struct core_reloc_size_output),		\
308 }
309 
310 #define SIZE_ERR_CASE(name) {						\
311 	SIZE_CASE_COMMON(name),						\
312 	.fails = true,							\
313 	.run_btfgen_fails = true,					\
314 }
315 
316 #define TYPE_BASED_CASE_COMMON(name)					\
317 	.case_name = #name,						\
318 	.bpf_obj_file = "test_core_reloc_type_based.bpf.o",		\
319 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
320 	.raw_tp_name = "sys_enter",					\
321 	.prog_name = "test_core_type_based"
322 
323 #define TYPE_BASED_CASE(name, ...) {					\
324 	TYPE_BASED_CASE_COMMON(name),					\
325 	.output = STRUCT_TO_CHAR_PTR(core_reloc_type_based_output)	\
326 			__VA_ARGS__,					\
327 	.output_len = sizeof(struct core_reloc_type_based_output),	\
328 }
329 
330 #define TYPE_BASED_ERR_CASE(name) {					\
331 	TYPE_BASED_CASE_COMMON(name),					\
332 	.fails = true,							\
333 }
334 
335 #define TYPE_ID_CASE_COMMON(name)					\
336 	.case_name = #name,						\
337 	.bpf_obj_file = "test_core_reloc_type_id.bpf.o",		\
338 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
339 	.raw_tp_name = "sys_enter",					\
340 	.prog_name = "test_core_type_id"
341 
342 #define TYPE_ID_CASE(name, setup_fn) {					\
343 	TYPE_ID_CASE_COMMON(name),					\
344 	.output = STRUCT_TO_CHAR_PTR(core_reloc_type_id_output) {},	\
345 	.output_len = sizeof(struct core_reloc_type_id_output),		\
346 	.setup = setup_fn,						\
347 }
348 
349 #define TYPE_ID_ERR_CASE(name) {					\
350 	TYPE_ID_CASE_COMMON(name),					\
351 	.fails = true,							\
352 }
353 
354 #define ENUMVAL_CASE_COMMON(name)					\
355 	.case_name = #name,						\
356 	.bpf_obj_file = "test_core_reloc_enumval.bpf.o",		\
357 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
358 	.raw_tp_name = "sys_enter",					\
359 	.prog_name = "test_core_enumval"
360 
361 #define ENUMVAL_CASE(name, ...) {					\
362 	ENUMVAL_CASE_COMMON(name),					\
363 	.output = STRUCT_TO_CHAR_PTR(core_reloc_enumval_output)		\
364 			__VA_ARGS__,					\
365 	.output_len = sizeof(struct core_reloc_enumval_output),		\
366 }
367 
368 #define ENUMVAL_ERR_CASE(name) {					\
369 	ENUMVAL_CASE_COMMON(name),					\
370 	.fails = true,							\
371 }
372 
373 #define ENUM64VAL_CASE_COMMON(name)					\
374 	.case_name = #name,						\
375 	.bpf_obj_file = "test_core_reloc_enum64val.bpf.o",		\
376 	.btf_src_file = "btf__core_reloc_" #name ".bpf.o",		\
377 	.raw_tp_name = "sys_enter",					\
378 	.prog_name = "test_core_enum64val"
379 
380 #define ENUM64VAL_CASE(name, ...) {					\
381 	ENUM64VAL_CASE_COMMON(name),					\
382 	.output = STRUCT_TO_CHAR_PTR(core_reloc_enum64val_output)	\
383 			__VA_ARGS__,					\
384 	.output_len = sizeof(struct core_reloc_enum64val_output),	\
385 }
386 
387 #define ENUM64VAL_ERR_CASE(name) {					\
388 	ENUM64VAL_CASE_COMMON(name),					\
389 	.fails = true,							\
390 }
391 
392 struct core_reloc_test_case;
393 
394 typedef int (*setup_test_fn)(struct core_reloc_test_case *test);
395 typedef int (*trigger_test_fn)(const struct core_reloc_test_case *test);
396 
397 struct core_reloc_test_case {
398 	const char *case_name;
399 	const char *bpf_obj_file;
400 	const char *btf_src_file;
401 	const char *input;
402 	int input_len;
403 	const char *output;
404 	int output_len;
405 	bool fails;
406 	bool run_btfgen_fails;
407 	bool needs_testmod;
408 	bool relaxed_core_relocs;
409 	const char *prog_name;
410 	const char *raw_tp_name;
411 	setup_test_fn setup;
412 	trigger_test_fn trigger;
413 };
414 
415 static int find_btf_type(const struct btf *btf, const char *name, __u32 kind)
416 {
417 	int id;
418 
419 	id = btf__find_by_name_kind(btf, name, kind);
420 	if (CHECK(id <= 0, "find_type_id", "failed to find '%s', kind %d: %d\n", name, kind, id))
421 		return -1;
422 
423 	return id;
424 }
425 
426 static int setup_type_id_case_local(struct core_reloc_test_case *test)
427 {
428 	struct core_reloc_type_id_output *exp = (void *)test->output;
429 	struct btf *local_btf = btf__parse(test->bpf_obj_file, NULL);
430 	struct btf *targ_btf = btf__parse(test->btf_src_file, NULL);
431 	const struct btf_type *t;
432 	const char *name;
433 	int i;
434 
435 	if (!ASSERT_OK_PTR(local_btf, "local_btf") || !ASSERT_OK_PTR(targ_btf, "targ_btf")) {
436 		btf__free(local_btf);
437 		btf__free(targ_btf);
438 		return -EINVAL;
439 	}
440 
441 	exp->local_anon_struct = -1;
442 	exp->local_anon_union = -1;
443 	exp->local_anon_enum = -1;
444 	exp->local_anon_func_proto_ptr = -1;
445 	exp->local_anon_void_ptr = -1;
446 	exp->local_anon_arr = -1;
447 
448 	for (i = 1; i < btf__type_cnt(local_btf); i++)
449 	{
450 		t = btf__type_by_id(local_btf, i);
451 		/* we are interested only in anonymous types */
452 		if (t->name_off)
453 			continue;
454 
455 		if (btf_is_struct(t) && btf_vlen(t) &&
456 		    (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
457 		    strcmp(name, "marker_field") == 0) {
458 			exp->local_anon_struct = i;
459 		} else if (btf_is_union(t) && btf_vlen(t) &&
460 			 (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
461 			 strcmp(name, "marker_field") == 0) {
462 			exp->local_anon_union = i;
463 		} else if (btf_is_enum(t) && btf_vlen(t) &&
464 			 (name = btf__name_by_offset(local_btf, btf_enum(t)[0].name_off)) &&
465 			 strcmp(name, "MARKER_ENUM_VAL") == 0) {
466 			exp->local_anon_enum = i;
467 		} else if (btf_is_ptr(t) && (t = btf__type_by_id(local_btf, t->type))) {
468 			if (btf_is_func_proto(t) && (t = btf__type_by_id(local_btf, t->type)) &&
469 			    btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
470 			    strcmp(name, "_Bool") == 0) {
471 				/* ptr -> func_proto -> _Bool */
472 				exp->local_anon_func_proto_ptr = i;
473 			} else if (btf_is_void(t)) {
474 				/* ptr -> void */
475 				exp->local_anon_void_ptr = i;
476 			}
477 		} else if (btf_is_array(t) && (t = btf__type_by_id(local_btf, btf_array(t)->type)) &&
478 			   btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
479 			   strcmp(name, "_Bool") == 0) {
480 			/* _Bool[] */
481 			exp->local_anon_arr = i;
482 		}
483 	}
484 
485 	exp->local_struct = find_btf_type(local_btf, "a_struct", BTF_KIND_STRUCT);
486 	exp->local_union = find_btf_type(local_btf, "a_union", BTF_KIND_UNION);
487 	exp->local_enum = find_btf_type(local_btf, "an_enum", BTF_KIND_ENUM);
488 	exp->local_int = find_btf_type(local_btf, "int", BTF_KIND_INT);
489 	exp->local_struct_typedef = find_btf_type(local_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
490 	exp->local_func_proto_typedef = find_btf_type(local_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
491 	exp->local_arr_typedef = find_btf_type(local_btf, "arr_typedef", BTF_KIND_TYPEDEF);
492 
493 	btf__free(local_btf);
494 	btf__free(targ_btf);
495 	return 0;
496 }
497 
498 static int setup_type_id_case_success(struct core_reloc_test_case *test) {
499 	struct core_reloc_type_id_output *exp = (void *)test->output;
500 	struct btf *targ_btf;
501 	int err;
502 
503 	err = setup_type_id_case_local(test);
504 	if (err)
505 		return err;
506 
507 	targ_btf = btf__parse(test->btf_src_file, NULL);
508 
509 	exp->targ_struct = find_btf_type(targ_btf, "a_struct", BTF_KIND_STRUCT);
510 	exp->targ_union = find_btf_type(targ_btf, "a_union", BTF_KIND_UNION);
511 	exp->targ_enum = find_btf_type(targ_btf, "an_enum", BTF_KIND_ENUM);
512 	exp->targ_int = find_btf_type(targ_btf, "int", BTF_KIND_INT);
513 	exp->targ_struct_typedef = find_btf_type(targ_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
514 	exp->targ_func_proto_typedef = find_btf_type(targ_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
515 	exp->targ_arr_typedef = find_btf_type(targ_btf, "arr_typedef", BTF_KIND_TYPEDEF);
516 
517 	btf__free(targ_btf);
518 	return 0;
519 }
520 
521 static int setup_type_id_case_failure(struct core_reloc_test_case *test)
522 {
523 	struct core_reloc_type_id_output *exp = (void *)test->output;
524 	int err;
525 
526 	err = setup_type_id_case_local(test);
527 	if (err)
528 		return err;
529 
530 	exp->targ_struct = 0;
531 	exp->targ_union = 0;
532 	exp->targ_enum = 0;
533 	exp->targ_int = 0;
534 	exp->targ_struct_typedef = 0;
535 	exp->targ_func_proto_typedef = 0;
536 	exp->targ_arr_typedef = 0;
537 
538 	return 0;
539 }
540 
541 static int __trigger_module_test_read(const struct core_reloc_test_case *test)
542 {
543 	struct core_reloc_module_output *exp = (void *)test->output;
544 
545 	trigger_module_test_read(exp->len);
546 	return 0;
547 }
548 
549 static const struct core_reloc_test_case test_cases[] = {
550 	/* validate we can find kernel image and use its BTF for relocs */
551 	{
552 		.case_name = "kernel",
553 		.bpf_obj_file = "test_core_reloc_kernel.bpf.o",
554 		.btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */
555 		.input = "",
556 		.input_len = 0,
557 		.output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) {
558 			.valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
559 			.comm = "test_progs",
560 			.comm_len = sizeof("test_progs"),
561 			.local_task_struct_matches = true,
562 		},
563 		.output_len = sizeof(struct core_reloc_kernel_output),
564 		.raw_tp_name = "sys_enter",
565 		.prog_name = "test_core_kernel",
566 	},
567 
568 	/* validate we can find kernel module BTF types for relocs/attach */
569 	MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"),
570 	MODULES_CASE("module_direct", "test_core_module_direct", NULL),
571 
572 	/* validate BPF program can use multiple flavors to match against
573 	 * single target BTF type
574 	 */
575 	FLAVORS_CASE(flavors),
576 
577 	FLAVORS_ERR_CASE(flavors__err_wrong_name),
578 
579 	/* various struct/enum nesting and resolution scenarios */
580 	NESTING_CASE(nesting),
581 	NESTING_CASE(nesting___anon_embed),
582 	NESTING_CASE(nesting___struct_union_mixup),
583 	NESTING_CASE(nesting___extra_nesting),
584 	NESTING_CASE(nesting___dup_compat_types),
585 
586 	NESTING_ERR_CASE(nesting___err_missing_field),
587 	NESTING_ERR_CASE(nesting___err_array_field),
588 	NESTING_ERR_CASE(nesting___err_missing_container),
589 	NESTING_ERR_CASE(nesting___err_nonstruct_container),
590 	NESTING_ERR_CASE(nesting___err_array_container),
591 	NESTING_ERR_CASE(nesting___err_dup_incompat_types),
592 	NESTING_ERR_CASE(nesting___err_partial_match_dups),
593 	NESTING_ERR_CASE(nesting___err_too_deep),
594 
595 	/* various array access relocation scenarios */
596 	ARRAYS_CASE(arrays),
597 	ARRAYS_CASE(arrays___diff_arr_dim),
598 	ARRAYS_CASE(arrays___diff_arr_val_sz),
599 	ARRAYS_CASE(arrays___equiv_zero_sz_arr),
600 	ARRAYS_CASE(arrays___fixed_arr),
601 
602 	ARRAYS_ERR_CASE(arrays___err_too_small),
603 	ARRAYS_ERR_CASE(arrays___err_too_shallow),
604 	ARRAYS_ERR_CASE(arrays___err_non_array),
605 	ARRAYS_ERR_CASE(arrays___err_wrong_val_type),
606 	ARRAYS_ERR_CASE(arrays___err_bad_zero_sz_arr),
607 	ARRAYS_ERR_CASE(arrays___err_bad_signed_arr_elem_sz),
608 
609 	/* enum/ptr/int handling scenarios */
610 	PRIMITIVES_CASE(primitives),
611 	PRIMITIVES_CASE(primitives___diff_enum_def),
612 	PRIMITIVES_CASE(primitives___diff_func_proto),
613 	PRIMITIVES_CASE(primitives___diff_ptr_type),
614 
615 	PRIMITIVES_ERR_CASE(primitives___err_non_enum),
616 	PRIMITIVES_ERR_CASE(primitives___err_non_int),
617 	PRIMITIVES_ERR_CASE(primitives___err_non_ptr),
618 
619 	/* const/volatile/restrict and typedefs scenarios */
620 	MODS_CASE(mods),
621 	MODS_CASE(mods___mod_swap),
622 	MODS_CASE(mods___typedefs),
623 
624 	/* handling "ptr is an array" semantics */
625 	PTR_AS_ARR_CASE(ptr_as_arr),
626 	PTR_AS_ARR_CASE(ptr_as_arr___diff_sz),
627 
628 	/* int signedness/sizing/bitfield handling */
629 	INTS_CASE(ints),
630 	INTS_CASE(ints___bool),
631 	INTS_CASE(ints___reverse_sign),
632 
633 	/* validate edge cases of capturing relocations */
634 	{
635 		.case_name = "misc",
636 		.bpf_obj_file = "test_core_reloc_misc.bpf.o",
637 		.btf_src_file = "btf__core_reloc_misc.bpf.o",
638 		.input = (const char *)&(struct core_reloc_misc_extensible[]){
639 			{ .a = 1 },
640 			{ .a = 2 }, /* not read */
641 			{ .a = 3 },
642 		},
643 		.input_len = 4 * sizeof(int),
644 		.output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) {
645 			.a = 1,
646 			.b = 1,
647 			.c = 0, /* BUG in clang, should be 3 */
648 		},
649 		.output_len = sizeof(struct core_reloc_misc_output),
650 		.raw_tp_name = "sys_enter",
651 		.prog_name = "test_core_misc",
652 	},
653 
654 	/* validate field existence checks */
655 	{
656 		FIELD_EXISTS_CASE_COMMON(existence),
657 		.input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
658 			.a = 1,
659 			.b = 2,
660 			.c = 3,
661 			.arr = { 4 },
662 			.s = { .x = 5 },
663 		},
664 		.input_len = sizeof(struct core_reloc_existence),
665 		.output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
666 			.a_exists = 1,
667 			.b_exists = 1,
668 			.c_exists = 1,
669 			.arr_exists = 1,
670 			.s_exists = 1,
671 			.a_value = 1,
672 			.b_value = 2,
673 			.c_value = 3,
674 			.arr_value = 4,
675 			.s_value = 5,
676 		},
677 		.output_len = sizeof(struct core_reloc_existence_output),
678 	},
679 	{
680 		FIELD_EXISTS_CASE_COMMON(existence___minimal),
681 		.input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
682 			.a = 42,
683 		},
684 		.input_len = sizeof(struct core_reloc_existence___minimal),
685 		.output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
686 			.a_exists = 1,
687 			.b_exists = 0,
688 			.c_exists = 0,
689 			.arr_exists = 0,
690 			.s_exists = 0,
691 			.a_value = 42,
692 			.b_value = 0xff000002u,
693 			.c_value = 0xff000003u,
694 			.arr_value = 0xff000004u,
695 			.s_value = 0xff000005u,
696 		},
697 		.output_len = sizeof(struct core_reloc_existence_output),
698 	},
699 	{
700 		FIELD_EXISTS_CASE_COMMON(existence___wrong_field_defs),
701 		.input = STRUCT_TO_CHAR_PTR(core_reloc_existence___wrong_field_defs) {
702 		},
703 		.input_len = sizeof(struct core_reloc_existence___wrong_field_defs),
704 		.output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
705 			.a_exists = 0,
706 			.b_exists = 0,
707 			.c_exists = 0,
708 			.arr_exists = 0,
709 			.s_exists = 0,
710 			.a_value = 0xff000001u,
711 			.b_value = 0xff000002u,
712 			.c_value = 0xff000003u,
713 			.arr_value = 0xff000004u,
714 			.s_value = 0xff000005u,
715 		},
716 		.output_len = sizeof(struct core_reloc_existence_output),
717 	},
718 
719 	/* bitfield relocation checks */
720 	BITFIELDS_CASE(bitfields, {
721 		.ub1 = 1,
722 		.ub2 = 2,
723 		.ub7 = 96,
724 		.sb4 = -7,
725 		.sb20 = -0x76543,
726 		.u32 = 0x80000000,
727 		.s32 = -0x76543210,
728 	}),
729 	BITFIELDS_CASE(bitfields___bit_sz_change, {
730 		.ub1 = 6,
731 		.ub2 = 0xABCDE,
732 		.ub7 = 1,
733 		.sb4 = -1,
734 		.sb20 = -0x17654321,
735 		.u32 = 0xBEEF,
736 		.s32 = -0x3FEDCBA987654321LL,
737 	}),
738 	BITFIELDS_CASE(bitfields___bitfield_vs_int, {
739 		.ub1 = 0xFEDCBA9876543210LL,
740 		.ub2 = 0xA6,
741 		.ub7 = -0x7EDCBA987654321LL,
742 		.sb4 = -0x6123456789ABCDELL,
743 		.sb20 = 0xD00DLL,
744 		.u32 = -0x76543,
745 		.s32 = 0x0ADEADBEEFBADB0BLL,
746 	}),
747 	BITFIELDS_CASE(bitfields___just_big_enough, {
748 		.ub1 = 0xFLL,
749 		.ub2 = 0x0812345678FEDCBALL,
750 	}),
751 	BITFIELDS_ERR_CASE(bitfields___err_too_big_bitfield),
752 
753 	/* field size and offset relocation checks */
754 	SIZE_CASE(size),
755 	SIZE_CASE(size___diff_sz),
756 	SIZE_CASE(size___diff_offs),
757 	SIZE_ERR_CASE(size___err_ambiguous),
758 
759 	/* validate type existence, match, and size relocations */
760 	TYPE_BASED_CASE(type_based, {
761 		.struct_exists = 1,
762 		.complex_struct_exists = 1,
763 		.union_exists = 1,
764 		.enum_exists = 1,
765 		.typedef_named_struct_exists = 1,
766 		.typedef_anon_struct_exists = 1,
767 		.typedef_struct_ptr_exists = 1,
768 		.typedef_int_exists = 1,
769 		.typedef_enum_exists = 1,
770 		.typedef_void_ptr_exists = 1,
771 		.typedef_restrict_ptr_exists = 1,
772 		.typedef_func_proto_exists = 1,
773 		.typedef_arr_exists = 1,
774 
775 		.struct_matches = 1,
776 		.complex_struct_matches = 1,
777 		.union_matches = 1,
778 		.enum_matches = 1,
779 		.typedef_named_struct_matches = 1,
780 		.typedef_anon_struct_matches = 1,
781 		.typedef_struct_ptr_matches = 1,
782 		.typedef_int_matches = 1,
783 		.typedef_enum_matches = 1,
784 		.typedef_void_ptr_matches = 1,
785 		.typedef_restrict_ptr_matches = 1,
786 		.typedef_func_proto_matches = 1,
787 		.typedef_arr_matches = 1,
788 
789 		.struct_sz = sizeof(struct a_struct),
790 		.union_sz = sizeof(union a_union),
791 		.enum_sz = sizeof(enum an_enum),
792 		.typedef_named_struct_sz = sizeof(named_struct_typedef),
793 		.typedef_anon_struct_sz = sizeof(anon_struct_typedef),
794 		.typedef_struct_ptr_sz = sizeof(struct_ptr_typedef),
795 		.typedef_int_sz = sizeof(int_typedef),
796 		.typedef_enum_sz = sizeof(enum_typedef),
797 		.typedef_void_ptr_sz = sizeof(void_ptr_typedef),
798 		.typedef_func_proto_sz = sizeof(func_proto_typedef),
799 		.typedef_arr_sz = sizeof(arr_typedef),
800 	}),
801 	TYPE_BASED_CASE(type_based___all_missing, {
802 		/* all zeros */
803 	}),
804 	TYPE_BASED_CASE(type_based___diff, {
805 		.struct_exists = 1,
806 		.complex_struct_exists = 1,
807 		.union_exists = 1,
808 		.enum_exists = 1,
809 		.typedef_named_struct_exists = 1,
810 		.typedef_anon_struct_exists = 1,
811 		.typedef_struct_ptr_exists = 1,
812 		.typedef_int_exists = 1,
813 		.typedef_enum_exists = 1,
814 		.typedef_void_ptr_exists = 1,
815 		.typedef_func_proto_exists = 1,
816 		.typedef_arr_exists = 1,
817 
818 		.struct_matches = 1,
819 		.complex_struct_matches = 1,
820 		.union_matches = 1,
821 		.enum_matches = 1,
822 		.typedef_named_struct_matches = 1,
823 		.typedef_anon_struct_matches = 1,
824 		.typedef_struct_ptr_matches = 1,
825 		.typedef_int_matches = 0,
826 		.typedef_enum_matches = 1,
827 		.typedef_void_ptr_matches = 1,
828 		.typedef_func_proto_matches = 0,
829 		.typedef_arr_matches = 0,
830 
831 		.struct_sz = sizeof(struct a_struct___diff),
832 		.union_sz = sizeof(union a_union___diff),
833 		.enum_sz = sizeof(enum an_enum___diff),
834 		.typedef_named_struct_sz = sizeof(named_struct_typedef___diff),
835 		.typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff),
836 		.typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff),
837 		.typedef_int_sz = sizeof(int_typedef___diff),
838 		.typedef_enum_sz = sizeof(enum_typedef___diff),
839 		.typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff),
840 		.typedef_func_proto_sz = sizeof(func_proto_typedef___diff),
841 		.typedef_arr_sz = sizeof(arr_typedef___diff),
842 	}),
843 	TYPE_BASED_CASE(type_based___diff_sz, {
844 		.struct_exists = 1,
845 		.union_exists = 1,
846 		.enum_exists = 1,
847 		.typedef_named_struct_exists = 1,
848 		.typedef_anon_struct_exists = 1,
849 		.typedef_struct_ptr_exists = 1,
850 		.typedef_int_exists = 1,
851 		.typedef_enum_exists = 1,
852 		.typedef_void_ptr_exists = 1,
853 		.typedef_func_proto_exists = 1,
854 		.typedef_arr_exists = 1,
855 
856 		.struct_matches = 0,
857 		.union_matches = 0,
858 		.enum_matches = 0,
859 		.typedef_named_struct_matches = 0,
860 		.typedef_anon_struct_matches = 0,
861 		.typedef_struct_ptr_matches = 1,
862 		.typedef_int_matches = 0,
863 		.typedef_enum_matches = 0,
864 		.typedef_void_ptr_matches = 1,
865 		.typedef_func_proto_matches = 0,
866 		.typedef_arr_matches = 0,
867 
868 		.struct_sz = sizeof(struct a_struct___diff_sz),
869 		.union_sz = sizeof(union a_union___diff_sz),
870 		.enum_sz = sizeof(enum an_enum___diff_sz),
871 		.typedef_named_struct_sz = sizeof(named_struct_typedef___diff_sz),
872 		.typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff_sz),
873 		.typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff_sz),
874 		.typedef_int_sz = sizeof(int_typedef___diff_sz),
875 		.typedef_enum_sz = sizeof(enum_typedef___diff_sz),
876 		.typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff_sz),
877 		.typedef_func_proto_sz = sizeof(func_proto_typedef___diff_sz),
878 		.typedef_arr_sz = sizeof(arr_typedef___diff_sz),
879 	}),
880 	TYPE_BASED_CASE(type_based___incompat, {
881 		.enum_exists = 1,
882 		.enum_matches = 1,
883 		.enum_sz = sizeof(enum an_enum),
884 	}),
885 	TYPE_BASED_CASE(type_based___fn_wrong_args, {
886 		.struct_exists = 1,
887 		.struct_matches = 1,
888 		.struct_sz = sizeof(struct a_struct),
889 	}),
890 
891 	/* BTF_TYPE_ID_LOCAL/BTF_TYPE_ID_TARGET tests */
892 	TYPE_ID_CASE(type_id, setup_type_id_case_success),
893 	TYPE_ID_CASE(type_id___missing_targets, setup_type_id_case_failure),
894 
895 	/* Enumerator value existence and value relocations */
896 	ENUMVAL_CASE(enumval, {
897 		.named_val1_exists = true,
898 		.named_val2_exists = true,
899 		.named_val3_exists = true,
900 		.anon_val1_exists = true,
901 		.anon_val2_exists = true,
902 		.anon_val3_exists = true,
903 		.named_val1 = 1,
904 		.named_val2 = 2,
905 		.anon_val1 = 0x10,
906 		.anon_val2 = 0x20,
907 	}),
908 	ENUMVAL_CASE(enumval___diff, {
909 		.named_val1_exists = true,
910 		.named_val2_exists = true,
911 		.named_val3_exists = true,
912 		.anon_val1_exists = true,
913 		.anon_val2_exists = true,
914 		.anon_val3_exists = true,
915 		.named_val1 = 101,
916 		.named_val2 = 202,
917 		.anon_val1 = 0x11,
918 		.anon_val2 = 0x22,
919 	}),
920 	ENUMVAL_CASE(enumval___val3_missing, {
921 		.named_val1_exists = true,
922 		.named_val2_exists = true,
923 		.named_val3_exists = false,
924 		.anon_val1_exists = true,
925 		.anon_val2_exists = true,
926 		.anon_val3_exists = false,
927 		.named_val1 = 111,
928 		.named_val2 = 222,
929 		.anon_val1 = 0x111,
930 		.anon_val2 = 0x222,
931 	}),
932 	ENUMVAL_ERR_CASE(enumval___err_missing),
933 
934 	/* 64bit enumerator value existence and value relocations */
935 	ENUM64VAL_CASE(enum64val, {
936 		.unsigned_val1_exists = true,
937 		.unsigned_val2_exists = true,
938 		.unsigned_val3_exists = true,
939 		.signed_val1_exists = true,
940 		.signed_val2_exists = true,
941 		.signed_val3_exists = true,
942 		.unsigned_val1 = 0x1ffffffffULL,
943 		.unsigned_val2 = 0x2,
944 		.signed_val1 = 0x1ffffffffLL,
945 		.signed_val2 = -2,
946 	}),
947 	ENUM64VAL_CASE(enum64val___diff, {
948 		.unsigned_val1_exists = true,
949 		.unsigned_val2_exists = true,
950 		.unsigned_val3_exists = true,
951 		.signed_val1_exists = true,
952 		.signed_val2_exists = true,
953 		.signed_val3_exists = true,
954 		.unsigned_val1 = 0x101ffffffffULL,
955 		.unsigned_val2 = 0x202ffffffffULL,
956 		.signed_val1 = -101,
957 		.signed_val2 = -202,
958 	}),
959 	ENUM64VAL_CASE(enum64val___val3_missing, {
960 		.unsigned_val1_exists = true,
961 		.unsigned_val2_exists = true,
962 		.unsigned_val3_exists = false,
963 		.signed_val1_exists = true,
964 		.signed_val2_exists = true,
965 		.signed_val3_exists = false,
966 		.unsigned_val1 = 0x111ffffffffULL,
967 		.unsigned_val2 = 0x222,
968 		.signed_val1 = 0x111ffffffffLL,
969 		.signed_val2 = -222,
970 	}),
971 	ENUM64VAL_ERR_CASE(enum64val___err_missing),
972 };
973 
974 struct data {
975 	char in[256];
976 	char out[256];
977 	bool skip;
978 	uint64_t my_pid_tgid;
979 };
980 
981 static size_t roundup_page(size_t sz)
982 {
983 	long page_size = sysconf(_SC_PAGE_SIZE);
984 	return (sz + page_size - 1) / page_size * page_size;
985 }
986 
987 static int run_btfgen(const char *src_btf, const char *dst_btf, const char *objpath)
988 {
989 	char args[4096];
990 	int n;
991 
992 	n = snprintf(args, sizeof(args), "gen min_core_btf %s %s %s",
993 		     src_btf, dst_btf, objpath);
994 	if (n < 0 || n >= sizeof(args))
995 		return -1;
996 
997 	return run_bpftool_command(args);
998 }
999 
1000 static void run_core_reloc_tests(bool use_btfgen)
1001 {
1002 	const size_t mmap_sz = roundup_page(sizeof(struct data));
1003 	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts);
1004 	struct core_reloc_test_case *test_case, test_case_copy;
1005 	const char *tp_name, *probe_name;
1006 	int err, i, equal, fd;
1007 	struct bpf_link *link = NULL;
1008 	struct bpf_map *data_map;
1009 	struct bpf_program *prog;
1010 	struct bpf_object *obj;
1011 	uint64_t my_pid_tgid;
1012 	struct data *data;
1013 	void *mmap_data = NULL;
1014 
1015 	my_pid_tgid = getpid() | ((uint64_t)sys_gettid() << 32);
1016 
1017 	for (i = 0; i < ARRAY_SIZE(test_cases); i++) {
1018 		char btf_file[] = "/tmp/core_reloc.btf.XXXXXX";
1019 
1020 		test_case_copy = test_cases[i];
1021 		test_case = &test_case_copy;
1022 
1023 		if (!test__start_subtest(test_case->case_name))
1024 			continue;
1025 
1026 		if (test_case->needs_testmod && !env.has_testmod) {
1027 			test__skip();
1028 			continue;
1029 		}
1030 
1031 		/* generate a "minimal" BTF file and use it as source */
1032 		if (use_btfgen) {
1033 
1034 			if (!test_case->btf_src_file || test_case->run_btfgen_fails) {
1035 				test__skip();
1036 				continue;
1037 			}
1038 
1039 			fd = mkstemp(btf_file);
1040 			if (!ASSERT_GE(fd, 0, "btf_tmp"))
1041 				continue;
1042 			close(fd); /* we only need the path */
1043 			err = run_btfgen(test_case->btf_src_file, btf_file,
1044 					 test_case->bpf_obj_file);
1045 			if (!ASSERT_OK(err, "run_btfgen"))
1046 				continue;
1047 
1048 			test_case->btf_src_file = btf_file;
1049 		}
1050 
1051 		if (test_case->setup) {
1052 			err = test_case->setup(test_case);
1053 			if (CHECK(err, "test_setup", "test #%d setup failed: %d\n", i, err))
1054 				continue;
1055 		}
1056 
1057 		if (test_case->btf_src_file) {
1058 			err = access(test_case->btf_src_file, R_OK);
1059 			if (!ASSERT_OK(err, "btf_src_file"))
1060 				continue;
1061 		}
1062 
1063 		open_opts.btf_custom_path = test_case->btf_src_file;
1064 		obj = bpf_object__open_file(test_case->bpf_obj_file, &open_opts);
1065 		if (!ASSERT_OK_PTR(obj, "obj_open"))
1066 			goto cleanup;
1067 
1068 		probe_name = test_case->prog_name;
1069 		tp_name = test_case->raw_tp_name; /* NULL for tp_btf */
1070 		prog = bpf_object__find_program_by_name(obj, probe_name);
1071 		if (CHECK(!prog, "find_probe",
1072 			  "prog '%s' not found\n", probe_name))
1073 			goto cleanup;
1074 
1075 		err = bpf_object__load(obj);
1076 		if (err) {
1077 			if (!test_case->fails)
1078 				ASSERT_OK(err, "obj_load");
1079 			goto cleanup;
1080 		}
1081 
1082 		data_map = bpf_object__find_map_by_name(obj, ".bss");
1083 		if (CHECK(!data_map, "find_data_map", "data map not found\n"))
1084 			goto cleanup;
1085 
1086 		mmap_data = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE,
1087 				 MAP_SHARED, bpf_map__fd(data_map), 0);
1088 		if (CHECK(mmap_data == MAP_FAILED, "mmap",
1089 			  ".bss mmap failed: %d", errno)) {
1090 			mmap_data = NULL;
1091 			goto cleanup;
1092 		}
1093 		data = mmap_data;
1094 
1095 		memset(mmap_data, 0, sizeof(*data));
1096 		if (test_case->input_len)
1097 			memcpy(data->in, test_case->input, test_case->input_len);
1098 		data->my_pid_tgid = my_pid_tgid;
1099 
1100 		link = bpf_program__attach_raw_tracepoint(prog, tp_name);
1101 		if (!ASSERT_OK_PTR(link, "attach_raw_tp"))
1102 			goto cleanup;
1103 
1104 		/* trigger test run */
1105 		if (test_case->trigger) {
1106 			if (!ASSERT_OK(test_case->trigger(test_case), "test_trigger"))
1107 				goto cleanup;
1108 		} else {
1109 			usleep(1);
1110 		}
1111 
1112 		if (data->skip) {
1113 			test__skip();
1114 			goto cleanup;
1115 		}
1116 
1117 		if (!ASSERT_FALSE(test_case->fails, "obj_load_should_fail"))
1118 			goto cleanup;
1119 
1120 		equal = memcmp(data->out, test_case->output,
1121 			       test_case->output_len) == 0;
1122 		if (CHECK(!equal, "check_result",
1123 			  "input/output data don't match\n")) {
1124 			int j;
1125 
1126 			for (j = 0; j < test_case->input_len; j++) {
1127 				printf("input byte #%d: 0x%02hhx\n",
1128 				       j, test_case->input[j]);
1129 			}
1130 			for (j = 0; j < test_case->output_len; j++) {
1131 				printf("output byte #%d: EXP 0x%02hhx GOT 0x%02hhx\n",
1132 				       j, test_case->output[j], data->out[j]);
1133 			}
1134 			goto cleanup;
1135 		}
1136 
1137 cleanup:
1138 		if (mmap_data) {
1139 			CHECK_FAIL(munmap(mmap_data, mmap_sz));
1140 			mmap_data = NULL;
1141 		}
1142 		if (use_btfgen)
1143 			remove(test_case->btf_src_file);
1144 		bpf_link__destroy(link);
1145 		link = NULL;
1146 		bpf_object__close(obj);
1147 	}
1148 }
1149 
1150 void test_core_reloc(void)
1151 {
1152 	run_core_reloc_tests(false);
1153 }
1154 
1155 void test_core_reloc_btfgen(void)
1156 {
1157 	run_core_reloc_tests(true);
1158 }
1159