File Index
Files and directories
Sign in
FILE

core_reloc.c

File preview with syntax highlighting.

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