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

bpf: btf: Add BTF tests

This patch tests the BTF loading, map_create with BTF
and the changes in libbpf.

-r: Raw tests that test raw crafted BTF data
-f: Test LLVM compiled bpf prog with BTF data
-g: Test BPF_OBJ_GET_INFO_BY_FD for btf_fd
-p: Test pretty print

The tools/testing/selftests/bpf/Makefile will probe
for BTF support in llc and pahole before generating
debug info (-g) and convert them to BTF. You can supply
the BTF supported binary through the following make variables:
LLC, BTF_PAHOLE and LLVM_OBJCOPY.

LLC: The lastest llc with -mattr=dwarfris support for the bpf target.
It is only in the master of the llvm repo for now.
BTF_PAHOLE: The modified pahole with BTF support:
https://github.com/iamkafai/pahole/tree/btf
To add a BTF section: "pahole -J bpf_prog.o"
LLVM_OBJCOPY: Any llvm-objcopy should do

Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Acked-by: Alexei Starovoitov <ast@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>

authored by

Martin KaFai Lau and committed by
Daniel Borkmann
c0fa1b6c 8a138aed

+1783 -3
+23 -3
tools/testing/selftests/bpf/Makefile
··· 24 24 # Order correspond to 'make run_tests' order 25 25 TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \ 26 26 test_align test_verifier_log test_dev_cgroup test_tcpbpf_user \ 27 - test_sock test_sock_addr 27 + test_sock test_sock_addr test_btf 28 28 29 29 TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ 30 30 test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ 31 31 sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o \ 32 32 test_l4lb_noinline.o test_xdp_noinline.o test_stacktrace_map.o \ 33 33 sample_map_ret0.o test_tcpbpf_kern.o test_stacktrace_build_id.o \ 34 - sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o 34 + sockmap_tcp_msg_prog.o connect4_prog.o connect6_prog.o test_adjust_tail.o \ 35 + test_btf_haskv.o test_btf_nokv.o 35 36 36 37 # Order correspond to 'make run_tests' order 37 38 TEST_PROGS := test_kmod.sh \ ··· 67 66 68 67 CLANG ?= clang 69 68 LLC ?= llc 69 + LLVM_OBJCOPY ?= llvm-objcopy 70 + BTF_PAHOLE ?= pahole 70 71 71 72 PROBE := $(shell $(LLC) -march=bpf -mcpu=probe -filetype=null /dev/null 2>&1) 72 73 ··· 86 83 $(OUTPUT)/test_l4lb_noinline.o: CLANG_FLAGS += -fno-inline 87 84 $(OUTPUT)/test_xdp_noinline.o: CLANG_FLAGS += -fno-inline 88 85 86 + BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help |& grep dwarfris) 87 + BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help |& grep BTF) 88 + BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --version |& grep LLVM) 89 + 90 + ifneq ($(BTF_LLC_PROBE),) 91 + ifneq ($(BTF_PAHOLE_PROBE),) 92 + ifneq ($(BTF_OBJCOPY_PROBE),) 93 + CLANG_FLAGS += -g 94 + LLC_FLAGS += -mattr=dwarfris 95 + DWARF2BTF = y 96 + endif 97 + endif 98 + endif 99 + 89 100 $(OUTPUT)/%.o: %.c 90 101 $(CLANG) $(CLANG_FLAGS) \ 91 102 -O2 -target bpf -emit-llvm -c $< -o - | \ 92 - $(LLC) -march=bpf -mcpu=$(CPU) -filetype=obj -o $@ 103 + $(LLC) -march=bpf -mcpu=$(CPU) $(LLC_FLAGS) -filetype=obj -o $@ 104 + ifeq ($(DWARF2BTF),y) 105 + $(BTF_PAHOLE) -J $@ 106 + endif 93 107 94 108 EXTRA_CLEAN := $(TEST_CUSTOM_PROGS)
+1669
tools/testing/selftests/bpf/test_btf.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018 Facebook */ 3 + 4 + #include <linux/bpf.h> 5 + #include <linux/btf.h> 6 + #include <linux/err.h> 7 + #include <bpf/bpf.h> 8 + #include <sys/resource.h> 9 + #include <libelf.h> 10 + #include <gelf.h> 11 + #include <string.h> 12 + #include <stdlib.h> 13 + #include <stdio.h> 14 + #include <stdarg.h> 15 + #include <unistd.h> 16 + #include <fcntl.h> 17 + #include <errno.h> 18 + #include <bpf/libbpf.h> 19 + #include <bpf/btf.h> 20 + 21 + #include "bpf_rlimit.h" 22 + 23 + #define min(a, b) ((a) < (b) ? (a) : (b)) 24 + #define __printf(a, b) __attribute__((format(printf, a, b))) 25 + 26 + __printf(1, 2) 27 + static int __base_pr(const char *format, ...) 28 + { 29 + va_list args; 30 + int err; 31 + 32 + va_start(args, format); 33 + err = vfprintf(stderr, format, args); 34 + va_end(args); 35 + return err; 36 + } 37 + 38 + #define BTF_INFO_ENC(kind, root, vlen) \ 39 + ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN)) 40 + 41 + #define BTF_TYPE_ENC(name, info, size_or_type) \ 42 + (name), (info), (size_or_type) 43 + 44 + #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \ 45 + ((encoding) << 24 | (bits_offset) << 16 | (nr_bits)) 46 + #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \ 47 + BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \ 48 + BTF_INT_ENC(encoding, bits_offset, bits) 49 + 50 + #define BTF_ARRAY_ENC(type, index_type, nr_elems) \ 51 + (type), (index_type), (nr_elems) 52 + #define BTF_TYPE_ARRAY_ENC(type, index_type, nr_elems) \ 53 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 0), \ 54 + BTF_ARRAY_ENC(type, index_type, nr_elems) 55 + 56 + #define BTF_MEMBER_ENC(name, type, bits_offset) \ 57 + (name), (type), (bits_offset) 58 + #define BTF_ENUM_ENC(name, val) (name), (val) 59 + 60 + #define BTF_TYPEDEF_ENC(name, type) \ 61 + BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), type) 62 + 63 + #define BTF_PTR_ENC(name, type) \ 64 + BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), type) 65 + 66 + #define BTF_END_RAW 0xdeadbeef 67 + #define NAME_TBD 0xdeadb33f 68 + 69 + #define MAX_NR_RAW_TYPES 1024 70 + #define BTF_LOG_BUF_SIZE 65535 71 + 72 + #ifndef ARRAY_SIZE 73 + # define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 74 + #endif 75 + 76 + static struct args { 77 + unsigned int raw_test_num; 78 + unsigned int file_test_num; 79 + unsigned int get_info_test_num; 80 + bool raw_test; 81 + bool file_test; 82 + bool get_info_test; 83 + bool pprint_test; 84 + bool always_log; 85 + } args; 86 + 87 + static char btf_log_buf[BTF_LOG_BUF_SIZE]; 88 + 89 + static struct btf_header hdr_tmpl = { 90 + .magic = BTF_MAGIC, 91 + .version = BTF_VERSION, 92 + }; 93 + 94 + struct btf_raw_test { 95 + const char *descr; 96 + const char *str_sec; 97 + const char *map_name; 98 + __u32 raw_types[MAX_NR_RAW_TYPES]; 99 + __u32 str_sec_size; 100 + enum bpf_map_type map_type; 101 + __u32 key_size; 102 + __u32 value_size; 103 + __u32 key_id; 104 + __u32 value_id; 105 + __u32 max_entries; 106 + bool btf_load_err; 107 + bool map_create_err; 108 + int type_off_delta; 109 + int str_off_delta; 110 + int str_len_delta; 111 + }; 112 + 113 + static struct btf_raw_test raw_tests[] = { 114 + /* enum E { 115 + * E0, 116 + * E1, 117 + * }; 118 + * 119 + * struct A { 120 + * int m; 121 + * unsigned long long n; 122 + * char o; 123 + * [3 bytes hole] 124 + * int p[8]; 125 + * int q[4][8]; 126 + * enum E r; 127 + * }; 128 + */ 129 + { 130 + .descr = "struct test #1", 131 + .raw_types = { 132 + /* int */ 133 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 134 + /* unsigned long long */ 135 + BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */ 136 + /* char */ 137 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */ 138 + /* int[8] */ 139 + BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */ 140 + /* struct A { */ /* [5] */ 141 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 6), 180), 142 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 143 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* unsigned long long n;*/ 144 + BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */ 145 + BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */ 146 + BTF_MEMBER_ENC(NAME_TBD, 6, 384),/* int q[4][8] */ 147 + BTF_MEMBER_ENC(NAME_TBD, 7, 1408), /* enum E r */ 148 + /* } */ 149 + /* int[4][8] */ 150 + BTF_TYPE_ARRAY_ENC(4, 1, 4), /* [6] */ 151 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)), 152 + BTF_ENUM_ENC(NAME_TBD, 0), 153 + BTF_ENUM_ENC(NAME_TBD, 1), 154 + BTF_END_RAW, 155 + }, 156 + .str_sec = "\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1", 157 + .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1"), 158 + .map_type = BPF_MAP_TYPE_ARRAY, 159 + .map_name = "struct_test1_map", 160 + .key_size = sizeof(int), 161 + .value_size = 180, 162 + .key_id = 1, 163 + .value_id = 5, 164 + .max_entries = 4, 165 + }, 166 + 167 + /* typedef struct b Struct_B; 168 + * 169 + * struct A { 170 + * int m; 171 + * struct b n[4]; 172 + * const Struct_B o[4]; 173 + * }; 174 + * 175 + * struct B { 176 + * int m; 177 + * int n; 178 + * }; 179 + */ 180 + { 181 + .descr = "struct test #2", 182 + .raw_types = { 183 + /* int */ /* [1] */ 184 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 185 + /* struct b [4] */ /* [2] */ 186 + BTF_TYPE_ARRAY_ENC(4, 1, 4), 187 + 188 + /* struct A { */ /* [3] */ 189 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 3), 68), 190 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 191 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct B n[4] */ 192 + BTF_MEMBER_ENC(NAME_TBD, 8, 288),/* const Struct_B o[4];*/ 193 + /* } */ 194 + 195 + /* struct B { */ /* [4] */ 196 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 197 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 198 + BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */ 199 + /* } */ 200 + 201 + /* const int */ /* [5] */ 202 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1), 203 + /* typedef struct b Struct_B */ /* [6] */ 204 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 4), 205 + /* const Struct_B */ /* [7] */ 206 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 6), 207 + /* const Struct_B [4] */ /* [8] */ 208 + BTF_TYPE_ARRAY_ENC(7, 1, 4), 209 + BTF_END_RAW, 210 + }, 211 + .str_sec = "\0A\0m\0n\0o\0B\0m\0n\0Struct_B", 212 + .str_sec_size = sizeof("\0A\0m\0n\0o\0B\0m\0n\0Struct_B"), 213 + .map_type = BPF_MAP_TYPE_ARRAY, 214 + .map_name = "struct_test2_map", 215 + .key_size = sizeof(int), 216 + .value_size = 68, 217 + .key_id = 1, 218 + .value_id = 3, 219 + .max_entries = 4, 220 + }, 221 + 222 + /* Test member exceeds the size of struct. 223 + * 224 + * struct A { 225 + * int m; 226 + * int n; 227 + * }; 228 + */ 229 + { 230 + .descr = "size check test #1", 231 + .raw_types = { 232 + /* int */ /* [1] */ 233 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 234 + /* struct A { */ /* [2] */ 235 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 - 1), 236 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 237 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* int n; */ 238 + /* } */ 239 + BTF_END_RAW, 240 + }, 241 + .str_sec = "\0A\0m\0n", 242 + .str_sec_size = sizeof("\0A\0m\0n"), 243 + .map_type = BPF_MAP_TYPE_ARRAY, 244 + .map_name = "size_check1_map", 245 + .key_size = sizeof(int), 246 + .value_size = 1, 247 + .key_id = 1, 248 + .value_id = 2, 249 + .max_entries = 4, 250 + .btf_load_err = true, 251 + }, 252 + 253 + /* Test member exeeds the size of struct 254 + * 255 + * struct A { 256 + * int m; 257 + * int n[2]; 258 + * }; 259 + */ 260 + { 261 + .descr = "size check test #2", 262 + .raw_types = { 263 + /* int */ /* [1] */ 264 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)), 265 + /* int[2] */ /* [2] */ 266 + BTF_TYPE_ARRAY_ENC(1, 1, 2), 267 + /* struct A { */ /* [3] */ 268 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 3 - 1), 269 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 270 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* int n[2]; */ 271 + /* } */ 272 + BTF_END_RAW, 273 + }, 274 + .str_sec = "\0A\0m\0n", 275 + .str_sec_size = sizeof("\0A\0m\0n"), 276 + .map_type = BPF_MAP_TYPE_ARRAY, 277 + .map_name = "size_check2_map", 278 + .key_size = sizeof(int), 279 + .value_size = 1, 280 + .key_id = 1, 281 + .value_id = 3, 282 + .max_entries = 4, 283 + .btf_load_err = true, 284 + 285 + }, 286 + 287 + /* Test member exeeds the size of struct 288 + * 289 + * struct A { 290 + * int m; 291 + * void *n; 292 + * }; 293 + */ 294 + { 295 + .descr = "size check test #3", 296 + .raw_types = { 297 + /* int */ /* [1] */ 298 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)), 299 + /* void* */ /* [2] */ 300 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0), 301 + /* struct A { */ /* [3] */ 302 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) + sizeof(void *) - 1), 303 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 304 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* void *n; */ 305 + /* } */ 306 + BTF_END_RAW, 307 + }, 308 + .str_sec = "\0A\0m\0n", 309 + .str_sec_size = sizeof("\0A\0m\0n"), 310 + .map_type = BPF_MAP_TYPE_ARRAY, 311 + .map_name = "size_check3_map", 312 + .key_size = sizeof(int), 313 + .value_size = 1, 314 + .key_id = 1, 315 + .value_id = 3, 316 + .max_entries = 4, 317 + .btf_load_err = true, 318 + }, 319 + 320 + /* Test member exceeds the size of struct 321 + * 322 + * enum E { 323 + * E0, 324 + * E1, 325 + * }; 326 + * 327 + * struct A { 328 + * int m; 329 + * enum E n; 330 + * }; 331 + */ 332 + { 333 + .descr = "size check test #4", 334 + .raw_types = { 335 + /* int */ /* [1] */ 336 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)), 337 + /* enum E { */ /* [2] */ 338 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)), 339 + BTF_ENUM_ENC(NAME_TBD, 0), 340 + BTF_ENUM_ENC(NAME_TBD, 1), 341 + /* } */ 342 + /* struct A { */ /* [3] */ 343 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 - 1), 344 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */ 345 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* enum E n; */ 346 + /* } */ 347 + BTF_END_RAW, 348 + }, 349 + .str_sec = "\0E\0E0\0E1\0A\0m\0n", 350 + .str_sec_size = sizeof("\0E\0E0\0E1\0A\0m\0n"), 351 + .map_type = BPF_MAP_TYPE_ARRAY, 352 + .map_name = "size_check4_map", 353 + .key_size = sizeof(int), 354 + .value_size = 1, 355 + .key_id = 1, 356 + .value_id = 3, 357 + .max_entries = 4, 358 + .btf_load_err = true, 359 + }, 360 + 361 + /* typedef const void * const_void_ptr; 362 + * struct A { 363 + * const_void_ptr m; 364 + * }; 365 + */ 366 + { 367 + .descr = "void test #1", 368 + .raw_types = { 369 + /* int */ /* [1] */ 370 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 371 + /* const void */ /* [2] */ 372 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0), 373 + /* const void* */ /* [3] */ 374 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2), 375 + /* typedef const void * const_void_ptr */ 376 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3), 377 + /* struct A { */ /* [4] */ 378 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)), 379 + /* const_void_ptr m; */ 380 + BTF_MEMBER_ENC(NAME_TBD, 3, 0), 381 + /* } */ 382 + BTF_END_RAW, 383 + }, 384 + .str_sec = "\0const_void_ptr\0A\0m", 385 + .str_sec_size = sizeof("\0const_void_ptr\0A\0m"), 386 + .map_type = BPF_MAP_TYPE_ARRAY, 387 + .map_name = "void_test1_map", 388 + .key_size = sizeof(int), 389 + .value_size = sizeof(void *), 390 + .key_id = 1, 391 + .value_id = 4, 392 + .max_entries = 4, 393 + }, 394 + 395 + /* struct A { 396 + * const void m; 397 + * }; 398 + */ 399 + { 400 + .descr = "void test #2", 401 + .raw_types = { 402 + /* int */ /* [1] */ 403 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 404 + /* const void */ /* [2] */ 405 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0), 406 + /* struct A { */ /* [3] */ 407 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 8), 408 + /* const void m; */ 409 + BTF_MEMBER_ENC(NAME_TBD, 2, 0), 410 + /* } */ 411 + BTF_END_RAW, 412 + }, 413 + .str_sec = "\0A\0m", 414 + .str_sec_size = sizeof("\0A\0m"), 415 + .map_type = BPF_MAP_TYPE_ARRAY, 416 + .map_name = "void_test2_map", 417 + .key_size = sizeof(int), 418 + .value_size = sizeof(void *), 419 + .key_id = 1, 420 + .value_id = 3, 421 + .max_entries = 4, 422 + .btf_load_err = true, 423 + }, 424 + 425 + /* typedef const void * const_void_ptr; 426 + * const_void_ptr[4] 427 + */ 428 + { 429 + .descr = "void test #3", 430 + .raw_types = { 431 + /* int */ /* [1] */ 432 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 433 + /* const void */ /* [2] */ 434 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0), 435 + /* const void* */ /* [3] */ 436 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2), 437 + /* typedef const void * const_void_ptr */ 438 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3), 439 + /* const_void_ptr[4] */ /* [4] */ 440 + BTF_TYPE_ARRAY_ENC(3, 1, 4), 441 + BTF_END_RAW, 442 + }, 443 + .str_sec = "\0const_void_ptr", 444 + .str_sec_size = sizeof("\0const_void_ptr"), 445 + .map_type = BPF_MAP_TYPE_ARRAY, 446 + .map_name = "void_test3_map", 447 + .key_size = sizeof(int), 448 + .value_size = sizeof(void *) * 4, 449 + .key_id = 1, 450 + .value_id = 4, 451 + .max_entries = 4, 452 + }, 453 + 454 + /* const void[4] */ 455 + { 456 + .descr = "void test #4", 457 + .raw_types = { 458 + /* int */ /* [1] */ 459 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 460 + /* const void */ /* [2] */ 461 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0), 462 + /* const void[4] */ /* [3] */ 463 + BTF_TYPE_ARRAY_ENC(2, 1, 4), 464 + BTF_END_RAW, 465 + }, 466 + .str_sec = "\0A\0m", 467 + .str_sec_size = sizeof("\0A\0m"), 468 + .map_type = BPF_MAP_TYPE_ARRAY, 469 + .map_name = "void_test4_map", 470 + .key_size = sizeof(int), 471 + .value_size = sizeof(void *) * 4, 472 + .key_id = 1, 473 + .value_id = 3, 474 + .max_entries = 4, 475 + .btf_load_err = true, 476 + }, 477 + 478 + /* Array_A <------------------+ 479 + * elem_type == Array_B | 480 + * | | 481 + * | | 482 + * Array_B <-------- + | 483 + * elem_type == Array A --+ 484 + */ 485 + { 486 + .descr = "loop test #1", 487 + .raw_types = { 488 + /* int */ /* [1] */ 489 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 490 + /* Array_A */ /* [2] */ 491 + BTF_TYPE_ARRAY_ENC(3, 1, 8), 492 + /* Array_B */ /* [3] */ 493 + BTF_TYPE_ARRAY_ENC(2, 1, 8), 494 + BTF_END_RAW, 495 + }, 496 + .str_sec = "", 497 + .str_sec_size = sizeof(""), 498 + .map_type = BPF_MAP_TYPE_ARRAY, 499 + .map_name = "loop_test1_map", 500 + .key_size = sizeof(int), 501 + .value_size = sizeof(sizeof(int) * 8), 502 + .key_id = 1, 503 + .value_id = 2, 504 + .max_entries = 4, 505 + .btf_load_err = true, 506 + }, 507 + 508 + /* typedef is _before_ the BTF type of Array_A and Array_B 509 + * 510 + * typedef Array_B int_array; 511 + * 512 + * Array_A <------------------+ 513 + * elem_type == int_array | 514 + * | | 515 + * | | 516 + * Array_B <-------- + | 517 + * elem_type == Array_A --+ 518 + */ 519 + { 520 + .descr = "loop test #2", 521 + .raw_types = { 522 + /* int */ 523 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 524 + /* typedef Array_B int_array */ 525 + BTF_TYPEDEF_ENC(1, 4), /* [2] */ 526 + /* Array_A */ 527 + BTF_TYPE_ARRAY_ENC(2, 1, 8), /* [3] */ 528 + /* Array_B */ 529 + BTF_TYPE_ARRAY_ENC(3, 1, 8), /* [4] */ 530 + 531 + BTF_END_RAW, 532 + }, 533 + .str_sec = "\0int_array\0", 534 + .str_sec_size = sizeof("\0int_array"), 535 + .map_type = BPF_MAP_TYPE_ARRAY, 536 + .map_name = "loop_test2_map", 537 + .key_size = sizeof(int), 538 + .value_size = sizeof(sizeof(int) * 8), 539 + .key_id = 1, 540 + .value_id = 2, 541 + .max_entries = 4, 542 + .btf_load_err = true, 543 + }, 544 + 545 + /* Array_A <------------------+ 546 + * elem_type == Array_B | 547 + * | | 548 + * | | 549 + * Array_B <-------- + | 550 + * elem_type == Array_A --+ 551 + */ 552 + { 553 + .descr = "loop test #3", 554 + .raw_types = { 555 + /* int */ /* [1] */ 556 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 557 + /* Array_A */ /* [2] */ 558 + BTF_TYPE_ARRAY_ENC(3, 1, 8), 559 + /* Array_B */ /* [3] */ 560 + BTF_TYPE_ARRAY_ENC(2, 1, 8), 561 + 562 + BTF_END_RAW, 563 + }, 564 + .str_sec = "", 565 + .str_sec_size = sizeof(""), 566 + .map_type = BPF_MAP_TYPE_ARRAY, 567 + .map_name = "loop_test3_map", 568 + .key_size = sizeof(int), 569 + .value_size = sizeof(sizeof(int) * 8), 570 + .key_id = 1, 571 + .value_id = 2, 572 + .max_entries = 4, 573 + .btf_load_err = true, 574 + }, 575 + 576 + /* typedef is _between_ the BTF type of Array_A and Array_B 577 + * 578 + * typedef Array_B int_array; 579 + * 580 + * Array_A <------------------+ 581 + * elem_type == int_array | 582 + * | | 583 + * | | 584 + * Array_B <-------- + | 585 + * elem_type == Array_A --+ 586 + */ 587 + { 588 + .descr = "loop test #4", 589 + .raw_types = { 590 + /* int */ /* [1] */ 591 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 592 + /* Array_A */ /* [2] */ 593 + BTF_TYPE_ARRAY_ENC(3, 1, 8), 594 + /* typedef Array_B int_array */ /* [3] */ 595 + BTF_TYPEDEF_ENC(NAME_TBD, 4), 596 + /* Array_B */ /* [4] */ 597 + BTF_TYPE_ARRAY_ENC(2, 1, 8), 598 + BTF_END_RAW, 599 + }, 600 + .str_sec = "\0int_array\0", 601 + .str_sec_size = sizeof("\0int_array"), 602 + .map_type = BPF_MAP_TYPE_ARRAY, 603 + .map_name = "loop_test4_map", 604 + .key_size = sizeof(int), 605 + .value_size = sizeof(sizeof(int) * 8), 606 + .key_id = 1, 607 + .value_id = 2, 608 + .max_entries = 4, 609 + .btf_load_err = true, 610 + }, 611 + 612 + /* typedef struct B Struct_B 613 + * 614 + * struct A { 615 + * int x; 616 + * Struct_B y; 617 + * }; 618 + * 619 + * struct B { 620 + * int x; 621 + * struct A y; 622 + * }; 623 + */ 624 + { 625 + .descr = "loop test #5", 626 + .raw_types = { 627 + /* int */ 628 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 629 + /* struct A */ /* [2] */ 630 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 631 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x; */ 632 + BTF_MEMBER_ENC(NAME_TBD, 3, 32),/* Struct_B y; */ 633 + /* typedef struct B Struct_B */ 634 + BTF_TYPEDEF_ENC(NAME_TBD, 4), /* [3] */ 635 + /* struct B */ /* [4] */ 636 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 637 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x; */ 638 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A y; */ 639 + BTF_END_RAW, 640 + }, 641 + .str_sec = "\0A\0x\0y\0Struct_B\0B\0x\0y", 642 + .str_sec_size = sizeof("\0A\0x\0y\0Struct_B\0B\0x\0y"), 643 + .map_type = BPF_MAP_TYPE_ARRAY, 644 + .map_name = "loop_test5_map", 645 + .key_size = sizeof(int), 646 + .value_size = 8, 647 + .key_id = 1, 648 + .value_id = 2, 649 + .max_entries = 4, 650 + .btf_load_err = true, 651 + }, 652 + 653 + /* struct A { 654 + * int x; 655 + * struct A array_a[4]; 656 + * }; 657 + */ 658 + { 659 + .descr = "loop test #6", 660 + .raw_types = { 661 + /* int */ 662 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */ 663 + BTF_TYPE_ARRAY_ENC(3, 1, 4), /* [2] */ 664 + /* struct A */ /* [3] */ 665 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8), 666 + BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x; */ 667 + BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A array_a[4]; */ 668 + BTF_END_RAW, 669 + }, 670 + .str_sec = "\0A\0x\0y", 671 + .str_sec_size = sizeof("\0A\0x\0y"), 672 + .map_type = BPF_MAP_TYPE_ARRAY, 673 + .map_name = "loop_test6_map", 674 + .key_size = sizeof(int), 675 + .value_size = 8, 676 + .key_id = 1, 677 + .value_id = 2, 678 + .max_entries = 4, 679 + .btf_load_err = true, 680 + }, 681 + 682 + { 683 + .descr = "loop test #7", 684 + .raw_types = { 685 + /* int */ /* [1] */ 686 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 687 + /* struct A { */ /* [2] */ 688 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)), 689 + /* const void *m; */ 690 + BTF_MEMBER_ENC(NAME_TBD, 3, 0), 691 + /* CONST type_id=3 */ /* [3] */ 692 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4), 693 + /* PTR type_id=2 */ /* [4] */ 694 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3), 695 + BTF_END_RAW, 696 + }, 697 + .str_sec = "\0A\0m", 698 + .str_sec_size = sizeof("\0A\0m"), 699 + .map_type = BPF_MAP_TYPE_ARRAY, 700 + .map_name = "loop_test7_map", 701 + .key_size = sizeof(int), 702 + .value_size = sizeof(void *), 703 + .key_id = 1, 704 + .value_id = 2, 705 + .max_entries = 4, 706 + .btf_load_err = true, 707 + }, 708 + 709 + { 710 + .descr = "loop test #8", 711 + .raw_types = { 712 + /* int */ /* [1] */ 713 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 714 + /* struct A { */ /* [2] */ 715 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)), 716 + /* const void *m; */ 717 + BTF_MEMBER_ENC(NAME_TBD, 4, 0), 718 + /* struct B { */ /* [3] */ 719 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)), 720 + /* const void *n; */ 721 + BTF_MEMBER_ENC(NAME_TBD, 6, 0), 722 + /* CONST type_id=5 */ /* [4] */ 723 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 5), 724 + /* PTR type_id=6 */ /* [5] */ 725 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6), 726 + /* CONST type_id=7 */ /* [6] */ 727 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 7), 728 + /* PTR type_id=4 */ /* [7] */ 729 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 4), 730 + BTF_END_RAW, 731 + }, 732 + .str_sec = "\0A\0m\0B\0n", 733 + .str_sec_size = sizeof("\0A\0m\0B\0n"), 734 + .map_type = BPF_MAP_TYPE_ARRAY, 735 + .map_name = "loop_test8_map", 736 + .key_size = sizeof(int), 737 + .value_size = sizeof(void *), 738 + .key_id = 1, 739 + .value_id = 2, 740 + .max_entries = 4, 741 + .btf_load_err = true, 742 + }, 743 + 744 + { 745 + .descr = "type_off == str_off", 746 + .raw_types = { 747 + /* int */ /* [1] */ 748 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 749 + BTF_END_RAW, 750 + }, 751 + .str_sec = "\0int", 752 + .str_sec_size = sizeof("\0int"), 753 + .map_type = BPF_MAP_TYPE_ARRAY, 754 + .map_name = "hdr_test_map", 755 + .key_size = sizeof(int), 756 + .value_size = sizeof(int), 757 + .key_id = 1, 758 + .value_id = 1, 759 + .max_entries = 4, 760 + .btf_load_err = true, 761 + .type_off_delta = sizeof(struct btf_type) + sizeof(int) + sizeof("\0int"), 762 + }, 763 + 764 + { 765 + .descr = "Unaligned type_off", 766 + .raw_types = { 767 + /* int */ /* [1] */ 768 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 769 + BTF_END_RAW, 770 + }, 771 + .str_sec = "\0int", 772 + .str_sec_size = sizeof("\0int"), 773 + .map_type = BPF_MAP_TYPE_ARRAY, 774 + .map_name = "hdr_test_map", 775 + .key_size = sizeof(int), 776 + .value_size = sizeof(int), 777 + .key_id = 1, 778 + .value_id = 1, 779 + .max_entries = 4, 780 + .btf_load_err = true, 781 + .type_off_delta = 1, 782 + }, 783 + 784 + { 785 + .descr = "str_off beyonds btf size", 786 + .raw_types = { 787 + /* int */ /* [1] */ 788 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 789 + BTF_END_RAW, 790 + }, 791 + .str_sec = "\0int", 792 + .str_sec_size = sizeof("\0int"), 793 + .map_type = BPF_MAP_TYPE_ARRAY, 794 + .map_name = "hdr_test_map", 795 + .key_size = sizeof(int), 796 + .value_size = sizeof(int), 797 + .key_id = 1, 798 + .value_id = 1, 799 + .max_entries = 4, 800 + .btf_load_err = true, 801 + .str_off_delta = sizeof("\0int") + 1, 802 + }, 803 + 804 + { 805 + .descr = "str_len beyonds btf size", 806 + .raw_types = { 807 + /* int */ /* [1] */ 808 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 809 + BTF_END_RAW, 810 + }, 811 + .str_sec = "\0int", 812 + .str_sec_size = sizeof("\0int"), 813 + .map_type = BPF_MAP_TYPE_ARRAY, 814 + .map_name = "hdr_test_map", 815 + .key_size = sizeof(int), 816 + .value_size = sizeof(int), 817 + .key_id = 1, 818 + .value_id = 1, 819 + .max_entries = 4, 820 + .btf_load_err = true, 821 + .str_len_delta = 1, 822 + }, 823 + 824 + { 825 + .descr = "String section does not end with null", 826 + .raw_types = { 827 + /* int */ /* [1] */ 828 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 829 + BTF_END_RAW, 830 + }, 831 + .str_sec = "\0int", 832 + .str_sec_size = sizeof("\0int"), 833 + .map_type = BPF_MAP_TYPE_ARRAY, 834 + .map_name = "hdr_test_map", 835 + .key_size = sizeof(int), 836 + .value_size = sizeof(int), 837 + .key_id = 1, 838 + .value_id = 1, 839 + .max_entries = 4, 840 + .btf_load_err = true, 841 + .str_len_delta = -1, 842 + }, 843 + 844 + { 845 + .descr = "Empty string section", 846 + .raw_types = { 847 + /* int */ /* [1] */ 848 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 849 + BTF_END_RAW, 850 + }, 851 + .str_sec = "\0int", 852 + .str_sec_size = sizeof("\0int"), 853 + .map_type = BPF_MAP_TYPE_ARRAY, 854 + .map_name = "hdr_test_map", 855 + .key_size = sizeof(int), 856 + .value_size = sizeof(int), 857 + .key_id = 1, 858 + .value_id = 1, 859 + .max_entries = 4, 860 + .btf_load_err = true, 861 + .str_len_delta = 0 - (int)sizeof("\0int"), 862 + }, 863 + 864 + }; /* struct btf_raw_test raw_tests[] */ 865 + 866 + static const char *get_next_str(const char *start, const char *end) 867 + { 868 + return start < end - 1 ? start + 1 : NULL; 869 + } 870 + 871 + static int get_type_sec_size(const __u32 *raw_types) 872 + { 873 + int i; 874 + 875 + for (i = MAX_NR_RAW_TYPES - 1; 876 + i >= 0 && raw_types[i] != BTF_END_RAW; 877 + i--) 878 + ; 879 + 880 + return i < 0 ? i : i * sizeof(raw_types[0]); 881 + } 882 + 883 + static void *btf_raw_create(const struct btf_header *hdr, 884 + const __u32 *raw_types, 885 + const char *str, 886 + unsigned int str_sec_size, 887 + unsigned int *btf_size) 888 + { 889 + const char *next_str = str, *end_str = str + str_sec_size; 890 + unsigned int size_needed, offset; 891 + struct btf_header *ret_hdr; 892 + int i, type_sec_size; 893 + uint32_t *ret_types; 894 + void *raw_btf; 895 + 896 + type_sec_size = get_type_sec_size(raw_types); 897 + if (type_sec_size < 0) { 898 + fprintf(stderr, "Cannot get nr_raw_types\n"); 899 + return NULL; 900 + } 901 + 902 + size_needed = sizeof(*hdr) + type_sec_size + str_sec_size; 903 + raw_btf = malloc(size_needed); 904 + if (!raw_btf) { 905 + fprintf(stderr, "Cannot allocate memory for raw_btf\n"); 906 + return NULL; 907 + } 908 + 909 + /* Copy header */ 910 + memcpy(raw_btf, hdr, sizeof(*hdr)); 911 + offset = sizeof(*hdr); 912 + 913 + /* Copy type section */ 914 + ret_types = raw_btf + offset; 915 + for (i = 0; i < type_sec_size / sizeof(raw_types[0]); i++) { 916 + if (raw_types[i] == NAME_TBD) { 917 + next_str = get_next_str(next_str, end_str); 918 + if (!next_str) { 919 + fprintf(stderr, "Error in getting next_str\n"); 920 + free(raw_btf); 921 + return NULL; 922 + } 923 + ret_types[i] = next_str - str; 924 + next_str += strlen(next_str); 925 + } else { 926 + ret_types[i] = raw_types[i]; 927 + } 928 + } 929 + offset += type_sec_size; 930 + 931 + /* Copy string section */ 932 + memcpy(raw_btf + offset, str, str_sec_size); 933 + 934 + ret_hdr = (struct btf_header *)raw_btf; 935 + ret_hdr->str_off = type_sec_size; 936 + ret_hdr->str_len = str_sec_size; 937 + 938 + *btf_size = size_needed; 939 + 940 + return raw_btf; 941 + } 942 + 943 + static int do_test_raw(unsigned int test_num) 944 + { 945 + struct btf_raw_test *test = &raw_tests[test_num - 1]; 946 + struct bpf_create_map_attr create_attr = {}; 947 + int map_fd = -1, btf_fd = -1; 948 + unsigned int raw_btf_size; 949 + struct btf_header *hdr; 950 + void *raw_btf; 951 + int err; 952 + 953 + fprintf(stderr, "BTF raw test[%u] (%s): ", test_num, test->descr); 954 + raw_btf = btf_raw_create(&hdr_tmpl, 955 + test->raw_types, 956 + test->str_sec, 957 + test->str_sec_size, 958 + &raw_btf_size); 959 + 960 + if (!raw_btf) 961 + return -1; 962 + 963 + hdr = raw_btf; 964 + 965 + hdr->type_off = (int)hdr->type_off + test->type_off_delta; 966 + hdr->str_off = (int)hdr->str_off + test->str_off_delta; 967 + hdr->str_len = (int)hdr->str_len + test->str_len_delta; 968 + 969 + *btf_log_buf = '\0'; 970 + btf_fd = bpf_load_btf(raw_btf, raw_btf_size, 971 + btf_log_buf, BTF_LOG_BUF_SIZE, 972 + args.always_log); 973 + free(raw_btf); 974 + 975 + err = ((btf_fd == -1) != test->btf_load_err); 976 + if (err) 977 + fprintf(stderr, "btf_load_err:%d btf_fd:%d\n", 978 + test->btf_load_err, btf_fd); 979 + 980 + if (err || btf_fd == -1) 981 + goto done; 982 + 983 + create_attr.name = test->map_name; 984 + create_attr.map_type = test->map_type; 985 + create_attr.key_size = test->key_size; 986 + create_attr.value_size = test->value_size; 987 + create_attr.max_entries = test->max_entries; 988 + create_attr.btf_fd = btf_fd; 989 + create_attr.btf_key_id = test->key_id; 990 + create_attr.btf_value_id = test->value_id; 991 + 992 + map_fd = bpf_create_map_xattr(&create_attr); 993 + 994 + err = ((map_fd == -1) != test->map_create_err); 995 + if (err) 996 + fprintf(stderr, "map_create_err:%d map_fd:%d\n", 997 + test->map_create_err, map_fd); 998 + 999 + done: 1000 + if (!err) 1001 + fprintf(stderr, "OK\n"); 1002 + 1003 + if (*btf_log_buf && (err || args.always_log)) 1004 + fprintf(stderr, "%s\n", btf_log_buf); 1005 + 1006 + if (btf_fd != -1) 1007 + close(btf_fd); 1008 + if (map_fd != -1) 1009 + close(map_fd); 1010 + 1011 + return err; 1012 + } 1013 + 1014 + static int test_raw(void) 1015 + { 1016 + unsigned int i; 1017 + int err = 0; 1018 + 1019 + if (args.raw_test_num) 1020 + return do_test_raw(args.raw_test_num); 1021 + 1022 + for (i = 1; i <= ARRAY_SIZE(raw_tests); i++) 1023 + err |= do_test_raw(i); 1024 + 1025 + return err; 1026 + } 1027 + 1028 + struct btf_get_info_test { 1029 + const char *descr; 1030 + const char *str_sec; 1031 + __u32 raw_types[MAX_NR_RAW_TYPES]; 1032 + __u32 str_sec_size; 1033 + int info_size_delta; 1034 + }; 1035 + 1036 + const struct btf_get_info_test get_info_tests[] = { 1037 + { 1038 + .descr = "== raw_btf_size+1", 1039 + .raw_types = { 1040 + /* int */ /* [1] */ 1041 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 1042 + BTF_END_RAW, 1043 + }, 1044 + .str_sec = "", 1045 + .str_sec_size = sizeof(""), 1046 + .info_size_delta = 1, 1047 + }, 1048 + { 1049 + .descr = "== raw_btf_size-3", 1050 + .raw_types = { 1051 + /* int */ /* [1] */ 1052 + BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), 1053 + BTF_END_RAW, 1054 + }, 1055 + .str_sec = "", 1056 + .str_sec_size = sizeof(""), 1057 + .info_size_delta = -3, 1058 + }, 1059 + }; 1060 + 1061 + static int do_test_get_info(unsigned int test_num) 1062 + { 1063 + const struct btf_get_info_test *test = &get_info_tests[test_num - 1]; 1064 + unsigned int raw_btf_size, user_btf_size, expected_nbytes; 1065 + uint8_t *raw_btf = NULL, *user_btf = NULL; 1066 + int btf_fd = -1, err; 1067 + 1068 + fprintf(stderr, "BTF GET_INFO_BY_ID test[%u] (%s): ", 1069 + test_num, test->descr); 1070 + 1071 + raw_btf = btf_raw_create(&hdr_tmpl, 1072 + test->raw_types, 1073 + test->str_sec, 1074 + test->str_sec_size, 1075 + &raw_btf_size); 1076 + 1077 + if (!raw_btf) 1078 + return -1; 1079 + 1080 + *btf_log_buf = '\0'; 1081 + 1082 + user_btf = malloc(raw_btf_size); 1083 + if (!user_btf) { 1084 + fprintf(stderr, "Cannot allocate memory for user_btf\n"); 1085 + err = -1; 1086 + goto done; 1087 + } 1088 + 1089 + btf_fd = bpf_load_btf(raw_btf, raw_btf_size, 1090 + btf_log_buf, BTF_LOG_BUF_SIZE, 1091 + args.always_log); 1092 + if (btf_fd == -1) { 1093 + fprintf(stderr, "bpf_load_btf:%s(%d)\n", 1094 + strerror(errno), errno); 1095 + err = -1; 1096 + goto done; 1097 + } 1098 + 1099 + user_btf_size = (int)raw_btf_size + test->info_size_delta; 1100 + expected_nbytes = min(raw_btf_size, user_btf_size); 1101 + if (raw_btf_size > expected_nbytes) 1102 + memset(user_btf + expected_nbytes, 0xff, 1103 + raw_btf_size - expected_nbytes); 1104 + 1105 + err = bpf_obj_get_info_by_fd(btf_fd, user_btf, &user_btf_size); 1106 + if (err || user_btf_size != raw_btf_size || 1107 + memcmp(raw_btf, user_btf, expected_nbytes)) { 1108 + fprintf(stderr, 1109 + "err:%d(errno:%d) raw_btf_size:%u user_btf_size:%u expected_nbytes:%u memcmp:%d\n", 1110 + err, errno, 1111 + raw_btf_size, user_btf_size, expected_nbytes, 1112 + memcmp(raw_btf, user_btf, expected_nbytes)); 1113 + err = -1; 1114 + goto done; 1115 + } 1116 + 1117 + while (expected_nbytes < raw_btf_size) { 1118 + fprintf(stderr, "%u...", expected_nbytes); 1119 + if (user_btf[expected_nbytes++] != 0xff) { 1120 + fprintf(stderr, "!= 0xff\n"); 1121 + err = -1; 1122 + goto done; 1123 + } 1124 + } 1125 + 1126 + fprintf(stderr, "OK\n"); 1127 + 1128 + done: 1129 + if (*btf_log_buf && (err || args.always_log)) 1130 + fprintf(stderr, "%s\n", btf_log_buf); 1131 + 1132 + free(raw_btf); 1133 + free(user_btf); 1134 + 1135 + if (btf_fd != -1) 1136 + close(btf_fd); 1137 + 1138 + return err; 1139 + } 1140 + 1141 + static int test_get_info(void) 1142 + { 1143 + unsigned int i; 1144 + int err = 0; 1145 + 1146 + if (args.get_info_test_num) 1147 + return do_test_get_info(args.get_info_test_num); 1148 + 1149 + for (i = 1; i <= ARRAY_SIZE(get_info_tests); i++) 1150 + err |= do_test_get_info(i); 1151 + 1152 + return err; 1153 + } 1154 + 1155 + struct btf_file_test { 1156 + const char *file; 1157 + bool btf_kv_notfound; 1158 + }; 1159 + 1160 + static struct btf_file_test file_tests[] = { 1161 + { 1162 + .file = "test_btf_haskv.o", 1163 + }, 1164 + { 1165 + .file = "test_btf_nokv.o", 1166 + .btf_kv_notfound = true, 1167 + }, 1168 + }; 1169 + 1170 + static int file_has_btf_elf(const char *fn) 1171 + { 1172 + Elf_Scn *scn = NULL; 1173 + GElf_Ehdr ehdr; 1174 + int elf_fd; 1175 + Elf *elf; 1176 + int ret; 1177 + 1178 + if (elf_version(EV_CURRENT) == EV_NONE) { 1179 + fprintf(stderr, "Failed to init libelf\n"); 1180 + return -1; 1181 + } 1182 + 1183 + elf_fd = open(fn, O_RDONLY); 1184 + if (elf_fd == -1) { 1185 + fprintf(stderr, "Cannot open file %s: %s(%d)\n", 1186 + fn, strerror(errno), errno); 1187 + return -1; 1188 + } 1189 + 1190 + elf = elf_begin(elf_fd, ELF_C_READ, NULL); 1191 + if (!elf) { 1192 + fprintf(stderr, "Failed to read ELF from %s. %s\n", fn, 1193 + elf_errmsg(elf_errno())); 1194 + ret = -1; 1195 + goto done; 1196 + } 1197 + 1198 + if (!gelf_getehdr(elf, &ehdr)) { 1199 + fprintf(stderr, "Failed to get EHDR from %s\n", fn); 1200 + ret = -1; 1201 + goto done; 1202 + } 1203 + 1204 + while ((scn = elf_nextscn(elf, scn))) { 1205 + const char *sh_name; 1206 + GElf_Shdr sh; 1207 + 1208 + if (gelf_getshdr(scn, &sh) != &sh) { 1209 + fprintf(stderr, 1210 + "Failed to get section header from %s\n", fn); 1211 + ret = -1; 1212 + goto done; 1213 + } 1214 + 1215 + sh_name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name); 1216 + if (!strcmp(sh_name, BTF_ELF_SEC)) { 1217 + ret = 1; 1218 + goto done; 1219 + } 1220 + } 1221 + 1222 + ret = 0; 1223 + 1224 + done: 1225 + close(elf_fd); 1226 + elf_end(elf); 1227 + return ret; 1228 + } 1229 + 1230 + static int do_test_file(unsigned int test_num) 1231 + { 1232 + const struct btf_file_test *test = &file_tests[test_num - 1]; 1233 + struct bpf_object *obj = NULL; 1234 + struct bpf_program *prog; 1235 + struct bpf_map *map; 1236 + int err; 1237 + 1238 + fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num, 1239 + test->file); 1240 + 1241 + err = file_has_btf_elf(test->file); 1242 + if (err == -1) 1243 + return err; 1244 + 1245 + if (err == 0) { 1246 + fprintf(stderr, "SKIP. No ELF %s found\n", BTF_ELF_SEC); 1247 + return 0; 1248 + } 1249 + 1250 + obj = bpf_object__open(test->file); 1251 + if (IS_ERR(obj)) 1252 + return PTR_ERR(obj); 1253 + 1254 + err = bpf_object__btf_fd(obj); 1255 + if (err == -1) { 1256 + fprintf(stderr, "bpf_object__btf_fd: -1\n"); 1257 + goto done; 1258 + } 1259 + 1260 + prog = bpf_program__next(NULL, obj); 1261 + if (!prog) { 1262 + fprintf(stderr, "Cannot find bpf_prog\n"); 1263 + err = -1; 1264 + goto done; 1265 + } 1266 + 1267 + bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT); 1268 + err = bpf_object__load(obj); 1269 + if (err < 0) { 1270 + fprintf(stderr, "bpf_object__load: %d\n", err); 1271 + goto done; 1272 + } 1273 + 1274 + map = bpf_object__find_map_by_name(obj, "btf_map"); 1275 + if (!map) { 1276 + fprintf(stderr, "btf_map not found\n"); 1277 + err = -1; 1278 + goto done; 1279 + } 1280 + 1281 + err = (bpf_map__btf_key_id(map) == 0 || bpf_map__btf_value_id(map) == 0) 1282 + != test->btf_kv_notfound; 1283 + if (err) { 1284 + fprintf(stderr, 1285 + "btf_kv_notfound:%u btf_key_id:%u btf_value_id:%u\n", 1286 + test->btf_kv_notfound, 1287 + bpf_map__btf_key_id(map), 1288 + bpf_map__btf_value_id(map)); 1289 + goto done; 1290 + } 1291 + 1292 + fprintf(stderr, "OK\n"); 1293 + 1294 + done: 1295 + bpf_object__close(obj); 1296 + return err; 1297 + } 1298 + 1299 + static int test_file(void) 1300 + { 1301 + unsigned int i; 1302 + int err = 0; 1303 + 1304 + if (args.file_test_num) 1305 + return do_test_file(args.file_test_num); 1306 + 1307 + for (i = 1; i <= ARRAY_SIZE(file_tests); i++) 1308 + err |= do_test_file(i); 1309 + 1310 + return err; 1311 + } 1312 + 1313 + const char *pprint_enum_str[] = { 1314 + "ENUM_ZERO", 1315 + "ENUM_ONE", 1316 + "ENUM_TWO", 1317 + "ENUM_THREE", 1318 + }; 1319 + 1320 + struct pprint_mapv { 1321 + uint32_t ui32; 1322 + uint16_t ui16; 1323 + /* 2 bytes hole */ 1324 + int32_t si32; 1325 + uint32_t unused_bits2a:2, 1326 + bits28:28, 1327 + unused_bits2b:2; 1328 + union { 1329 + uint64_t ui64; 1330 + uint8_t ui8a[8]; 1331 + }; 1332 + enum { 1333 + ENUM_ZERO, 1334 + ENUM_ONE, 1335 + ENUM_TWO, 1336 + ENUM_THREE, 1337 + } aenum; 1338 + }; 1339 + 1340 + static struct btf_raw_test pprint_test = { 1341 + .descr = "BTF pretty print test #1", 1342 + .raw_types = { 1343 + /* unsighed char */ /* [1] */ 1344 + BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1), 1345 + /* unsigned short */ /* [2] */ 1346 + BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2), 1347 + /* unsigned int */ /* [3] */ 1348 + BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), 1349 + /* int */ /* [4] */ 1350 + BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), 1351 + /* unsigned long long */ /* [5] */ 1352 + BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8), 1353 + /* 2 bits */ /* [6] */ 1354 + BTF_TYPE_INT_ENC(0, 0, 0, 2, 2), 1355 + /* 28 bits */ /* [7] */ 1356 + BTF_TYPE_INT_ENC(0, 0, 0, 28, 4), 1357 + /* uint8_t[8] */ /* [8] */ 1358 + BTF_TYPE_ARRAY_ENC(9, 3, 8), 1359 + /* typedef unsigned char uint8_t */ /* [9] */ 1360 + BTF_TYPEDEF_ENC(NAME_TBD, 1), 1361 + /* typedef unsigned short uint16_t */ /* [10] */ 1362 + BTF_TYPEDEF_ENC(NAME_TBD, 2), 1363 + /* typedef unsigned int uint32_t */ /* [11] */ 1364 + BTF_TYPEDEF_ENC(NAME_TBD, 3), 1365 + /* typedef int int32_t */ /* [12] */ 1366 + BTF_TYPEDEF_ENC(NAME_TBD, 4), 1367 + /* typedef unsigned long long uint64_t *//* [13] */ 1368 + BTF_TYPEDEF_ENC(NAME_TBD, 5), 1369 + /* union (anon) */ /* [14] */ 1370 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 0, 2), 8), 1371 + BTF_MEMBER_ENC(NAME_TBD, 13, 0),/* uint64_t ui64; */ 1372 + BTF_MEMBER_ENC(NAME_TBD, 8, 0), /* uint8_t ui8a[8]; */ 1373 + /* enum (anon) */ /* [15] */ 1374 + BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 4), 4), 1375 + BTF_ENUM_ENC(NAME_TBD, 0), 1376 + BTF_ENUM_ENC(NAME_TBD, 1), 1377 + BTF_ENUM_ENC(NAME_TBD, 2), 1378 + BTF_ENUM_ENC(NAME_TBD, 3), 1379 + /* struct pprint_mapv */ /* [16] */ 1380 + BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 28), 1381 + BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */ 1382 + BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */ 1383 + BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */ 1384 + BTF_MEMBER_ENC(NAME_TBD, 6, 96), /* unused_bits2a */ 1385 + BTF_MEMBER_ENC(NAME_TBD, 7, 98), /* bits28 */ 1386 + BTF_MEMBER_ENC(NAME_TBD, 6, 126), /* unused_bits2b */ 1387 + BTF_MEMBER_ENC(0, 14, 128), /* union (anon) */ 1388 + BTF_MEMBER_ENC(NAME_TBD, 15, 192), /* aenum */ 1389 + BTF_END_RAW, 1390 + }, 1391 + .str_sec = "\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum", 1392 + .str_sec_size = sizeof("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"), 1393 + .map_type = BPF_MAP_TYPE_ARRAY, 1394 + .map_name = "pprint_test", 1395 + .key_size = sizeof(unsigned int), 1396 + .value_size = sizeof(struct pprint_mapv), 1397 + .key_id = 3, /* unsigned int */ 1398 + .value_id = 16, /* struct pprint_mapv */ 1399 + .max_entries = 128 * 1024, 1400 + }; 1401 + 1402 + static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i) 1403 + { 1404 + v->ui32 = i; 1405 + v->si32 = -i; 1406 + v->unused_bits2a = 3; 1407 + v->bits28 = i; 1408 + v->unused_bits2b = 3; 1409 + v->ui64 = i; 1410 + v->aenum = i & 0x03; 1411 + } 1412 + 1413 + static int test_pprint(void) 1414 + { 1415 + const struct btf_raw_test *test = &pprint_test; 1416 + struct bpf_create_map_attr create_attr = {}; 1417 + int map_fd = -1, btf_fd = -1; 1418 + struct pprint_mapv mapv = {}; 1419 + unsigned int raw_btf_size; 1420 + char expected_line[255]; 1421 + FILE *pin_file = NULL; 1422 + char pin_path[255]; 1423 + size_t line_len = 0; 1424 + char *line = NULL; 1425 + unsigned int key; 1426 + uint8_t *raw_btf; 1427 + ssize_t nread; 1428 + int err; 1429 + 1430 + fprintf(stderr, "%s......", test->descr); 1431 + raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types, 1432 + test->str_sec, test->str_sec_size, 1433 + &raw_btf_size); 1434 + 1435 + if (!raw_btf) 1436 + return -1; 1437 + 1438 + *btf_log_buf = '\0'; 1439 + btf_fd = bpf_load_btf(raw_btf, raw_btf_size, 1440 + btf_log_buf, BTF_LOG_BUF_SIZE, 1441 + args.always_log); 1442 + free(raw_btf); 1443 + 1444 + if (btf_fd == -1) { 1445 + err = -1; 1446 + fprintf(stderr, "bpf_load_btf: %s(%d)\n", 1447 + strerror(errno), errno); 1448 + goto done; 1449 + } 1450 + 1451 + create_attr.name = test->map_name; 1452 + create_attr.map_type = test->map_type; 1453 + create_attr.key_size = test->key_size; 1454 + create_attr.value_size = test->value_size; 1455 + create_attr.max_entries = test->max_entries; 1456 + create_attr.btf_fd = btf_fd; 1457 + create_attr.btf_key_id = test->key_id; 1458 + create_attr.btf_value_id = test->value_id; 1459 + 1460 + map_fd = bpf_create_map_xattr(&create_attr); 1461 + if (map_fd == -1) { 1462 + err = -1; 1463 + fprintf(stderr, "bpf_creat_map_btf: %s(%d)\n", 1464 + strerror(errno), errno); 1465 + goto done; 1466 + } 1467 + 1468 + if (snprintf(pin_path, sizeof(pin_path), "%s/%s", 1469 + "/sys/fs/bpf", test->map_name) == sizeof(pin_path)) { 1470 + err = -1; 1471 + fprintf(stderr, "pin_path is too long\n"); 1472 + goto done; 1473 + } 1474 + 1475 + err = bpf_obj_pin(map_fd, pin_path); 1476 + if (err) { 1477 + fprintf(stderr, "Cannot pin to %s. %s(%d).\n", pin_path, 1478 + strerror(errno), errno); 1479 + goto done; 1480 + } 1481 + 1482 + for (key = 0; key < test->max_entries; key++) { 1483 + set_pprint_mapv(&mapv, key); 1484 + bpf_map_update_elem(map_fd, &key, &mapv, 0); 1485 + } 1486 + 1487 + pin_file = fopen(pin_path, "r"); 1488 + if (!pin_file) { 1489 + err = -1; 1490 + fprintf(stderr, "fopen(%s): %s(%d)\n", pin_path, 1491 + strerror(errno), errno); 1492 + goto done; 1493 + } 1494 + 1495 + /* Skip lines start with '#' */ 1496 + while ((nread = getline(&line, &line_len, pin_file)) > 0 && 1497 + *line == '#') 1498 + ; 1499 + 1500 + if (nread <= 0) { 1501 + err = -1; 1502 + fprintf(stderr, "Unexpected EOF\n"); 1503 + goto done; 1504 + } 1505 + 1506 + key = 0; 1507 + do { 1508 + ssize_t nexpected_line; 1509 + 1510 + set_pprint_mapv(&mapv, key); 1511 + nexpected_line = snprintf(expected_line, sizeof(expected_line), 1512 + "%u: {%u,0,%d,0x%x,0x%x,0x%x,{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n", 1513 + key, 1514 + mapv.ui32, mapv.si32, 1515 + mapv.unused_bits2a, mapv.bits28, mapv.unused_bits2b, 1516 + mapv.ui64, 1517 + mapv.ui8a[0], mapv.ui8a[1], mapv.ui8a[2], mapv.ui8a[3], 1518 + mapv.ui8a[4], mapv.ui8a[5], mapv.ui8a[6], mapv.ui8a[7], 1519 + pprint_enum_str[mapv.aenum]); 1520 + 1521 + if (nexpected_line == sizeof(expected_line)) { 1522 + err = -1; 1523 + fprintf(stderr, "expected_line is too long\n"); 1524 + goto done; 1525 + } 1526 + 1527 + if (strcmp(expected_line, line)) { 1528 + err = -1; 1529 + fprintf(stderr, "unexpected pprint output\n"); 1530 + fprintf(stderr, "expected: %s", expected_line); 1531 + fprintf(stderr, " read: %s", line); 1532 + goto done; 1533 + } 1534 + 1535 + nread = getline(&line, &line_len, pin_file); 1536 + } while (++key < test->max_entries && nread > 0); 1537 + 1538 + if (key < test->max_entries) { 1539 + err = -1; 1540 + fprintf(stderr, "Unexpected EOF\n"); 1541 + goto done; 1542 + } 1543 + 1544 + if (nread > 0) { 1545 + err = -1; 1546 + fprintf(stderr, "Unexpected extra pprint output: %s\n", line); 1547 + goto done; 1548 + } 1549 + 1550 + err = 0; 1551 + 1552 + done: 1553 + if (!err) 1554 + fprintf(stderr, "OK\n"); 1555 + if (*btf_log_buf && (err || args.always_log)) 1556 + fprintf(stderr, "%s\n", btf_log_buf); 1557 + if (btf_fd != -1) 1558 + close(btf_fd); 1559 + if (map_fd != -1) 1560 + close(map_fd); 1561 + if (pin_file) 1562 + fclose(pin_file); 1563 + unlink(pin_path); 1564 + free(line); 1565 + 1566 + return err; 1567 + } 1568 + 1569 + static void usage(const char *cmd) 1570 + { 1571 + fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] | [-g test_num (1 - %zu)] | [-f test_num (1 - %zu)] | [-p]]\n", 1572 + cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests), 1573 + ARRAY_SIZE(file_tests)); 1574 + } 1575 + 1576 + static int parse_args(int argc, char **argv) 1577 + { 1578 + const char *optstr = "lpf:r:g:"; 1579 + int opt; 1580 + 1581 + while ((opt = getopt(argc, argv, optstr)) != -1) { 1582 + switch (opt) { 1583 + case 'l': 1584 + args.always_log = true; 1585 + break; 1586 + case 'f': 1587 + args.file_test_num = atoi(optarg); 1588 + args.file_test = true; 1589 + break; 1590 + case 'r': 1591 + args.raw_test_num = atoi(optarg); 1592 + args.raw_test = true; 1593 + break; 1594 + case 'g': 1595 + args.get_info_test_num = atoi(optarg); 1596 + args.get_info_test = true; 1597 + break; 1598 + case 'p': 1599 + args.pprint_test = true; 1600 + break; 1601 + case 'h': 1602 + usage(argv[0]); 1603 + exit(0); 1604 + default: 1605 + usage(argv[0]); 1606 + return -1; 1607 + } 1608 + } 1609 + 1610 + if (args.raw_test_num && 1611 + (args.raw_test_num < 1 || 1612 + args.raw_test_num > ARRAY_SIZE(raw_tests))) { 1613 + fprintf(stderr, "BTF raw test number must be [1 - %zu]\n", 1614 + ARRAY_SIZE(raw_tests)); 1615 + return -1; 1616 + } 1617 + 1618 + if (args.file_test_num && 1619 + (args.file_test_num < 1 || 1620 + args.file_test_num > ARRAY_SIZE(file_tests))) { 1621 + fprintf(stderr, "BTF file test number must be [1 - %zu]\n", 1622 + ARRAY_SIZE(file_tests)); 1623 + return -1; 1624 + } 1625 + 1626 + if (args.get_info_test_num && 1627 + (args.get_info_test_num < 1 || 1628 + args.get_info_test_num > ARRAY_SIZE(get_info_tests))) { 1629 + fprintf(stderr, "BTF get info test number must be [1 - %zu]\n", 1630 + ARRAY_SIZE(get_info_tests)); 1631 + return -1; 1632 + } 1633 + 1634 + return 0; 1635 + } 1636 + 1637 + int main(int argc, char **argv) 1638 + { 1639 + int err = 0; 1640 + 1641 + err = parse_args(argc, argv); 1642 + if (err) 1643 + return err; 1644 + 1645 + if (args.always_log) 1646 + libbpf_set_print(__base_pr, __base_pr, __base_pr); 1647 + 1648 + if (args.raw_test) 1649 + err |= test_raw(); 1650 + 1651 + if (args.get_info_test) 1652 + err |= test_get_info(); 1653 + 1654 + if (args.file_test) 1655 + err |= test_file(); 1656 + 1657 + if (args.pprint_test) 1658 + err |= test_pprint(); 1659 + 1660 + if (args.raw_test || args.get_info_test || args.file_test || 1661 + args.pprint_test) 1662 + return err; 1663 + 1664 + err |= test_raw(); 1665 + err |= test_get_info(); 1666 + err |= test_file(); 1667 + 1668 + return err; 1669 + }
+48
tools/testing/selftests/bpf/test_btf_haskv.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018 Facebook */ 3 + #include <linux/bpf.h> 4 + #include "bpf_helpers.h" 5 + 6 + int _version SEC("version") = 1; 7 + 8 + struct ipv_counts { 9 + unsigned int v4; 10 + unsigned int v6; 11 + }; 12 + 13 + typedef int btf_map_key; 14 + typedef struct ipv_counts btf_map_value; 15 + btf_map_key dumm_key; 16 + btf_map_value dummy_value; 17 + 18 + struct bpf_map_def SEC("maps") btf_map = { 19 + .type = BPF_MAP_TYPE_ARRAY, 20 + .key_size = sizeof(int), 21 + .value_size = sizeof(struct ipv_counts), 22 + .max_entries = 4, 23 + }; 24 + 25 + struct dummy_tracepoint_args { 26 + unsigned long long pad; 27 + struct sock *sock; 28 + }; 29 + 30 + SEC("dummy_tracepoint") 31 + int _dummy_tracepoint(struct dummy_tracepoint_args *arg) 32 + { 33 + struct ipv_counts *counts; 34 + int key = 0; 35 + 36 + if (!arg->sock) 37 + return 0; 38 + 39 + counts = bpf_map_lookup_elem(&btf_map, &key); 40 + if (!counts) 41 + return 0; 42 + 43 + counts->v6++; 44 + 45 + return 0; 46 + } 47 + 48 + char _license[] SEC("license") = "GPL";
+43
tools/testing/selftests/bpf/test_btf_nokv.c
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2018 Facebook */ 3 + #include <linux/bpf.h> 4 + #include "bpf_helpers.h" 5 + 6 + int _version SEC("version") = 1; 7 + 8 + struct ipv_counts { 9 + unsigned int v4; 10 + unsigned int v6; 11 + }; 12 + 13 + struct bpf_map_def SEC("maps") btf_map = { 14 + .type = BPF_MAP_TYPE_ARRAY, 15 + .key_size = sizeof(int), 16 + .value_size = sizeof(struct ipv_counts), 17 + .max_entries = 4, 18 + }; 19 + 20 + struct dummy_tracepoint_args { 21 + unsigned long long pad; 22 + struct sock *sock; 23 + }; 24 + 25 + SEC("dummy_tracepoint") 26 + int _dummy_tracepoint(struct dummy_tracepoint_args *arg) 27 + { 28 + struct ipv_counts *counts; 29 + int key = 0; 30 + 31 + if (!arg->sock) 32 + return 0; 33 + 34 + counts = bpf_map_lookup_elem(&btf_map, &key); 35 + if (!counts) 36 + return 0; 37 + 38 + counts->v6++; 39 + 40 + return 0; 41 + } 42 + 43 + char _license[] SEC("license") = "GPL";