Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add a test for enum64 value relocations

Add a test for enum64 value relocations.
The test will be skipped if clang version is 14 or lower
since enum64 is only supported from version 15.

Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/r/20220607062718.3726307-1-yhs@fb.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Yonghong Song and committed by
Alexei Starovoitov
f4db3dd5 adc26d13

+218
+58
tools/testing/selftests/bpf/prog_tests/core_reloc.c
··· 363 363 .fails = true, \ 364 364 } 365 365 366 + #define ENUM64VAL_CASE_COMMON(name) \ 367 + .case_name = #name, \ 368 + .bpf_obj_file = "test_core_reloc_enum64val.o", \ 369 + .btf_src_file = "btf__core_reloc_" #name ".o", \ 370 + .raw_tp_name = "sys_enter", \ 371 + .prog_name = "test_core_enum64val" 372 + 373 + #define ENUM64VAL_CASE(name, ...) { \ 374 + ENUM64VAL_CASE_COMMON(name), \ 375 + .output = STRUCT_TO_CHAR_PTR(core_reloc_enum64val_output) \ 376 + __VA_ARGS__, \ 377 + .output_len = sizeof(struct core_reloc_enum64val_output), \ 378 + } 379 + 380 + #define ENUM64VAL_ERR_CASE(name) { \ 381 + ENUM64VAL_CASE_COMMON(name), \ 382 + .fails = true, \ 383 + } 384 + 366 385 struct core_reloc_test_case; 367 386 368 387 typedef int (*setup_test_fn)(struct core_reloc_test_case *test); ··· 850 831 .anon_val2 = 0x222, 851 832 }), 852 833 ENUMVAL_ERR_CASE(enumval___err_missing), 834 + 835 + /* 64bit enumerator value existence and value relocations */ 836 + ENUM64VAL_CASE(enum64val, { 837 + .unsigned_val1_exists = true, 838 + .unsigned_val2_exists = true, 839 + .unsigned_val3_exists = true, 840 + .signed_val1_exists = true, 841 + .signed_val2_exists = true, 842 + .signed_val3_exists = true, 843 + .unsigned_val1 = 0x1ffffffffULL, 844 + .unsigned_val2 = 0x2, 845 + .signed_val1 = 0x1ffffffffLL, 846 + .signed_val2 = -2, 847 + }), 848 + ENUM64VAL_CASE(enum64val___diff, { 849 + .unsigned_val1_exists = true, 850 + .unsigned_val2_exists = true, 851 + .unsigned_val3_exists = true, 852 + .signed_val1_exists = true, 853 + .signed_val2_exists = true, 854 + .signed_val3_exists = true, 855 + .unsigned_val1 = 0x101ffffffffULL, 856 + .unsigned_val2 = 0x202ffffffffULL, 857 + .signed_val1 = -101, 858 + .signed_val2 = -202, 859 + }), 860 + ENUM64VAL_CASE(enum64val___val3_missing, { 861 + .unsigned_val1_exists = true, 862 + .unsigned_val2_exists = true, 863 + .unsigned_val3_exists = false, 864 + .signed_val1_exists = true, 865 + .signed_val2_exists = true, 866 + .signed_val3_exists = false, 867 + .unsigned_val1 = 0x111ffffffffULL, 868 + .unsigned_val2 = 0x222, 869 + .signed_val1 = 0x111ffffffffLL, 870 + .signed_val2 = -222, 871 + }), 872 + ENUM64VAL_ERR_CASE(enum64val___err_missing), 853 873 }; 854 874 855 875 struct data {
+3
tools/testing/selftests/bpf/progs/btf__core_reloc_enum64val.c
··· 1 + #include "core_reloc_types.h" 2 + 3 + void f(struct core_reloc_enum64val x) {}
+3
tools/testing/selftests/bpf/progs/btf__core_reloc_enum64val___diff.c
··· 1 + #include "core_reloc_types.h" 2 + 3 + void f(struct core_reloc_enum64val___diff x) {}
+3
tools/testing/selftests/bpf/progs/btf__core_reloc_enum64val___err_missing.c
··· 1 + #include "core_reloc_types.h" 2 + 3 + void f(struct core_reloc_enum64val___err_missing x) {}
+3
tools/testing/selftests/bpf/progs/btf__core_reloc_enum64val___val3_missing.c
··· 1 + #include "core_reloc_types.h" 2 + 3 + void f(struct core_reloc_enum64val___val3_missing x) {}
+78
tools/testing/selftests/bpf/progs/core_reloc_types.h
··· 1117 1117 int anon_val2; 1118 1118 }; 1119 1119 1120 + struct core_reloc_enum64val_output { 1121 + bool unsigned_val1_exists; 1122 + bool unsigned_val2_exists; 1123 + bool unsigned_val3_exists; 1124 + bool signed_val1_exists; 1125 + bool signed_val2_exists; 1126 + bool signed_val3_exists; 1127 + 1128 + long unsigned_val1; 1129 + long unsigned_val2; 1130 + long signed_val1; 1131 + long signed_val2; 1132 + }; 1133 + 1120 1134 enum named_enum { 1121 1135 NAMED_ENUM_VAL1 = 1, 1122 1136 NAMED_ENUM_VAL2 = 2, ··· 1146 1132 struct core_reloc_enumval { 1147 1133 enum named_enum f1; 1148 1134 anon_enum f2; 1135 + }; 1136 + 1137 + enum named_unsigned_enum64 { 1138 + UNSIGNED_ENUM64_VAL1 = 0x1ffffffffULL, 1139 + UNSIGNED_ENUM64_VAL2 = 0x2, 1140 + UNSIGNED_ENUM64_VAL3 = 0x3ffffffffULL, 1141 + }; 1142 + 1143 + enum named_signed_enum64 { 1144 + SIGNED_ENUM64_VAL1 = 0x1ffffffffLL, 1145 + SIGNED_ENUM64_VAL2 = -2, 1146 + SIGNED_ENUM64_VAL3 = 0x3ffffffffLL, 1147 + }; 1148 + 1149 + struct core_reloc_enum64val { 1150 + enum named_unsigned_enum64 f1; 1151 + enum named_signed_enum64 f2; 1149 1152 }; 1150 1153 1151 1154 /* differing enumerator values */ ··· 1183 1152 anon_enum___diff f2; 1184 1153 }; 1185 1154 1155 + enum named_unsigned_enum64___diff { 1156 + UNSIGNED_ENUM64_VAL1___diff = 0x101ffffffffULL, 1157 + UNSIGNED_ENUM64_VAL2___diff = 0x202ffffffffULL, 1158 + UNSIGNED_ENUM64_VAL3___diff = 0x303ffffffffULL, 1159 + }; 1160 + 1161 + enum named_signed_enum64___diff { 1162 + SIGNED_ENUM64_VAL1___diff = -101, 1163 + SIGNED_ENUM64_VAL2___diff = -202, 1164 + SIGNED_ENUM64_VAL3___diff = -303, 1165 + }; 1166 + 1167 + struct core_reloc_enum64val___diff { 1168 + enum named_unsigned_enum64___diff f1; 1169 + enum named_signed_enum64___diff f2; 1170 + }; 1171 + 1186 1172 /* missing (optional) third enum value */ 1187 1173 enum named_enum___val3_missing { 1188 1174 NAMED_ENUM_VAL1___val3_missing = 111, ··· 1216 1168 anon_enum___val3_missing f2; 1217 1169 }; 1218 1170 1171 + enum named_unsigned_enum64___val3_missing { 1172 + UNSIGNED_ENUM64_VAL1___val3_missing = 0x111ffffffffULL, 1173 + UNSIGNED_ENUM64_VAL2___val3_missing = 0x222, 1174 + }; 1175 + 1176 + enum named_signed_enum64___val3_missing { 1177 + SIGNED_ENUM64_VAL1___val3_missing = 0x111ffffffffLL, 1178 + SIGNED_ENUM64_VAL2___val3_missing = -222, 1179 + }; 1180 + 1181 + struct core_reloc_enum64val___val3_missing { 1182 + enum named_unsigned_enum64___val3_missing f1; 1183 + enum named_signed_enum64___val3_missing f2; 1184 + }; 1185 + 1219 1186 /* missing (mandatory) second enum value, should fail */ 1220 1187 enum named_enum___err_missing { 1221 1188 NAMED_ENUM_VAL1___err_missing = 1, ··· 1245 1182 struct core_reloc_enumval___err_missing { 1246 1183 enum named_enum___err_missing f1; 1247 1184 anon_enum___err_missing f2; 1185 + }; 1186 + 1187 + enum named_unsigned_enum64___err_missing { 1188 + UNSIGNED_ENUM64_VAL1___err_missing = 0x1ffffffffULL, 1189 + UNSIGNED_ENUM64_VAL3___err_missing = 0x3ffffffffULL, 1190 + }; 1191 + 1192 + enum named_signed_enum64___err_missing { 1193 + SIGNED_ENUM64_VAL1___err_missing = 0x1ffffffffLL, 1194 + SIGNED_ENUM64_VAL3___err_missing = -3, 1195 + }; 1196 + 1197 + struct core_reloc_enum64val___err_missing { 1198 + enum named_unsigned_enum64___err_missing f1; 1199 + enum named_signed_enum64___err_missing f2; 1248 1200 };
+70
tools/testing/selftests/bpf/progs/test_core_reloc_enum64val.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <linux/bpf.h> 5 + #include <stdint.h> 6 + #include <stdbool.h> 7 + #include <bpf/bpf_helpers.h> 8 + #include <bpf/bpf_core_read.h> 9 + 10 + char _license[] SEC("license") = "GPL"; 11 + 12 + struct { 13 + char in[256]; 14 + char out[256]; 15 + bool skip; 16 + } data = {}; 17 + 18 + enum named_unsigned_enum64 { 19 + UNSIGNED_ENUM64_VAL1 = 0x1ffffffffULL, 20 + UNSIGNED_ENUM64_VAL2 = 0x2ffffffffULL, 21 + UNSIGNED_ENUM64_VAL3 = 0x3ffffffffULL, 22 + }; 23 + 24 + enum named_signed_enum64 { 25 + SIGNED_ENUM64_VAL1 = 0x1ffffffffLL, 26 + SIGNED_ENUM64_VAL2 = -2, 27 + SIGNED_ENUM64_VAL3 = 0x3ffffffffLL, 28 + }; 29 + 30 + struct core_reloc_enum64val_output { 31 + bool unsigned_val1_exists; 32 + bool unsigned_val2_exists; 33 + bool unsigned_val3_exists; 34 + bool signed_val1_exists; 35 + bool signed_val2_exists; 36 + bool signed_val3_exists; 37 + 38 + long unsigned_val1; 39 + long unsigned_val2; 40 + long signed_val1; 41 + long signed_val2; 42 + }; 43 + 44 + SEC("raw_tracepoint/sys_enter") 45 + int test_core_enum64val(void *ctx) 46 + { 47 + #if __clang_major__ >= 15 48 + struct core_reloc_enum64val_output *out = (void *)&data.out; 49 + enum named_unsigned_enum64 named_unsigned = 0; 50 + enum named_signed_enum64 named_signed = 0; 51 + 52 + out->unsigned_val1_exists = bpf_core_enum_value_exists(named_unsigned, UNSIGNED_ENUM64_VAL1); 53 + out->unsigned_val2_exists = bpf_core_enum_value_exists(enum named_unsigned_enum64, UNSIGNED_ENUM64_VAL2); 54 + out->unsigned_val3_exists = bpf_core_enum_value_exists(enum named_unsigned_enum64, UNSIGNED_ENUM64_VAL3); 55 + out->signed_val1_exists = bpf_core_enum_value_exists(named_signed, SIGNED_ENUM64_VAL1); 56 + out->signed_val2_exists = bpf_core_enum_value_exists(enum named_signed_enum64, SIGNED_ENUM64_VAL2); 57 + out->signed_val3_exists = bpf_core_enum_value_exists(enum named_signed_enum64, SIGNED_ENUM64_VAL3); 58 + 59 + out->unsigned_val1 = bpf_core_enum_value(named_unsigned, UNSIGNED_ENUM64_VAL1); 60 + out->unsigned_val2 = bpf_core_enum_value(named_unsigned, UNSIGNED_ENUM64_VAL2); 61 + out->signed_val1 = bpf_core_enum_value(named_signed, SIGNED_ENUM64_VAL1); 62 + out->signed_val2 = bpf_core_enum_value(named_signed, SIGNED_ENUM64_VAL2); 63 + /* NAMED_ENUM64_VAL3 value is optional */ 64 + 65 + #else 66 + data.skip = true; 67 + #endif 68 + 69 + return 0; 70 + }