0001
0002 #include <test_progs.h>
0003 #include "progs/core_reloc_types.h"
0004 #include "bpf_testmod/bpf_testmod.h"
0005 #include <linux/limits.h>
0006 #include <sys/mman.h>
0007 #include <sys/syscall.h>
0008 #include <bpf/btf.h>
0009
0010 static int duration = 0;
0011
0012 #define STRUCT_TO_CHAR_PTR(struct_name) (const char *)&(struct struct_name)
0013
0014 #define MODULES_CASE(name, pg_name, tp_name) { \
0015 .case_name = name, \
0016 .bpf_obj_file = "test_core_reloc_module.o", \
0017 .btf_src_file = NULL, \
0018 .input = "", \
0019 .input_len = 0, \
0020 .output = STRUCT_TO_CHAR_PTR(core_reloc_module_output) { \
0021 .read_ctx_sz = sizeof(struct bpf_testmod_test_read_ctx),\
0022 .read_ctx_exists = true, \
0023 .buf_exists = true, \
0024 .len_exists = true, \
0025 .off_exists = true, \
0026 .len = 123, \
0027 .off = 0, \
0028 .comm = "test_progs", \
0029 .comm_len = sizeof("test_progs"), \
0030 }, \
0031 .output_len = sizeof(struct core_reloc_module_output), \
0032 .prog_name = pg_name, \
0033 .raw_tp_name = tp_name, \
0034 .trigger = __trigger_module_test_read, \
0035 .needs_testmod = true, \
0036 }
0037
0038 #define FLAVORS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
0039 .a = 42, \
0040 .b = 0xc001, \
0041 .c = 0xbeef, \
0042 }
0043
0044 #define FLAVORS_CASE_COMMON(name) \
0045 .case_name = #name, \
0046 .bpf_obj_file = "test_core_reloc_flavors.o", \
0047 .btf_src_file = "btf__core_reloc_" #name ".o", \
0048 .raw_tp_name = "sys_enter", \
0049 .prog_name = "test_core_flavors" \
0050
0051 #define FLAVORS_CASE(name) { \
0052 FLAVORS_CASE_COMMON(name), \
0053 .input = FLAVORS_DATA(core_reloc_##name), \
0054 .input_len = sizeof(struct core_reloc_##name), \
0055 .output = FLAVORS_DATA(core_reloc_flavors), \
0056 .output_len = sizeof(struct core_reloc_flavors), \
0057 }
0058
0059 #define FLAVORS_ERR_CASE(name) { \
0060 FLAVORS_CASE_COMMON(name), \
0061 .fails = true, \
0062 }
0063
0064 #define NESTING_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
0065 .a = { .a = { .a = 42 } }, \
0066 .b = { .b = { .b = 0xc001 } }, \
0067 }
0068
0069 #define NESTING_CASE_COMMON(name) \
0070 .case_name = #name, \
0071 .bpf_obj_file = "test_core_reloc_nesting.o", \
0072 .btf_src_file = "btf__core_reloc_" #name ".o", \
0073 .raw_tp_name = "sys_enter", \
0074 .prog_name = "test_core_nesting" \
0075
0076 #define NESTING_CASE(name) { \
0077 NESTING_CASE_COMMON(name), \
0078 .input = NESTING_DATA(core_reloc_##name), \
0079 .input_len = sizeof(struct core_reloc_##name), \
0080 .output = NESTING_DATA(core_reloc_nesting), \
0081 .output_len = sizeof(struct core_reloc_nesting) \
0082 }
0083
0084 #define NESTING_ERR_CASE(name) { \
0085 NESTING_CASE_COMMON(name), \
0086 .fails = true, \
0087 .run_btfgen_fails = true, \
0088 }
0089
0090 #define ARRAYS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
0091 .a = { [2] = 1 }, \
0092 .b = { [1] = { [2] = { [3] = 2 } } }, \
0093 .c = { [1] = { .c = 3 } }, \
0094 .d = { [0] = { [0] = { .d = 4 } } }, \
0095 }
0096
0097 #define ARRAYS_CASE_COMMON(name) \
0098 .case_name = #name, \
0099 .bpf_obj_file = "test_core_reloc_arrays.o", \
0100 .btf_src_file = "btf__core_reloc_" #name ".o", \
0101 .raw_tp_name = "sys_enter", \
0102 .prog_name = "test_core_arrays" \
0103
0104 #define ARRAYS_CASE(name) { \
0105 ARRAYS_CASE_COMMON(name), \
0106 .input = ARRAYS_DATA(core_reloc_##name), \
0107 .input_len = sizeof(struct core_reloc_##name), \
0108 .output = STRUCT_TO_CHAR_PTR(core_reloc_arrays_output) { \
0109 .a2 = 1, \
0110 .b123 = 2, \
0111 .c1c = 3, \
0112 .d00d = 4, \
0113 .f10c = 0, \
0114 }, \
0115 .output_len = sizeof(struct core_reloc_arrays_output) \
0116 }
0117
0118 #define ARRAYS_ERR_CASE(name) { \
0119 ARRAYS_CASE_COMMON(name), \
0120 .fails = true, \
0121 }
0122
0123 #define PRIMITIVES_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
0124 .a = 1, \
0125 .b = 2, \
0126 .c = 3, \
0127 .d = (void *)4, \
0128 .f = (void *)5, \
0129 }
0130
0131 #define PRIMITIVES_CASE_COMMON(name) \
0132 .case_name = #name, \
0133 .bpf_obj_file = "test_core_reloc_primitives.o", \
0134 .btf_src_file = "btf__core_reloc_" #name ".o", \
0135 .raw_tp_name = "sys_enter", \
0136 .prog_name = "test_core_primitives" \
0137
0138 #define PRIMITIVES_CASE(name) { \
0139 PRIMITIVES_CASE_COMMON(name), \
0140 .input = PRIMITIVES_DATA(core_reloc_##name), \
0141 .input_len = sizeof(struct core_reloc_##name), \
0142 .output = PRIMITIVES_DATA(core_reloc_primitives), \
0143 .output_len = sizeof(struct core_reloc_primitives), \
0144 }
0145
0146 #define PRIMITIVES_ERR_CASE(name) { \
0147 PRIMITIVES_CASE_COMMON(name), \
0148 .fails = true, \
0149 }
0150
0151 #define MODS_CASE(name) { \
0152 .case_name = #name, \
0153 .bpf_obj_file = "test_core_reloc_mods.o", \
0154 .btf_src_file = "btf__core_reloc_" #name ".o", \
0155 .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) { \
0156 .a = 1, \
0157 .b = 2, \
0158 .c = (void *)3, \
0159 .d = (void *)4, \
0160 .e = { [2] = 5 }, \
0161 .f = { [1] = 6 }, \
0162 .g = { .x = 7 }, \
0163 .h = { .y = 8 }, \
0164 }, \
0165 .input_len = sizeof(struct core_reloc_##name), \
0166 .output = STRUCT_TO_CHAR_PTR(core_reloc_mods_output) { \
0167 .a = 1, .b = 2, .c = 3, .d = 4, \
0168 .e = 5, .f = 6, .g = 7, .h = 8, \
0169 }, \
0170 .output_len = sizeof(struct core_reloc_mods_output), \
0171 .raw_tp_name = "sys_enter", \
0172 .prog_name = "test_core_mods", \
0173 }
0174
0175 #define PTR_AS_ARR_CASE(name) { \
0176 .case_name = #name, \
0177 .bpf_obj_file = "test_core_reloc_ptr_as_arr.o", \
0178 .btf_src_file = "btf__core_reloc_" #name ".o", \
0179 .input = (const char *)&(struct core_reloc_##name []){ \
0180 { .a = 1 }, \
0181 { .a = 2 }, \
0182 { .a = 3 }, \
0183 }, \
0184 .input_len = 3 * sizeof(struct core_reloc_##name), \
0185 .output = STRUCT_TO_CHAR_PTR(core_reloc_ptr_as_arr) { \
0186 .a = 3, \
0187 }, \
0188 .output_len = sizeof(struct core_reloc_ptr_as_arr), \
0189 .raw_tp_name = "sys_enter", \
0190 .prog_name = "test_core_ptr_as_arr", \
0191 }
0192
0193 #define INTS_DATA(struct_name) STRUCT_TO_CHAR_PTR(struct_name) { \
0194 .u8_field = 1, \
0195 .s8_field = 2, \
0196 .u16_field = 3, \
0197 .s16_field = 4, \
0198 .u32_field = 5, \
0199 .s32_field = 6, \
0200 .u64_field = 7, \
0201 .s64_field = 8, \
0202 }
0203
0204 #define INTS_CASE_COMMON(name) \
0205 .case_name = #name, \
0206 .bpf_obj_file = "test_core_reloc_ints.o", \
0207 .btf_src_file = "btf__core_reloc_" #name ".o", \
0208 .raw_tp_name = "sys_enter", \
0209 .prog_name = "test_core_ints"
0210
0211 #define INTS_CASE(name) { \
0212 INTS_CASE_COMMON(name), \
0213 .input = INTS_DATA(core_reloc_##name), \
0214 .input_len = sizeof(struct core_reloc_##name), \
0215 .output = INTS_DATA(core_reloc_ints), \
0216 .output_len = sizeof(struct core_reloc_ints), \
0217 }
0218
0219 #define INTS_ERR_CASE(name) { \
0220 INTS_CASE_COMMON(name), \
0221 .fails = true, \
0222 }
0223
0224 #define FIELD_EXISTS_CASE_COMMON(name) \
0225 .case_name = #name, \
0226 .bpf_obj_file = "test_core_reloc_existence.o", \
0227 .btf_src_file = "btf__core_reloc_" #name ".o", \
0228 .raw_tp_name = "sys_enter", \
0229 .prog_name = "test_core_existence"
0230
0231 #define BITFIELDS_CASE_COMMON(objfile, test_name_prefix, name) \
0232 .case_name = test_name_prefix#name, \
0233 .bpf_obj_file = objfile, \
0234 .btf_src_file = "btf__core_reloc_" #name ".o"
0235
0236 #define BITFIELDS_CASE(name, ...) { \
0237 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
0238 "probed:", name), \
0239 .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__, \
0240 .input_len = sizeof(struct core_reloc_##name), \
0241 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
0242 __VA_ARGS__, \
0243 .output_len = sizeof(struct core_reloc_bitfields_output), \
0244 .raw_tp_name = "sys_enter", \
0245 .prog_name = "test_core_bitfields", \
0246 }, { \
0247 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
0248 "direct:", name), \
0249 .input = STRUCT_TO_CHAR_PTR(core_reloc_##name) __VA_ARGS__, \
0250 .input_len = sizeof(struct core_reloc_##name), \
0251 .output = STRUCT_TO_CHAR_PTR(core_reloc_bitfields_output) \
0252 __VA_ARGS__, \
0253 .output_len = sizeof(struct core_reloc_bitfields_output), \
0254 .prog_name = "test_core_bitfields_direct", \
0255 }
0256
0257
0258 #define BITFIELDS_ERR_CASE(name) { \
0259 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_probed.o", \
0260 "probed:", name), \
0261 .fails = true, \
0262 .run_btfgen_fails = true, \
0263 .raw_tp_name = "sys_enter", \
0264 .prog_name = "test_core_bitfields", \
0265 }, { \
0266 BITFIELDS_CASE_COMMON("test_core_reloc_bitfields_direct.o", \
0267 "direct:", name), \
0268 .fails = true, \
0269 .run_btfgen_fails = true, \
0270 .prog_name = "test_core_bitfields_direct", \
0271 }
0272
0273 #define SIZE_CASE_COMMON(name) \
0274 .case_name = #name, \
0275 .bpf_obj_file = "test_core_reloc_size.o", \
0276 .btf_src_file = "btf__core_reloc_" #name ".o", \
0277 .raw_tp_name = "sys_enter", \
0278 .prog_name = "test_core_size"
0279
0280 #define SIZE_OUTPUT_DATA(type) \
0281 STRUCT_TO_CHAR_PTR(core_reloc_size_output) { \
0282 .int_sz = sizeof(((type *)0)->int_field), \
0283 .int_off = offsetof(type, int_field), \
0284 .struct_sz = sizeof(((type *)0)->struct_field), \
0285 .struct_off = offsetof(type, struct_field), \
0286 .union_sz = sizeof(((type *)0)->union_field), \
0287 .union_off = offsetof(type, union_field), \
0288 .arr_sz = sizeof(((type *)0)->arr_field), \
0289 .arr_off = offsetof(type, arr_field), \
0290 .arr_elem_sz = sizeof(((type *)0)->arr_field[1]), \
0291 .arr_elem_off = offsetof(type, arr_field[1]), \
0292 .ptr_sz = 8, \
0293 .ptr_off = offsetof(type, ptr_field), \
0294 .enum_sz = sizeof(((type *)0)->enum_field), \
0295 .enum_off = offsetof(type, enum_field), \
0296 .float_sz = sizeof(((type *)0)->float_field), \
0297 .float_off = offsetof(type, float_field), \
0298 }
0299
0300 #define SIZE_CASE(name) { \
0301 SIZE_CASE_COMMON(name), \
0302 .input_len = 0, \
0303 .output = SIZE_OUTPUT_DATA(struct core_reloc_##name), \
0304 .output_len = sizeof(struct core_reloc_size_output), \
0305 }
0306
0307 #define SIZE_ERR_CASE(name) { \
0308 SIZE_CASE_COMMON(name), \
0309 .fails = true, \
0310 .run_btfgen_fails = true, \
0311 }
0312
0313 #define TYPE_BASED_CASE_COMMON(name) \
0314 .case_name = #name, \
0315 .bpf_obj_file = "test_core_reloc_type_based.o", \
0316 .btf_src_file = "btf__core_reloc_" #name ".o", \
0317 .raw_tp_name = "sys_enter", \
0318 .prog_name = "test_core_type_based"
0319
0320 #define TYPE_BASED_CASE(name, ...) { \
0321 TYPE_BASED_CASE_COMMON(name), \
0322 .output = STRUCT_TO_CHAR_PTR(core_reloc_type_based_output) \
0323 __VA_ARGS__, \
0324 .output_len = sizeof(struct core_reloc_type_based_output), \
0325 }
0326
0327 #define TYPE_BASED_ERR_CASE(name) { \
0328 TYPE_BASED_CASE_COMMON(name), \
0329 .fails = true, \
0330 }
0331
0332 #define TYPE_ID_CASE_COMMON(name) \
0333 .case_name = #name, \
0334 .bpf_obj_file = "test_core_reloc_type_id.o", \
0335 .btf_src_file = "btf__core_reloc_" #name ".o", \
0336 .raw_tp_name = "sys_enter", \
0337 .prog_name = "test_core_type_id"
0338
0339 #define TYPE_ID_CASE(name, setup_fn) { \
0340 TYPE_ID_CASE_COMMON(name), \
0341 .output = STRUCT_TO_CHAR_PTR(core_reloc_type_id_output) {}, \
0342 .output_len = sizeof(struct core_reloc_type_id_output), \
0343 .setup = setup_fn, \
0344 }
0345
0346 #define TYPE_ID_ERR_CASE(name) { \
0347 TYPE_ID_CASE_COMMON(name), \
0348 .fails = true, \
0349 }
0350
0351 #define ENUMVAL_CASE_COMMON(name) \
0352 .case_name = #name, \
0353 .bpf_obj_file = "test_core_reloc_enumval.o", \
0354 .btf_src_file = "btf__core_reloc_" #name ".o", \
0355 .raw_tp_name = "sys_enter", \
0356 .prog_name = "test_core_enumval"
0357
0358 #define ENUMVAL_CASE(name, ...) { \
0359 ENUMVAL_CASE_COMMON(name), \
0360 .output = STRUCT_TO_CHAR_PTR(core_reloc_enumval_output) \
0361 __VA_ARGS__, \
0362 .output_len = sizeof(struct core_reloc_enumval_output), \
0363 }
0364
0365 #define ENUMVAL_ERR_CASE(name) { \
0366 ENUMVAL_CASE_COMMON(name), \
0367 .fails = true, \
0368 }
0369
0370 #define ENUM64VAL_CASE_COMMON(name) \
0371 .case_name = #name, \
0372 .bpf_obj_file = "test_core_reloc_enum64val.o", \
0373 .btf_src_file = "btf__core_reloc_" #name ".o", \
0374 .raw_tp_name = "sys_enter", \
0375 .prog_name = "test_core_enum64val"
0376
0377 #define ENUM64VAL_CASE(name, ...) { \
0378 ENUM64VAL_CASE_COMMON(name), \
0379 .output = STRUCT_TO_CHAR_PTR(core_reloc_enum64val_output) \
0380 __VA_ARGS__, \
0381 .output_len = sizeof(struct core_reloc_enum64val_output), \
0382 }
0383
0384 #define ENUM64VAL_ERR_CASE(name) { \
0385 ENUM64VAL_CASE_COMMON(name), \
0386 .fails = true, \
0387 }
0388
0389 struct core_reloc_test_case;
0390
0391 typedef int (*setup_test_fn)(struct core_reloc_test_case *test);
0392 typedef int (*trigger_test_fn)(const struct core_reloc_test_case *test);
0393
0394 struct core_reloc_test_case {
0395 const char *case_name;
0396 const char *bpf_obj_file;
0397 const char *btf_src_file;
0398 const char *input;
0399 int input_len;
0400 const char *output;
0401 int output_len;
0402 bool fails;
0403 bool run_btfgen_fails;
0404 bool needs_testmod;
0405 bool relaxed_core_relocs;
0406 const char *prog_name;
0407 const char *raw_tp_name;
0408 setup_test_fn setup;
0409 trigger_test_fn trigger;
0410 };
0411
0412 static int find_btf_type(const struct btf *btf, const char *name, __u32 kind)
0413 {
0414 int id;
0415
0416 id = btf__find_by_name_kind(btf, name, kind);
0417 if (CHECK(id <= 0, "find_type_id", "failed to find '%s', kind %d: %d\n", name, kind, id))
0418 return -1;
0419
0420 return id;
0421 }
0422
0423 static int setup_type_id_case_local(struct core_reloc_test_case *test)
0424 {
0425 struct core_reloc_type_id_output *exp = (void *)test->output;
0426 struct btf *local_btf = btf__parse(test->bpf_obj_file, NULL);
0427 struct btf *targ_btf = btf__parse(test->btf_src_file, NULL);
0428 const struct btf_type *t;
0429 const char *name;
0430 int i;
0431
0432 if (!ASSERT_OK_PTR(local_btf, "local_btf") || !ASSERT_OK_PTR(targ_btf, "targ_btf")) {
0433 btf__free(local_btf);
0434 btf__free(targ_btf);
0435 return -EINVAL;
0436 }
0437
0438 exp->local_anon_struct = -1;
0439 exp->local_anon_union = -1;
0440 exp->local_anon_enum = -1;
0441 exp->local_anon_func_proto_ptr = -1;
0442 exp->local_anon_void_ptr = -1;
0443 exp->local_anon_arr = -1;
0444
0445 for (i = 1; i < btf__type_cnt(local_btf); i++)
0446 {
0447 t = btf__type_by_id(local_btf, i);
0448
0449 if (t->name_off)
0450 continue;
0451
0452 if (btf_is_struct(t) && btf_vlen(t) &&
0453 (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
0454 strcmp(name, "marker_field") == 0) {
0455 exp->local_anon_struct = i;
0456 } else if (btf_is_union(t) && btf_vlen(t) &&
0457 (name = btf__name_by_offset(local_btf, btf_members(t)[0].name_off)) &&
0458 strcmp(name, "marker_field") == 0) {
0459 exp->local_anon_union = i;
0460 } else if (btf_is_enum(t) && btf_vlen(t) &&
0461 (name = btf__name_by_offset(local_btf, btf_enum(t)[0].name_off)) &&
0462 strcmp(name, "MARKER_ENUM_VAL") == 0) {
0463 exp->local_anon_enum = i;
0464 } else if (btf_is_ptr(t) && (t = btf__type_by_id(local_btf, t->type))) {
0465 if (btf_is_func_proto(t) && (t = btf__type_by_id(local_btf, t->type)) &&
0466 btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
0467 strcmp(name, "_Bool") == 0) {
0468
0469 exp->local_anon_func_proto_ptr = i;
0470 } else if (btf_is_void(t)) {
0471
0472 exp->local_anon_void_ptr = i;
0473 }
0474 } else if (btf_is_array(t) && (t = btf__type_by_id(local_btf, btf_array(t)->type)) &&
0475 btf_is_int(t) && (name = btf__name_by_offset(local_btf, t->name_off)) &&
0476 strcmp(name, "_Bool") == 0) {
0477
0478 exp->local_anon_arr = i;
0479 }
0480 }
0481
0482 exp->local_struct = find_btf_type(local_btf, "a_struct", BTF_KIND_STRUCT);
0483 exp->local_union = find_btf_type(local_btf, "a_union", BTF_KIND_UNION);
0484 exp->local_enum = find_btf_type(local_btf, "an_enum", BTF_KIND_ENUM);
0485 exp->local_int = find_btf_type(local_btf, "int", BTF_KIND_INT);
0486 exp->local_struct_typedef = find_btf_type(local_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
0487 exp->local_func_proto_typedef = find_btf_type(local_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
0488 exp->local_arr_typedef = find_btf_type(local_btf, "arr_typedef", BTF_KIND_TYPEDEF);
0489
0490 btf__free(local_btf);
0491 btf__free(targ_btf);
0492 return 0;
0493 }
0494
0495 static int setup_type_id_case_success(struct core_reloc_test_case *test) {
0496 struct core_reloc_type_id_output *exp = (void *)test->output;
0497 struct btf *targ_btf;
0498 int err;
0499
0500 err = setup_type_id_case_local(test);
0501 if (err)
0502 return err;
0503
0504 targ_btf = btf__parse(test->btf_src_file, NULL);
0505
0506 exp->targ_struct = find_btf_type(targ_btf, "a_struct", BTF_KIND_STRUCT);
0507 exp->targ_union = find_btf_type(targ_btf, "a_union", BTF_KIND_UNION);
0508 exp->targ_enum = find_btf_type(targ_btf, "an_enum", BTF_KIND_ENUM);
0509 exp->targ_int = find_btf_type(targ_btf, "int", BTF_KIND_INT);
0510 exp->targ_struct_typedef = find_btf_type(targ_btf, "named_struct_typedef", BTF_KIND_TYPEDEF);
0511 exp->targ_func_proto_typedef = find_btf_type(targ_btf, "func_proto_typedef", BTF_KIND_TYPEDEF);
0512 exp->targ_arr_typedef = find_btf_type(targ_btf, "arr_typedef", BTF_KIND_TYPEDEF);
0513
0514 btf__free(targ_btf);
0515 return 0;
0516 }
0517
0518 static int setup_type_id_case_failure(struct core_reloc_test_case *test)
0519 {
0520 struct core_reloc_type_id_output *exp = (void *)test->output;
0521 int err;
0522
0523 err = setup_type_id_case_local(test);
0524 if (err)
0525 return err;
0526
0527 exp->targ_struct = 0;
0528 exp->targ_union = 0;
0529 exp->targ_enum = 0;
0530 exp->targ_int = 0;
0531 exp->targ_struct_typedef = 0;
0532 exp->targ_func_proto_typedef = 0;
0533 exp->targ_arr_typedef = 0;
0534
0535 return 0;
0536 }
0537
0538 static int __trigger_module_test_read(const struct core_reloc_test_case *test)
0539 {
0540 struct core_reloc_module_output *exp = (void *)test->output;
0541
0542 trigger_module_test_read(exp->len);
0543 return 0;
0544 }
0545
0546 static const struct core_reloc_test_case test_cases[] = {
0547
0548 {
0549 .case_name = "kernel",
0550 .bpf_obj_file = "test_core_reloc_kernel.o",
0551 .btf_src_file = NULL,
0552 .input = "",
0553 .input_len = 0,
0554 .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) {
0555 .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
0556 .comm = "test_progs",
0557 .comm_len = sizeof("test_progs"),
0558 .local_task_struct_matches = true,
0559 },
0560 .output_len = sizeof(struct core_reloc_kernel_output),
0561 .raw_tp_name = "sys_enter",
0562 .prog_name = "test_core_kernel",
0563 },
0564
0565
0566 MODULES_CASE("module_probed", "test_core_module_probed", "bpf_testmod_test_read"),
0567 MODULES_CASE("module_direct", "test_core_module_direct", NULL),
0568
0569
0570
0571
0572 FLAVORS_CASE(flavors),
0573
0574 FLAVORS_ERR_CASE(flavors__err_wrong_name),
0575
0576
0577 NESTING_CASE(nesting),
0578 NESTING_CASE(nesting___anon_embed),
0579 NESTING_CASE(nesting___struct_union_mixup),
0580 NESTING_CASE(nesting___extra_nesting),
0581 NESTING_CASE(nesting___dup_compat_types),
0582
0583 NESTING_ERR_CASE(nesting___err_missing_field),
0584 NESTING_ERR_CASE(nesting___err_array_field),
0585 NESTING_ERR_CASE(nesting___err_missing_container),
0586 NESTING_ERR_CASE(nesting___err_nonstruct_container),
0587 NESTING_ERR_CASE(nesting___err_array_container),
0588 NESTING_ERR_CASE(nesting___err_dup_incompat_types),
0589 NESTING_ERR_CASE(nesting___err_partial_match_dups),
0590 NESTING_ERR_CASE(nesting___err_too_deep),
0591
0592
0593 ARRAYS_CASE(arrays),
0594 ARRAYS_CASE(arrays___diff_arr_dim),
0595 ARRAYS_CASE(arrays___diff_arr_val_sz),
0596 ARRAYS_CASE(arrays___equiv_zero_sz_arr),
0597 ARRAYS_CASE(arrays___fixed_arr),
0598
0599 ARRAYS_ERR_CASE(arrays___err_too_small),
0600 ARRAYS_ERR_CASE(arrays___err_too_shallow),
0601 ARRAYS_ERR_CASE(arrays___err_non_array),
0602 ARRAYS_ERR_CASE(arrays___err_wrong_val_type),
0603 ARRAYS_ERR_CASE(arrays___err_bad_zero_sz_arr),
0604
0605
0606 PRIMITIVES_CASE(primitives),
0607 PRIMITIVES_CASE(primitives___diff_enum_def),
0608 PRIMITIVES_CASE(primitives___diff_func_proto),
0609 PRIMITIVES_CASE(primitives___diff_ptr_type),
0610
0611 PRIMITIVES_ERR_CASE(primitives___err_non_enum),
0612 PRIMITIVES_ERR_CASE(primitives___err_non_int),
0613 PRIMITIVES_ERR_CASE(primitives___err_non_ptr),
0614
0615
0616 MODS_CASE(mods),
0617 MODS_CASE(mods___mod_swap),
0618 MODS_CASE(mods___typedefs),
0619
0620
0621 PTR_AS_ARR_CASE(ptr_as_arr),
0622 PTR_AS_ARR_CASE(ptr_as_arr___diff_sz),
0623
0624
0625 INTS_CASE(ints),
0626 INTS_CASE(ints___bool),
0627 INTS_CASE(ints___reverse_sign),
0628
0629
0630 {
0631 .case_name = "misc",
0632 .bpf_obj_file = "test_core_reloc_misc.o",
0633 .btf_src_file = "btf__core_reloc_misc.o",
0634 .input = (const char *)&(struct core_reloc_misc_extensible[]){
0635 { .a = 1 },
0636 { .a = 2 },
0637 { .a = 3 },
0638 },
0639 .input_len = 4 * sizeof(int),
0640 .output = STRUCT_TO_CHAR_PTR(core_reloc_misc_output) {
0641 .a = 1,
0642 .b = 1,
0643 .c = 0,
0644 },
0645 .output_len = sizeof(struct core_reloc_misc_output),
0646 .raw_tp_name = "sys_enter",
0647 .prog_name = "test_core_misc",
0648 },
0649
0650
0651 {
0652 FIELD_EXISTS_CASE_COMMON(existence),
0653 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence) {
0654 .a = 1,
0655 .b = 2,
0656 .c = 3,
0657 .arr = { 4 },
0658 .s = { .x = 5 },
0659 },
0660 .input_len = sizeof(struct core_reloc_existence),
0661 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
0662 .a_exists = 1,
0663 .b_exists = 1,
0664 .c_exists = 1,
0665 .arr_exists = 1,
0666 .s_exists = 1,
0667 .a_value = 1,
0668 .b_value = 2,
0669 .c_value = 3,
0670 .arr_value = 4,
0671 .s_value = 5,
0672 },
0673 .output_len = sizeof(struct core_reloc_existence_output),
0674 },
0675 {
0676 FIELD_EXISTS_CASE_COMMON(existence___minimal),
0677 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___minimal) {
0678 .a = 42,
0679 },
0680 .input_len = sizeof(struct core_reloc_existence___minimal),
0681 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
0682 .a_exists = 1,
0683 .b_exists = 0,
0684 .c_exists = 0,
0685 .arr_exists = 0,
0686 .s_exists = 0,
0687 .a_value = 42,
0688 .b_value = 0xff000002u,
0689 .c_value = 0xff000003u,
0690 .arr_value = 0xff000004u,
0691 .s_value = 0xff000005u,
0692 },
0693 .output_len = sizeof(struct core_reloc_existence_output),
0694 },
0695 {
0696 FIELD_EXISTS_CASE_COMMON(existence___wrong_field_defs),
0697 .input = STRUCT_TO_CHAR_PTR(core_reloc_existence___wrong_field_defs) {
0698 },
0699 .input_len = sizeof(struct core_reloc_existence___wrong_field_defs),
0700 .output = STRUCT_TO_CHAR_PTR(core_reloc_existence_output) {
0701 .a_exists = 0,
0702 .b_exists = 0,
0703 .c_exists = 0,
0704 .arr_exists = 0,
0705 .s_exists = 0,
0706 .a_value = 0xff000001u,
0707 .b_value = 0xff000002u,
0708 .c_value = 0xff000003u,
0709 .arr_value = 0xff000004u,
0710 .s_value = 0xff000005u,
0711 },
0712 .output_len = sizeof(struct core_reloc_existence_output),
0713 },
0714
0715
0716 BITFIELDS_CASE(bitfields, {
0717 .ub1 = 1,
0718 .ub2 = 2,
0719 .ub7 = 96,
0720 .sb4 = -7,
0721 .sb20 = -0x76543,
0722 .u32 = 0x80000000,
0723 .s32 = -0x76543210,
0724 }),
0725 BITFIELDS_CASE(bitfields___bit_sz_change, {
0726 .ub1 = 6,
0727 .ub2 = 0xABCDE,
0728 .ub7 = 1,
0729 .sb4 = -1,
0730 .sb20 = -0x17654321,
0731 .u32 = 0xBEEF,
0732 .s32 = -0x3FEDCBA987654321LL,
0733 }),
0734 BITFIELDS_CASE(bitfields___bitfield_vs_int, {
0735 .ub1 = 0xFEDCBA9876543210LL,
0736 .ub2 = 0xA6,
0737 .ub7 = -0x7EDCBA987654321LL,
0738 .sb4 = -0x6123456789ABCDELL,
0739 .sb20 = 0xD00DLL,
0740 .u32 = -0x76543,
0741 .s32 = 0x0ADEADBEEFBADB0BLL,
0742 }),
0743 BITFIELDS_CASE(bitfields___just_big_enough, {
0744 .ub1 = 0xFLL,
0745 .ub2 = 0x0812345678FEDCBALL,
0746 }),
0747 BITFIELDS_ERR_CASE(bitfields___err_too_big_bitfield),
0748
0749
0750 SIZE_CASE(size),
0751 SIZE_CASE(size___diff_sz),
0752 SIZE_CASE(size___diff_offs),
0753 SIZE_ERR_CASE(size___err_ambiguous),
0754
0755
0756 TYPE_BASED_CASE(type_based, {
0757 .struct_exists = 1,
0758 .complex_struct_exists = 1,
0759 .union_exists = 1,
0760 .enum_exists = 1,
0761 .typedef_named_struct_exists = 1,
0762 .typedef_anon_struct_exists = 1,
0763 .typedef_struct_ptr_exists = 1,
0764 .typedef_int_exists = 1,
0765 .typedef_enum_exists = 1,
0766 .typedef_void_ptr_exists = 1,
0767 .typedef_restrict_ptr_exists = 1,
0768 .typedef_func_proto_exists = 1,
0769 .typedef_arr_exists = 1,
0770
0771 .struct_matches = 1,
0772 .complex_struct_matches = 1,
0773 .union_matches = 1,
0774 .enum_matches = 1,
0775 .typedef_named_struct_matches = 1,
0776 .typedef_anon_struct_matches = 1,
0777 .typedef_struct_ptr_matches = 1,
0778 .typedef_int_matches = 1,
0779 .typedef_enum_matches = 1,
0780 .typedef_void_ptr_matches = 1,
0781 .typedef_restrict_ptr_matches = 1,
0782 .typedef_func_proto_matches = 1,
0783 .typedef_arr_matches = 1,
0784
0785 .struct_sz = sizeof(struct a_struct),
0786 .union_sz = sizeof(union a_union),
0787 .enum_sz = sizeof(enum an_enum),
0788 .typedef_named_struct_sz = sizeof(named_struct_typedef),
0789 .typedef_anon_struct_sz = sizeof(anon_struct_typedef),
0790 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef),
0791 .typedef_int_sz = sizeof(int_typedef),
0792 .typedef_enum_sz = sizeof(enum_typedef),
0793 .typedef_void_ptr_sz = sizeof(void_ptr_typedef),
0794 .typedef_func_proto_sz = sizeof(func_proto_typedef),
0795 .typedef_arr_sz = sizeof(arr_typedef),
0796 }),
0797 TYPE_BASED_CASE(type_based___all_missing, {
0798
0799 }),
0800 TYPE_BASED_CASE(type_based___diff, {
0801 .struct_exists = 1,
0802 .complex_struct_exists = 1,
0803 .union_exists = 1,
0804 .enum_exists = 1,
0805 .typedef_named_struct_exists = 1,
0806 .typedef_anon_struct_exists = 1,
0807 .typedef_struct_ptr_exists = 1,
0808 .typedef_int_exists = 1,
0809 .typedef_enum_exists = 1,
0810 .typedef_void_ptr_exists = 1,
0811 .typedef_func_proto_exists = 1,
0812 .typedef_arr_exists = 1,
0813
0814 .struct_matches = 1,
0815 .complex_struct_matches = 1,
0816 .union_matches = 1,
0817 .enum_matches = 1,
0818 .typedef_named_struct_matches = 1,
0819 .typedef_anon_struct_matches = 1,
0820 .typedef_struct_ptr_matches = 1,
0821 .typedef_int_matches = 0,
0822 .typedef_enum_matches = 1,
0823 .typedef_void_ptr_matches = 1,
0824 .typedef_func_proto_matches = 0,
0825 .typedef_arr_matches = 0,
0826
0827 .struct_sz = sizeof(struct a_struct___diff),
0828 .union_sz = sizeof(union a_union___diff),
0829 .enum_sz = sizeof(enum an_enum___diff),
0830 .typedef_named_struct_sz = sizeof(named_struct_typedef___diff),
0831 .typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff),
0832 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff),
0833 .typedef_int_sz = sizeof(int_typedef___diff),
0834 .typedef_enum_sz = sizeof(enum_typedef___diff),
0835 .typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff),
0836 .typedef_func_proto_sz = sizeof(func_proto_typedef___diff),
0837 .typedef_arr_sz = sizeof(arr_typedef___diff),
0838 }),
0839 TYPE_BASED_CASE(type_based___diff_sz, {
0840 .struct_exists = 1,
0841 .union_exists = 1,
0842 .enum_exists = 1,
0843 .typedef_named_struct_exists = 1,
0844 .typedef_anon_struct_exists = 1,
0845 .typedef_struct_ptr_exists = 1,
0846 .typedef_int_exists = 1,
0847 .typedef_enum_exists = 1,
0848 .typedef_void_ptr_exists = 1,
0849 .typedef_func_proto_exists = 1,
0850 .typedef_arr_exists = 1,
0851
0852 .struct_matches = 0,
0853 .union_matches = 0,
0854 .enum_matches = 0,
0855 .typedef_named_struct_matches = 0,
0856 .typedef_anon_struct_matches = 0,
0857 .typedef_struct_ptr_matches = 1,
0858 .typedef_int_matches = 0,
0859 .typedef_enum_matches = 0,
0860 .typedef_void_ptr_matches = 1,
0861 .typedef_func_proto_matches = 0,
0862 .typedef_arr_matches = 0,
0863
0864 .struct_sz = sizeof(struct a_struct___diff_sz),
0865 .union_sz = sizeof(union a_union___diff_sz),
0866 .enum_sz = sizeof(enum an_enum___diff_sz),
0867 .typedef_named_struct_sz = sizeof(named_struct_typedef___diff_sz),
0868 .typedef_anon_struct_sz = sizeof(anon_struct_typedef___diff_sz),
0869 .typedef_struct_ptr_sz = sizeof(struct_ptr_typedef___diff_sz),
0870 .typedef_int_sz = sizeof(int_typedef___diff_sz),
0871 .typedef_enum_sz = sizeof(enum_typedef___diff_sz),
0872 .typedef_void_ptr_sz = sizeof(void_ptr_typedef___diff_sz),
0873 .typedef_func_proto_sz = sizeof(func_proto_typedef___diff_sz),
0874 .typedef_arr_sz = sizeof(arr_typedef___diff_sz),
0875 }),
0876 TYPE_BASED_CASE(type_based___incompat, {
0877 .enum_exists = 1,
0878 .enum_matches = 1,
0879 .enum_sz = sizeof(enum an_enum),
0880 }),
0881 TYPE_BASED_CASE(type_based___fn_wrong_args, {
0882 .struct_exists = 1,
0883 .struct_matches = 1,
0884 .struct_sz = sizeof(struct a_struct),
0885 }),
0886
0887
0888 TYPE_ID_CASE(type_id, setup_type_id_case_success),
0889 TYPE_ID_CASE(type_id___missing_targets, setup_type_id_case_failure),
0890
0891
0892 ENUMVAL_CASE(enumval, {
0893 .named_val1_exists = true,
0894 .named_val2_exists = true,
0895 .named_val3_exists = true,
0896 .anon_val1_exists = true,
0897 .anon_val2_exists = true,
0898 .anon_val3_exists = true,
0899 .named_val1 = 1,
0900 .named_val2 = 2,
0901 .anon_val1 = 0x10,
0902 .anon_val2 = 0x20,
0903 }),
0904 ENUMVAL_CASE(enumval___diff, {
0905 .named_val1_exists = true,
0906 .named_val2_exists = true,
0907 .named_val3_exists = true,
0908 .anon_val1_exists = true,
0909 .anon_val2_exists = true,
0910 .anon_val3_exists = true,
0911 .named_val1 = 101,
0912 .named_val2 = 202,
0913 .anon_val1 = 0x11,
0914 .anon_val2 = 0x22,
0915 }),
0916 ENUMVAL_CASE(enumval___val3_missing, {
0917 .named_val1_exists = true,
0918 .named_val2_exists = true,
0919 .named_val3_exists = false,
0920 .anon_val1_exists = true,
0921 .anon_val2_exists = true,
0922 .anon_val3_exists = false,
0923 .named_val1 = 111,
0924 .named_val2 = 222,
0925 .anon_val1 = 0x111,
0926 .anon_val2 = 0x222,
0927 }),
0928 ENUMVAL_ERR_CASE(enumval___err_missing),
0929
0930
0931 ENUM64VAL_CASE(enum64val, {
0932 .unsigned_val1_exists = true,
0933 .unsigned_val2_exists = true,
0934 .unsigned_val3_exists = true,
0935 .signed_val1_exists = true,
0936 .signed_val2_exists = true,
0937 .signed_val3_exists = true,
0938 .unsigned_val1 = 0x1ffffffffULL,
0939 .unsigned_val2 = 0x2,
0940 .signed_val1 = 0x1ffffffffLL,
0941 .signed_val2 = -2,
0942 }),
0943 ENUM64VAL_CASE(enum64val___diff, {
0944 .unsigned_val1_exists = true,
0945 .unsigned_val2_exists = true,
0946 .unsigned_val3_exists = true,
0947 .signed_val1_exists = true,
0948 .signed_val2_exists = true,
0949 .signed_val3_exists = true,
0950 .unsigned_val1 = 0x101ffffffffULL,
0951 .unsigned_val2 = 0x202ffffffffULL,
0952 .signed_val1 = -101,
0953 .signed_val2 = -202,
0954 }),
0955 ENUM64VAL_CASE(enum64val___val3_missing, {
0956 .unsigned_val1_exists = true,
0957 .unsigned_val2_exists = true,
0958 .unsigned_val3_exists = false,
0959 .signed_val1_exists = true,
0960 .signed_val2_exists = true,
0961 .signed_val3_exists = false,
0962 .unsigned_val1 = 0x111ffffffffULL,
0963 .unsigned_val2 = 0x222,
0964 .signed_val1 = 0x111ffffffffLL,
0965 .signed_val2 = -222,
0966 }),
0967 ENUM64VAL_ERR_CASE(enum64val___err_missing),
0968 };
0969
0970 struct data {
0971 char in[256];
0972 char out[256];
0973 bool skip;
0974 uint64_t my_pid_tgid;
0975 };
0976
0977 static size_t roundup_page(size_t sz)
0978 {
0979 long page_size = sysconf(_SC_PAGE_SIZE);
0980 return (sz + page_size - 1) / page_size * page_size;
0981 }
0982
0983 static int run_btfgen(const char *src_btf, const char *dst_btf, const char *objpath)
0984 {
0985 char command[4096];
0986 int n;
0987
0988 n = snprintf(command, sizeof(command),
0989 "./bpftool gen min_core_btf %s %s %s",
0990 src_btf, dst_btf, objpath);
0991 if (n < 0 || n >= sizeof(command))
0992 return -1;
0993
0994 return system(command);
0995 }
0996
0997 static void run_core_reloc_tests(bool use_btfgen)
0998 {
0999 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
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);
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;
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
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
1147 void test_core_reloc(void)
1148 {
1149 run_core_reloc_tests(false);
1150 }
1151
1152 void test_core_reloc_btfgen(void)
1153 {
1154 run_core_reloc_tests(true);
1155 }