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