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