1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2018 Facebook */
7 #include <linux/kernel.h>
8 #include <linux/filter.h>
10 #include <sys/resource.h>
20 #include <bpf/libbpf.h>
23 #include "bpf_rlimit.h"
27 #define MAX_SUBPROGS 16
29 static uint32_t pass_cnt;
30 static uint32_t error_cnt;
31 static uint32_t skip_cnt;
33 #define CHECK(condition, format...) ({ \
34 int __ret = !!(condition); \
36 fprintf(stderr, "%s:%d:FAIL ", __func__, __LINE__); \
37 fprintf(stderr, format); \
42 static int count_result(int err)
49 fprintf(stderr, "\n");
53 #define __printf(a, b) __attribute__((format(printf, a, b)))
56 static int __base_pr(const char *format, ...)
61 va_start(args, format);
62 err = vfprintf(stderr, format, args);
67 #define BTF_INFO_ENC(kind, root, vlen) \
68 ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
70 #define BTF_TYPE_ENC(name, info, size_or_type) \
71 (name), (info), (size_or_type)
73 #define BTF_INT_ENC(encoding, bits_offset, nr_bits) \
74 ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
75 #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
76 BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz), \
77 BTF_INT_ENC(encoding, bits_offset, bits)
79 #define BTF_ARRAY_ENC(type, index_type, nr_elems) \
80 (type), (index_type), (nr_elems)
81 #define BTF_TYPE_ARRAY_ENC(type, index_type, nr_elems) \
82 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 0), \
83 BTF_ARRAY_ENC(type, index_type, nr_elems)
85 #define BTF_MEMBER_ENC(name, type, bits_offset) \
86 (name), (type), (bits_offset)
87 #define BTF_ENUM_ENC(name, val) (name), (val)
89 #define BTF_TYPEDEF_ENC(name, type) \
90 BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), type)
92 #define BTF_PTR_ENC(type) \
93 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), type)
95 #define BTF_CONST_ENC(type) \
96 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), type)
98 #define BTF_FUNC_PROTO_ENC(ret_type, nargs) \
99 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, nargs), ret_type)
101 #define BTF_FUNC_PROTO_ARG_ENC(name, type) \
104 #define BTF_FUNC_ENC(name, func_proto) \
105 BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 0), func_proto)
107 #define BTF_END_RAW 0xdeadbeef
108 #define NAME_TBD 0xdeadb33f
110 #define MAX_NR_RAW_TYPES 1024
111 #define BTF_LOG_BUF_SIZE 65535
114 unsigned int raw_test_num;
115 unsigned int file_test_num;
116 unsigned int get_info_test_num;
125 static char btf_log_buf[BTF_LOG_BUF_SIZE];
127 static struct btf_header hdr_tmpl = {
129 .version = BTF_VERSION,
130 .hdr_len = sizeof(struct btf_header),
133 struct btf_raw_test {
136 const char *map_name;
138 __u32 raw_types[MAX_NR_RAW_TYPES];
140 enum bpf_map_type map_type;
157 static struct btf_raw_test raw_tests[] = {
164 * unsigned long long m;
174 .descr = "struct test #1",
177 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
178 /* unsigned long long */
179 BTF_TYPE_INT_ENC(0, 0, 0, 64, 8), /* [2] */
181 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1), /* [3] */
183 BTF_TYPE_ARRAY_ENC(1, 1, 8), /* [4] */
184 /* struct A { */ /* [5] */
185 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 6), 180),
186 BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/
187 BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n; */
188 BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o; */
189 BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8] */
190 BTF_MEMBER_ENC(NAME_TBD, 6, 384),/* int q[4][8] */
191 BTF_MEMBER_ENC(NAME_TBD, 7, 1408), /* enum E r */
194 BTF_TYPE_ARRAY_ENC(4, 1, 4), /* [6] */
195 /* enum E */ /* [7] */
196 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)),
197 BTF_ENUM_ENC(NAME_TBD, 0),
198 BTF_ENUM_ENC(NAME_TBD, 1),
201 .str_sec = "\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1",
202 .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1"),
203 .map_type = BPF_MAP_TYPE_ARRAY,
204 .map_name = "struct_test1_map",
205 .key_size = sizeof(int),
212 /* typedef struct b Struct_B;
217 * const Struct_B o[4];
226 .descr = "struct test #2",
229 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
230 /* struct b [4] */ /* [2] */
231 BTF_TYPE_ARRAY_ENC(4, 1, 4),
233 /* struct A { */ /* [3] */
234 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 3), 68),
235 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
236 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct B n[4] */
237 BTF_MEMBER_ENC(NAME_TBD, 8, 288),/* const Struct_B o[4];*/
240 /* struct B { */ /* [4] */
241 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
242 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
243 BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */
246 /* const int */ /* [5] */
247 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),
248 /* typedef struct b Struct_B */ /* [6] */
249 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 4),
250 /* const Struct_B */ /* [7] */
251 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 6),
252 /* const Struct_B [4] */ /* [8] */
253 BTF_TYPE_ARRAY_ENC(7, 1, 4),
256 .str_sec = "\0A\0m\0n\0o\0B\0m\0n\0Struct_B",
257 .str_sec_size = sizeof("\0A\0m\0n\0o\0B\0m\0n\0Struct_B"),
258 .map_type = BPF_MAP_TYPE_ARRAY,
259 .map_name = "struct_test2_map",
260 .key_size = sizeof(int),
268 .descr = "struct test #3 Invalid member offset",
271 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
272 /* int64 */ /* [2] */
273 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),
275 /* struct A { */ /* [3] */
276 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 16),
277 BTF_MEMBER_ENC(NAME_TBD, 1, 64), /* int m; */
278 BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* int64 n; */
282 .str_sec = "\0A\0m\0n\0",
283 .str_sec_size = sizeof("\0A\0m\0n\0"),
284 .map_type = BPF_MAP_TYPE_ARRAY,
285 .map_name = "struct_test3_map",
286 .key_size = sizeof(int),
291 .btf_load_err = true,
292 .err_str = "Invalid member bits_offset",
295 /* Test member exceeds the size of struct.
303 .descr = "size check test #1",
306 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
307 /* struct A { */ /* [2] */
308 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 - 1),
309 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
310 BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */
314 .str_sec = "\0A\0m\0n",
315 .str_sec_size = sizeof("\0A\0m\0n"),
316 .map_type = BPF_MAP_TYPE_ARRAY,
317 .map_name = "size_check1_map",
318 .key_size = sizeof(int),
323 .btf_load_err = true,
324 .err_str = "Member exceeds struct_size",
327 /* Test member exeeds the size of struct
335 .descr = "size check test #2",
338 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
339 /* int[2] */ /* [2] */
340 BTF_TYPE_ARRAY_ENC(1, 1, 2),
341 /* struct A { */ /* [3] */
342 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 3 - 1),
343 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
344 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* int n[2]; */
348 .str_sec = "\0A\0m\0n",
349 .str_sec_size = sizeof("\0A\0m\0n"),
350 .map_type = BPF_MAP_TYPE_ARRAY,
351 .map_name = "size_check2_map",
352 .key_size = sizeof(int),
357 .btf_load_err = true,
358 .err_str = "Member exceeds struct_size",
361 /* Test member exeeds the size of struct
369 .descr = "size check test #3",
372 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
373 /* void* */ /* [2] */
374 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
375 /* struct A { */ /* [3] */
376 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) + sizeof(void *) - 1),
377 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
378 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* void *n; */
382 .str_sec = "\0A\0m\0n",
383 .str_sec_size = sizeof("\0A\0m\0n"),
384 .map_type = BPF_MAP_TYPE_ARRAY,
385 .map_name = "size_check3_map",
386 .key_size = sizeof(int),
391 .btf_load_err = true,
392 .err_str = "Member exceeds struct_size",
395 /* Test member exceeds the size of struct
408 .descr = "size check test #4",
411 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
412 /* enum E { */ /* [2] */
413 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)),
414 BTF_ENUM_ENC(NAME_TBD, 0),
415 BTF_ENUM_ENC(NAME_TBD, 1),
417 /* struct A { */ /* [3] */
418 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 - 1),
419 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
420 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* enum E n; */
424 .str_sec = "\0E\0E0\0E1\0A\0m\0n",
425 .str_sec_size = sizeof("\0E\0E0\0E1\0A\0m\0n"),
426 .map_type = BPF_MAP_TYPE_ARRAY,
427 .map_name = "size_check4_map",
428 .key_size = sizeof(int),
433 .btf_load_err = true,
434 .err_str = "Member exceeds struct_size",
437 /* typedef const void * const_void_ptr;
443 .descr = "void test #1",
446 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
447 /* const void */ /* [2] */
448 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
449 /* const void* */ /* [3] */
450 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
451 /* typedef const void * const_void_ptr */
452 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
453 /* struct A { */ /* [4] */
454 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
455 /* const_void_ptr m; */
456 BTF_MEMBER_ENC(NAME_TBD, 3, 0),
460 .str_sec = "\0const_void_ptr\0A\0m",
461 .str_sec_size = sizeof("\0const_void_ptr\0A\0m"),
462 .map_type = BPF_MAP_TYPE_ARRAY,
463 .map_name = "void_test1_map",
464 .key_size = sizeof(int),
465 .value_size = sizeof(void *),
476 .descr = "void test #2",
479 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
480 /* const void */ /* [2] */
481 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
482 /* struct A { */ /* [3] */
483 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 8),
485 BTF_MEMBER_ENC(NAME_TBD, 2, 0),
490 .str_sec_size = sizeof("\0A\0m"),
491 .map_type = BPF_MAP_TYPE_ARRAY,
492 .map_name = "void_test2_map",
493 .key_size = sizeof(int),
494 .value_size = sizeof(void *),
498 .btf_load_err = true,
499 .err_str = "Invalid member",
502 /* typedef const void * const_void_ptr;
506 .descr = "void test #3",
509 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
510 /* const void */ /* [2] */
511 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
512 /* const void* */ /* [3] */
513 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
514 /* typedef const void * const_void_ptr */ /* [4] */
515 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
516 /* const_void_ptr[4] */ /* [5] */
517 BTF_TYPE_ARRAY_ENC(3, 1, 4),
520 .str_sec = "\0const_void_ptr",
521 .str_sec_size = sizeof("\0const_void_ptr"),
522 .map_type = BPF_MAP_TYPE_ARRAY,
523 .map_name = "void_test3_map",
524 .key_size = sizeof(int),
525 .value_size = sizeof(void *) * 4,
533 .descr = "void test #4",
536 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
537 /* const void */ /* [2] */
538 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
539 /* const void[4] */ /* [3] */
540 BTF_TYPE_ARRAY_ENC(2, 1, 4),
544 .str_sec_size = sizeof("\0A\0m"),
545 .map_type = BPF_MAP_TYPE_ARRAY,
546 .map_name = "void_test4_map",
547 .key_size = sizeof(int),
548 .value_size = sizeof(void *) * 4,
552 .btf_load_err = true,
553 .err_str = "Invalid elem",
556 /* Array_A <------------------+
557 * elem_type == Array_B |
560 * Array_B <-------- + |
561 * elem_type == Array A --+
564 .descr = "loop test #1",
567 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
568 /* Array_A */ /* [2] */
569 BTF_TYPE_ARRAY_ENC(3, 1, 8),
570 /* Array_B */ /* [3] */
571 BTF_TYPE_ARRAY_ENC(2, 1, 8),
575 .str_sec_size = sizeof(""),
576 .map_type = BPF_MAP_TYPE_ARRAY,
577 .map_name = "loop_test1_map",
578 .key_size = sizeof(int),
579 .value_size = sizeof(sizeof(int) * 8),
583 .btf_load_err = true,
584 .err_str = "Loop detected",
587 /* typedef is _before_ the BTF type of Array_A and Array_B
589 * typedef Array_B int_array;
591 * Array_A <------------------+
592 * elem_type == int_array |
595 * Array_B <-------- + |
596 * elem_type == Array_A --+
599 .descr = "loop test #2",
602 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
603 /* typedef Array_B int_array */
604 BTF_TYPEDEF_ENC(1, 4), /* [2] */
606 BTF_TYPE_ARRAY_ENC(2, 1, 8), /* [3] */
608 BTF_TYPE_ARRAY_ENC(3, 1, 8), /* [4] */
611 .str_sec = "\0int_array\0",
612 .str_sec_size = sizeof("\0int_array"),
613 .map_type = BPF_MAP_TYPE_ARRAY,
614 .map_name = "loop_test2_map",
615 .key_size = sizeof(int),
616 .value_size = sizeof(sizeof(int) * 8),
620 .btf_load_err = true,
621 .err_str = "Loop detected",
624 /* Array_A <------------------+
625 * elem_type == Array_B |
628 * Array_B <-------- + |
629 * elem_type == Array_A --+
632 .descr = "loop test #3",
635 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
636 /* Array_A */ /* [2] */
637 BTF_TYPE_ARRAY_ENC(3, 1, 8),
638 /* Array_B */ /* [3] */
639 BTF_TYPE_ARRAY_ENC(2, 1, 8),
643 .str_sec_size = sizeof(""),
644 .map_type = BPF_MAP_TYPE_ARRAY,
645 .map_name = "loop_test3_map",
646 .key_size = sizeof(int),
647 .value_size = sizeof(sizeof(int) * 8),
651 .btf_load_err = true,
652 .err_str = "Loop detected",
655 /* typedef is _between_ the BTF type of Array_A and Array_B
657 * typedef Array_B int_array;
659 * Array_A <------------------+
660 * elem_type == int_array |
663 * Array_B <-------- + |
664 * elem_type == Array_A --+
667 .descr = "loop test #4",
670 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
671 /* Array_A */ /* [2] */
672 BTF_TYPE_ARRAY_ENC(3, 1, 8),
673 /* typedef Array_B int_array */ /* [3] */
674 BTF_TYPEDEF_ENC(NAME_TBD, 4),
675 /* Array_B */ /* [4] */
676 BTF_TYPE_ARRAY_ENC(2, 1, 8),
679 .str_sec = "\0int_array\0",
680 .str_sec_size = sizeof("\0int_array"),
681 .map_type = BPF_MAP_TYPE_ARRAY,
682 .map_name = "loop_test4_map",
683 .key_size = sizeof(int),
684 .value_size = sizeof(sizeof(int) * 8),
688 .btf_load_err = true,
689 .err_str = "Loop detected",
692 /* typedef struct B Struct_B
705 .descr = "loop test #5",
708 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
709 /* struct A */ /* [2] */
710 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
711 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x; */
712 BTF_MEMBER_ENC(NAME_TBD, 3, 32),/* Struct_B y; */
713 /* typedef struct B Struct_B */
714 BTF_TYPEDEF_ENC(NAME_TBD, 4), /* [3] */
715 /* struct B */ /* [4] */
716 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
717 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x; */
718 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A y; */
721 .str_sec = "\0A\0x\0y\0Struct_B\0B\0x\0y",
722 .str_sec_size = sizeof("\0A\0x\0y\0Struct_B\0B\0x\0y"),
723 .map_type = BPF_MAP_TYPE_ARRAY,
724 .map_name = "loop_test5_map",
725 .key_size = sizeof(int),
730 .btf_load_err = true,
731 .err_str = "Loop detected",
736 * struct A array_a[4];
740 .descr = "loop test #6",
743 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
744 BTF_TYPE_ARRAY_ENC(3, 1, 4), /* [2] */
745 /* struct A */ /* [3] */
746 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
747 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x; */
748 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A array_a[4]; */
751 .str_sec = "\0A\0x\0y",
752 .str_sec_size = sizeof("\0A\0x\0y"),
753 .map_type = BPF_MAP_TYPE_ARRAY,
754 .map_name = "loop_test6_map",
755 .key_size = sizeof(int),
760 .btf_load_err = true,
761 .err_str = "Loop detected",
765 .descr = "loop test #7",
768 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
769 /* struct A { */ /* [2] */
770 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
772 BTF_MEMBER_ENC(NAME_TBD, 3, 0),
773 /* CONST type_id=3 */ /* [3] */
774 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
775 /* PTR type_id=2 */ /* [4] */
776 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
780 .str_sec_size = sizeof("\0A\0m"),
781 .map_type = BPF_MAP_TYPE_ARRAY,
782 .map_name = "loop_test7_map",
783 .key_size = sizeof(int),
784 .value_size = sizeof(void *),
788 .btf_load_err = true,
789 .err_str = "Loop detected",
793 .descr = "loop test #8",
796 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
797 /* struct A { */ /* [2] */
798 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
800 BTF_MEMBER_ENC(NAME_TBD, 4, 0),
801 /* struct B { */ /* [3] */
802 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
804 BTF_MEMBER_ENC(NAME_TBD, 6, 0),
805 /* CONST type_id=5 */ /* [4] */
806 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 5),
807 /* PTR type_id=6 */ /* [5] */
808 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),
809 /* CONST type_id=7 */ /* [6] */
810 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 7),
811 /* PTR type_id=4 */ /* [7] */
812 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 4),
815 .str_sec = "\0A\0m\0B\0n",
816 .str_sec_size = sizeof("\0A\0m\0B\0n"),
817 .map_type = BPF_MAP_TYPE_ARRAY,
818 .map_name = "loop_test8_map",
819 .key_size = sizeof(int),
820 .value_size = sizeof(void *),
824 .btf_load_err = true,
825 .err_str = "Loop detected",
829 .descr = "string section does not end with null",
832 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
836 .str_sec_size = sizeof("\0int") - 1,
837 .map_type = BPF_MAP_TYPE_ARRAY,
838 .map_name = "hdr_test_map",
839 .key_size = sizeof(int),
840 .value_size = sizeof(int),
844 .btf_load_err = true,
845 .err_str = "Invalid string section",
849 .descr = "empty string section",
852 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
857 .map_type = BPF_MAP_TYPE_ARRAY,
858 .map_name = "hdr_test_map",
859 .key_size = sizeof(int),
860 .value_size = sizeof(int),
864 .btf_load_err = true,
865 .err_str = "Invalid string section",
869 .descr = "empty type section",
874 .str_sec_size = sizeof("\0int"),
875 .map_type = BPF_MAP_TYPE_ARRAY,
876 .map_name = "hdr_test_map",
877 .key_size = sizeof(int),
878 .value_size = sizeof(int),
882 .btf_load_err = true,
883 .err_str = "No type found",
887 .descr = "btf_header test. Longer hdr_len",
890 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
894 .str_sec_size = sizeof("\0int"),
895 .map_type = BPF_MAP_TYPE_ARRAY,
896 .map_name = "hdr_test_map",
897 .key_size = sizeof(int),
898 .value_size = sizeof(int),
902 .btf_load_err = true,
904 .err_str = "Unsupported btf_header",
908 .descr = "btf_header test. Gap between hdr and type",
911 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
915 .str_sec_size = sizeof("\0int"),
916 .map_type = BPF_MAP_TYPE_ARRAY,
917 .map_name = "hdr_test_map",
918 .key_size = sizeof(int),
919 .value_size = sizeof(int),
923 .btf_load_err = true,
925 .err_str = "Unsupported section found",
929 .descr = "btf_header test. Gap between type and str",
932 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
936 .str_sec_size = sizeof("\0int"),
937 .map_type = BPF_MAP_TYPE_ARRAY,
938 .map_name = "hdr_test_map",
939 .key_size = sizeof(int),
940 .value_size = sizeof(int),
944 .btf_load_err = true,
946 .err_str = "Unsupported section found",
950 .descr = "btf_header test. Overlap between type and str",
953 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
957 .str_sec_size = sizeof("\0int"),
958 .map_type = BPF_MAP_TYPE_ARRAY,
959 .map_name = "hdr_test_map",
960 .key_size = sizeof(int),
961 .value_size = sizeof(int),
965 .btf_load_err = true,
967 .err_str = "Section overlap found",
971 .descr = "btf_header test. Larger BTF size",
974 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
978 .str_sec_size = sizeof("\0int"),
979 .map_type = BPF_MAP_TYPE_ARRAY,
980 .map_name = "hdr_test_map",
981 .key_size = sizeof(int),
982 .value_size = sizeof(int),
986 .btf_load_err = true,
988 .err_str = "Unsupported section found",
992 .descr = "btf_header test. Smaller BTF size",
995 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
999 .str_sec_size = sizeof("\0int"),
1000 .map_type = BPF_MAP_TYPE_ARRAY,
1001 .map_name = "hdr_test_map",
1002 .key_size = sizeof(int),
1003 .value_size = sizeof(int),
1007 .btf_load_err = true,
1009 .err_str = "Total section length too long",
1013 .descr = "array test. index_type/elem_type \"int\"",
1016 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1017 /* int[16] */ /* [2] */
1018 BTF_TYPE_ARRAY_ENC(1, 1, 16),
1022 .str_sec_size = sizeof(""),
1023 .map_type = BPF_MAP_TYPE_ARRAY,
1024 .map_name = "array_test_map",
1025 .key_size = sizeof(int),
1026 .value_size = sizeof(int),
1033 .descr = "array test. index_type/elem_type \"const int\"",
1036 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1037 /* int[16] */ /* [2] */
1038 BTF_TYPE_ARRAY_ENC(3, 3, 16),
1039 /* CONST type_id=1 */ /* [3] */
1040 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),
1044 .str_sec_size = sizeof(""),
1045 .map_type = BPF_MAP_TYPE_ARRAY,
1046 .map_name = "array_test_map",
1047 .key_size = sizeof(int),
1048 .value_size = sizeof(int),
1055 .descr = "array test. index_type \"const int:31\"",
1058 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1059 /* int:31 */ /* [2] */
1060 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 31, 4),
1061 /* int[16] */ /* [3] */
1062 BTF_TYPE_ARRAY_ENC(1, 4, 16),
1063 /* CONST type_id=2 */ /* [4] */
1064 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2),
1068 .str_sec_size = sizeof(""),
1069 .map_type = BPF_MAP_TYPE_ARRAY,
1070 .map_name = "array_test_map",
1071 .key_size = sizeof(int),
1072 .value_size = sizeof(int),
1076 .btf_load_err = true,
1077 .err_str = "Invalid index",
1081 .descr = "array test. elem_type \"const int:31\"",
1084 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1085 /* int:31 */ /* [2] */
1086 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 31, 4),
1087 /* int[16] */ /* [3] */
1088 BTF_TYPE_ARRAY_ENC(4, 1, 16),
1089 /* CONST type_id=2 */ /* [4] */
1090 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2),
1094 .str_sec_size = sizeof(""),
1095 .map_type = BPF_MAP_TYPE_ARRAY,
1096 .map_name = "array_test_map",
1097 .key_size = sizeof(int),
1098 .value_size = sizeof(int),
1102 .btf_load_err = true,
1103 .err_str = "Invalid array of int",
1107 .descr = "array test. index_type \"void\"",
1110 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1111 /* int[16] */ /* [2] */
1112 BTF_TYPE_ARRAY_ENC(1, 0, 16),
1116 .str_sec_size = sizeof(""),
1117 .map_type = BPF_MAP_TYPE_ARRAY,
1118 .map_name = "array_test_map",
1119 .key_size = sizeof(int),
1120 .value_size = sizeof(int),
1124 .btf_load_err = true,
1125 .err_str = "Invalid index",
1129 .descr = "array test. index_type \"const void\"",
1132 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1133 /* int[16] */ /* [2] */
1134 BTF_TYPE_ARRAY_ENC(1, 3, 16),
1135 /* CONST type_id=0 (void) */ /* [3] */
1136 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
1140 .str_sec_size = sizeof(""),
1141 .map_type = BPF_MAP_TYPE_ARRAY,
1142 .map_name = "array_test_map",
1143 .key_size = sizeof(int),
1144 .value_size = sizeof(int),
1148 .btf_load_err = true,
1149 .err_str = "Invalid index",
1153 .descr = "array test. elem_type \"const void\"",
1156 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1157 /* int[16] */ /* [2] */
1158 BTF_TYPE_ARRAY_ENC(3, 1, 16),
1159 /* CONST type_id=0 (void) */ /* [3] */
1160 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
1164 .str_sec_size = sizeof(""),
1165 .map_type = BPF_MAP_TYPE_ARRAY,
1166 .map_name = "array_test_map",
1167 .key_size = sizeof(int),
1168 .value_size = sizeof(int),
1172 .btf_load_err = true,
1173 .err_str = "Invalid elem",
1177 .descr = "array test. elem_type \"const void *\"",
1180 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1181 /* const void *[16] */ /* [2] */
1182 BTF_TYPE_ARRAY_ENC(3, 1, 16),
1183 /* CONST type_id=4 */ /* [3] */
1184 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
1185 /* void* */ /* [4] */
1186 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
1190 .str_sec_size = sizeof(""),
1191 .map_type = BPF_MAP_TYPE_ARRAY,
1192 .map_name = "array_test_map",
1193 .key_size = sizeof(int),
1194 .value_size = sizeof(int),
1201 .descr = "array test. index_type \"const void *\"",
1204 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1205 /* const void *[16] */ /* [2] */
1206 BTF_TYPE_ARRAY_ENC(3, 3, 16),
1207 /* CONST type_id=4 */ /* [3] */
1208 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
1209 /* void* */ /* [4] */
1210 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
1214 .str_sec_size = sizeof(""),
1215 .map_type = BPF_MAP_TYPE_ARRAY,
1216 .map_name = "array_test_map",
1217 .key_size = sizeof(int),
1218 .value_size = sizeof(int),
1222 .btf_load_err = true,
1223 .err_str = "Invalid index",
1227 .descr = "array test. t->size != 0\"",
1230 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1231 /* int[16] */ /* [2] */
1232 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 1),
1233 BTF_ARRAY_ENC(1, 1, 16),
1237 .str_sec_size = sizeof(""),
1238 .map_type = BPF_MAP_TYPE_ARRAY,
1239 .map_name = "array_test_map",
1240 .key_size = sizeof(int),
1241 .value_size = sizeof(int),
1245 .btf_load_err = true,
1246 .err_str = "size != 0",
1250 .descr = "int test. invalid int_data",
1252 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), 4),
1257 .str_sec_size = sizeof(""),
1258 .map_type = BPF_MAP_TYPE_ARRAY,
1259 .map_name = "array_test_map",
1260 .key_size = sizeof(int),
1261 .value_size = sizeof(int),
1265 .btf_load_err = true,
1266 .err_str = "Invalid int_data",
1270 .descr = "invalid BTF_INFO",
1273 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1274 BTF_TYPE_ENC(0, 0x10000000, 4),
1278 .str_sec_size = sizeof(""),
1279 .map_type = BPF_MAP_TYPE_ARRAY,
1280 .map_name = "array_test_map",
1281 .key_size = sizeof(int),
1282 .value_size = sizeof(int),
1286 .btf_load_err = true,
1287 .err_str = "Invalid btf_info",
1291 .descr = "fwd test. t->type != 0\"",
1294 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1295 /* fwd type */ /* [2] */
1296 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FWD, 0, 0), 1),
1300 .str_sec_size = sizeof(""),
1301 .map_type = BPF_MAP_TYPE_ARRAY,
1302 .map_name = "fwd_test_map",
1303 .key_size = sizeof(int),
1304 .value_size = sizeof(int),
1308 .btf_load_err = true,
1309 .err_str = "type != 0",
1313 .descr = "arraymap invalid btf key (a bit field)",
1316 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1317 /* 32 bit int with 32 bit offset */ /* [2] */
1318 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 32, 32, 8),
1322 .str_sec_size = sizeof(""),
1323 .map_type = BPF_MAP_TYPE_ARRAY,
1324 .map_name = "array_map_check_btf",
1325 .key_size = sizeof(int),
1326 .value_size = sizeof(int),
1330 .map_create_err = true,
1334 .descr = "arraymap invalid btf key (!= 32 bits)",
1337 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1338 /* 16 bit int with 0 bit offset */ /* [2] */
1339 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 16, 2),
1343 .str_sec_size = sizeof(""),
1344 .map_type = BPF_MAP_TYPE_ARRAY,
1345 .map_name = "array_map_check_btf",
1346 .key_size = sizeof(int),
1347 .value_size = sizeof(int),
1351 .map_create_err = true,
1355 .descr = "arraymap invalid btf value (too small)",
1358 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1362 .str_sec_size = sizeof(""),
1363 .map_type = BPF_MAP_TYPE_ARRAY,
1364 .map_name = "array_map_check_btf",
1365 .key_size = sizeof(int),
1366 /* btf_value_size < map->value_size */
1367 .value_size = sizeof(__u64),
1371 .map_create_err = true,
1375 .descr = "arraymap invalid btf value (too big)",
1378 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1382 .str_sec_size = sizeof(""),
1383 .map_type = BPF_MAP_TYPE_ARRAY,
1384 .map_name = "array_map_check_btf",
1385 .key_size = sizeof(int),
1386 /* btf_value_size > map->value_size */
1387 .value_size = sizeof(__u16),
1391 .map_create_err = true,
1395 .descr = "func proto (int (*)(int, unsigned int))",
1397 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1398 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1399 /* int (*)(int, unsigned int) */
1400 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
1401 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1402 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1406 .str_sec_size = sizeof(""),
1407 .map_type = BPF_MAP_TYPE_ARRAY,
1408 .map_name = "func_proto_type_check_btf",
1409 .key_size = sizeof(int),
1410 .value_size = sizeof(int),
1417 .descr = "func proto (vararg)",
1419 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1420 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1421 /* void (*)(int, unsigned int, ...) */
1422 BTF_FUNC_PROTO_ENC(0, 3), /* [3] */
1423 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1424 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1425 BTF_FUNC_PROTO_ARG_ENC(0, 0),
1429 .str_sec_size = sizeof(""),
1430 .map_type = BPF_MAP_TYPE_ARRAY,
1431 .map_name = "func_proto_type_check_btf",
1432 .key_size = sizeof(int),
1433 .value_size = sizeof(int),
1440 .descr = "func proto (vararg with name)",
1442 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1443 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1444 /* void (*)(int a, unsigned int b, ... c) */
1445 BTF_FUNC_PROTO_ENC(0, 3), /* [3] */
1446 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1447 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1448 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 0),
1451 .str_sec = "\0a\0b\0c",
1452 .str_sec_size = sizeof("\0a\0b\0c"),
1453 .map_type = BPF_MAP_TYPE_ARRAY,
1454 .map_name = "func_proto_type_check_btf",
1455 .key_size = sizeof(int),
1456 .value_size = sizeof(int),
1460 .btf_load_err = true,
1461 .err_str = "Invalid arg#3",
1465 .descr = "func proto (arg after vararg)",
1467 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1468 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1469 /* void (*)(int a, ..., unsigned int b) */
1470 BTF_FUNC_PROTO_ENC(0, 3), /* [3] */
1471 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1472 BTF_FUNC_PROTO_ARG_ENC(0, 0),
1473 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1476 .str_sec = "\0a\0b",
1477 .str_sec_size = sizeof("\0a\0b"),
1478 .map_type = BPF_MAP_TYPE_ARRAY,
1479 .map_name = "func_proto_type_check_btf",
1480 .key_size = sizeof(int),
1481 .value_size = sizeof(int),
1485 .btf_load_err = true,
1486 .err_str = "Invalid arg#2",
1490 .descr = "func proto (CONST=>TYPEDEF=>PTR=>FUNC_PROTO)",
1492 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1493 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1494 /* typedef void (*func_ptr)(int, unsigned int) */
1495 BTF_TYPEDEF_ENC(NAME_TBD, 5), /* [3] */
1496 /* const func_ptr */
1497 BTF_CONST_ENC(3), /* [4] */
1498 BTF_PTR_ENC(6), /* [5] */
1499 BTF_FUNC_PROTO_ENC(0, 2), /* [6] */
1500 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1501 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1504 .str_sec = "\0func_ptr",
1505 .str_sec_size = sizeof("\0func_ptr"),
1506 .map_type = BPF_MAP_TYPE_ARRAY,
1507 .map_name = "func_proto_type_check_btf",
1508 .key_size = sizeof(int),
1509 .value_size = sizeof(int),
1516 .descr = "func proto (CONST=>TYPEDEF=>FUNC_PROTO)",
1518 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1519 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1520 BTF_CONST_ENC(4), /* [3] */
1521 BTF_TYPEDEF_ENC(NAME_TBD, 5), /* [4] */
1522 BTF_FUNC_PROTO_ENC(0, 2), /* [5] */
1523 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1524 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1527 .str_sec = "\0func_typedef",
1528 .str_sec_size = sizeof("\0func_typedef"),
1529 .map_type = BPF_MAP_TYPE_ARRAY,
1530 .map_name = "func_proto_type_check_btf",
1531 .key_size = sizeof(int),
1532 .value_size = sizeof(int),
1536 .btf_load_err = true,
1537 .err_str = "Invalid type_id",
1541 .descr = "func proto (btf_resolve(arg))",
1543 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1544 /* void (*)(const void *) */
1545 BTF_FUNC_PROTO_ENC(0, 1), /* [2] */
1546 BTF_FUNC_PROTO_ARG_ENC(0, 3),
1547 BTF_CONST_ENC(4), /* [3] */
1548 BTF_PTR_ENC(0), /* [4] */
1552 .str_sec_size = sizeof(""),
1553 .map_type = BPF_MAP_TYPE_ARRAY,
1554 .map_name = "func_proto_type_check_btf",
1555 .key_size = sizeof(int),
1556 .value_size = sizeof(int),
1563 .descr = "func proto (Not all arg has name)",
1565 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1566 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1567 /* void (*)(int, unsigned int b) */
1568 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1569 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1570 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1574 .str_sec_size = sizeof("\0b"),
1575 .map_type = BPF_MAP_TYPE_ARRAY,
1576 .map_name = "func_proto_type_check_btf",
1577 .key_size = sizeof(int),
1578 .value_size = sizeof(int),
1585 .descr = "func proto (Bad arg name_off)",
1587 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1588 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1589 /* void (*)(int a, unsigned int <bad_name_off>) */
1590 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1591 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1592 BTF_FUNC_PROTO_ARG_ENC(0xffffffff, 2),
1596 .str_sec_size = sizeof("\0a"),
1597 .map_type = BPF_MAP_TYPE_ARRAY,
1598 .map_name = "func_proto_type_check_btf",
1599 .key_size = sizeof(int),
1600 .value_size = sizeof(int),
1604 .btf_load_err = true,
1605 .err_str = "Invalid arg#2",
1609 .descr = "func proto (Bad arg name)",
1611 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1612 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1613 /* void (*)(int a, unsigned int !!!) */
1614 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1615 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1616 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1619 .str_sec = "\0a\0!!!",
1620 .str_sec_size = sizeof("\0a\0!!!"),
1621 .map_type = BPF_MAP_TYPE_ARRAY,
1622 .map_name = "func_proto_type_check_btf",
1623 .key_size = sizeof(int),
1624 .value_size = sizeof(int),
1628 .btf_load_err = true,
1629 .err_str = "Invalid arg#2",
1633 .descr = "func proto (Invalid return type)",
1635 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1636 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1637 /* <bad_ret_type> (*)(int, unsigned int) */
1638 BTF_FUNC_PROTO_ENC(100, 2), /* [3] */
1639 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1640 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1644 .str_sec_size = sizeof(""),
1645 .map_type = BPF_MAP_TYPE_ARRAY,
1646 .map_name = "func_proto_type_check_btf",
1647 .key_size = sizeof(int),
1648 .value_size = sizeof(int),
1652 .btf_load_err = true,
1653 .err_str = "Invalid return type",
1657 .descr = "func proto (with func name)",
1659 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1660 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1661 /* void func_proto(int, unsigned int) */
1662 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC_PROTO, 0, 2), 0), /* [3] */
1663 BTF_FUNC_PROTO_ARG_ENC(0, 1),
1664 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1667 .str_sec = "\0func_proto",
1668 .str_sec_size = sizeof("\0func_proto"),
1669 .map_type = BPF_MAP_TYPE_ARRAY,
1670 .map_name = "func_proto_type_check_btf",
1671 .key_size = sizeof(int),
1672 .value_size = sizeof(int),
1676 .btf_load_err = true,
1677 .err_str = "Invalid name",
1681 .descr = "func proto (const void arg)",
1683 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1684 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1685 /* void (*)(const void) */
1686 BTF_FUNC_PROTO_ENC(0, 1), /* [3] */
1687 BTF_FUNC_PROTO_ARG_ENC(0, 4),
1688 BTF_CONST_ENC(0), /* [4] */
1692 .str_sec_size = sizeof(""),
1693 .map_type = BPF_MAP_TYPE_ARRAY,
1694 .map_name = "func_proto_type_check_btf",
1695 .key_size = sizeof(int),
1696 .value_size = sizeof(int),
1700 .btf_load_err = true,
1701 .err_str = "Invalid arg#1",
1705 .descr = "func (void func(int a, unsigned int b))",
1707 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1708 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1709 /* void (*)(int a, unsigned int b) */
1710 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1711 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1712 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1713 /* void func(int a, unsigned int b) */
1714 BTF_FUNC_ENC(NAME_TBD, 3), /* [4] */
1717 .str_sec = "\0a\0b\0func",
1718 .str_sec_size = sizeof("\0a\0b\0func"),
1719 .map_type = BPF_MAP_TYPE_ARRAY,
1720 .map_name = "func_type_check_btf",
1721 .key_size = sizeof(int),
1722 .value_size = sizeof(int),
1729 .descr = "func (No func name)",
1731 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1732 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1733 /* void (*)(int a, unsigned int b) */
1734 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1735 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1736 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1737 /* void <no_name>(int a, unsigned int b) */
1738 BTF_FUNC_ENC(0, 3), /* [4] */
1741 .str_sec = "\0a\0b",
1742 .str_sec_size = sizeof("\0a\0b"),
1743 .map_type = BPF_MAP_TYPE_ARRAY,
1744 .map_name = "func_type_check_btf",
1745 .key_size = sizeof(int),
1746 .value_size = sizeof(int),
1750 .btf_load_err = true,
1751 .err_str = "Invalid name",
1755 .descr = "func (Invalid func name)",
1757 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1758 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1759 /* void (*)(int a, unsigned int b) */
1760 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1761 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1762 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1763 /* void !!!(int a, unsigned int b) */
1764 BTF_FUNC_ENC(NAME_TBD, 3), /* [4] */
1767 .str_sec = "\0a\0b\0!!!",
1768 .str_sec_size = sizeof("\0a\0b\0!!!"),
1769 .map_type = BPF_MAP_TYPE_ARRAY,
1770 .map_name = "func_type_check_btf",
1771 .key_size = sizeof(int),
1772 .value_size = sizeof(int),
1776 .btf_load_err = true,
1777 .err_str = "Invalid name",
1781 .descr = "func (Some arg has no name)",
1783 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1784 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1785 /* void (*)(int a, unsigned int) */
1786 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1787 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1788 BTF_FUNC_PROTO_ARG_ENC(0, 2),
1789 /* void func(int a, unsigned int) */
1790 BTF_FUNC_ENC(NAME_TBD, 3), /* [4] */
1793 .str_sec = "\0a\0func",
1794 .str_sec_size = sizeof("\0a\0func"),
1795 .map_type = BPF_MAP_TYPE_ARRAY,
1796 .map_name = "func_type_check_btf",
1797 .key_size = sizeof(int),
1798 .value_size = sizeof(int),
1802 .btf_load_err = true,
1803 .err_str = "Invalid arg#2",
1807 .descr = "func (Non zero vlen)",
1809 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1810 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4), /* [2] */
1811 /* void (*)(int a, unsigned int b) */
1812 BTF_FUNC_PROTO_ENC(0, 2), /* [3] */
1813 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
1814 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
1815 /* void func(int a, unsigned int b) */
1816 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_FUNC, 0, 2), 3), /* [4] */
1819 .str_sec = "\0a\0b\0func",
1820 .str_sec_size = sizeof("\0a\0b\0func"),
1821 .map_type = BPF_MAP_TYPE_ARRAY,
1822 .map_name = "func_type_check_btf",
1823 .key_size = sizeof(int),
1824 .value_size = sizeof(int),
1828 .btf_load_err = true,
1829 .err_str = "vlen != 0",
1833 .descr = "func (Not referring to FUNC_PROTO)",
1835 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
1836 BTF_FUNC_ENC(NAME_TBD, 1), /* [2] */
1839 .str_sec = "\0func",
1840 .str_sec_size = sizeof("\0func"),
1841 .map_type = BPF_MAP_TYPE_ARRAY,
1842 .map_name = "func_type_check_btf",
1843 .key_size = sizeof(int),
1844 .value_size = sizeof(int),
1848 .btf_load_err = true,
1849 .err_str = "Invalid type_id",
1852 }; /* struct btf_raw_test raw_tests[] */
1854 static const char *get_next_str(const char *start, const char *end)
1856 return start < end - 1 ? start + 1 : NULL;
1859 static int get_type_sec_size(const __u32 *raw_types)
1863 for (i = MAX_NR_RAW_TYPES - 1;
1864 i >= 0 && raw_types[i] != BTF_END_RAW;
1868 return i < 0 ? i : i * sizeof(raw_types[0]);
1871 static void *btf_raw_create(const struct btf_header *hdr,
1872 const __u32 *raw_types,
1874 unsigned int str_sec_size,
1875 unsigned int *btf_size)
1877 const char *next_str = str, *end_str = str + str_sec_size;
1878 unsigned int size_needed, offset;
1879 struct btf_header *ret_hdr;
1880 int i, type_sec_size;
1881 uint32_t *ret_types;
1884 type_sec_size = get_type_sec_size(raw_types);
1885 if (CHECK(type_sec_size < 0, "Cannot get nr_raw_types"))
1888 size_needed = sizeof(*hdr) + type_sec_size + str_sec_size;
1889 raw_btf = malloc(size_needed);
1890 if (CHECK(!raw_btf, "Cannot allocate memory for raw_btf"))
1894 memcpy(raw_btf, hdr, sizeof(*hdr));
1895 offset = sizeof(*hdr);
1897 /* Copy type section */
1898 ret_types = raw_btf + offset;
1899 for (i = 0; i < type_sec_size / sizeof(raw_types[0]); i++) {
1900 if (raw_types[i] == NAME_TBD) {
1901 next_str = get_next_str(next_str, end_str);
1902 if (CHECK(!next_str, "Error in getting next_str")) {
1906 ret_types[i] = next_str - str;
1907 next_str += strlen(next_str);
1909 ret_types[i] = raw_types[i];
1912 offset += type_sec_size;
1914 /* Copy string section */
1915 memcpy(raw_btf + offset, str, str_sec_size);
1917 ret_hdr = (struct btf_header *)raw_btf;
1918 ret_hdr->type_len = type_sec_size;
1919 ret_hdr->str_off = type_sec_size;
1920 ret_hdr->str_len = str_sec_size;
1922 *btf_size = size_needed;
1927 static int do_test_raw(unsigned int test_num)
1929 struct btf_raw_test *test = &raw_tests[test_num - 1];
1930 struct bpf_create_map_attr create_attr = {};
1931 int map_fd = -1, btf_fd = -1;
1932 unsigned int raw_btf_size;
1933 struct btf_header *hdr;
1937 fprintf(stderr, "BTF raw test[%u] (%s): ", test_num, test->descr);
1938 raw_btf = btf_raw_create(&hdr_tmpl,
1949 hdr->hdr_len = (int)hdr->hdr_len + test->hdr_len_delta;
1950 hdr->type_off = (int)hdr->type_off + test->type_off_delta;
1951 hdr->str_off = (int)hdr->str_off + test->str_off_delta;
1952 hdr->str_len = (int)hdr->str_len + test->str_len_delta;
1954 *btf_log_buf = '\0';
1955 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
1956 btf_log_buf, BTF_LOG_BUF_SIZE,
1960 err = ((btf_fd == -1) != test->btf_load_err);
1961 if (CHECK(err, "btf_fd:%d test->btf_load_err:%u",
1962 btf_fd, test->btf_load_err) ||
1963 CHECK(test->err_str && !strstr(btf_log_buf, test->err_str),
1964 "expected err_str:%s", test->err_str)) {
1969 if (err || btf_fd == -1)
1972 create_attr.name = test->map_name;
1973 create_attr.map_type = test->map_type;
1974 create_attr.key_size = test->key_size;
1975 create_attr.value_size = test->value_size;
1976 create_attr.max_entries = test->max_entries;
1977 create_attr.btf_fd = btf_fd;
1978 create_attr.btf_key_type_id = test->key_type_id;
1979 create_attr.btf_value_type_id = test->value_type_id;
1981 map_fd = bpf_create_map_xattr(&create_attr);
1983 err = ((map_fd == -1) != test->map_create_err);
1984 CHECK(err, "map_fd:%d test->map_create_err:%u",
1985 map_fd, test->map_create_err);
1989 fprintf(stderr, "OK");
1991 if (*btf_log_buf && (err || args.always_log))
1992 fprintf(stderr, "\n%s", btf_log_buf);
2002 static int test_raw(void)
2007 if (args.raw_test_num)
2008 return count_result(do_test_raw(args.raw_test_num));
2010 for (i = 1; i <= ARRAY_SIZE(raw_tests); i++)
2011 err |= count_result(do_test_raw(i));
2016 struct btf_get_info_test {
2018 const char *str_sec;
2019 __u32 raw_types[MAX_NR_RAW_TYPES];
2022 int (*special_test)(unsigned int test_num);
2025 static int test_big_btf_info(unsigned int test_num);
2026 static int test_btf_id(unsigned int test_num);
2028 const struct btf_get_info_test get_info_tests[] = {
2030 .descr = "== raw_btf_size+1",
2033 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
2037 .str_sec_size = sizeof(""),
2038 .btf_size_delta = 1,
2041 .descr = "== raw_btf_size-3",
2044 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
2048 .str_sec_size = sizeof(""),
2049 .btf_size_delta = -3,
2052 .descr = "Large bpf_btf_info",
2055 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
2059 .str_sec_size = sizeof(""),
2060 .special_test = test_big_btf_info,
2066 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
2067 /* unsigned int */ /* [2] */
2068 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),
2072 .str_sec_size = sizeof(""),
2073 .special_test = test_btf_id,
2077 static inline __u64 ptr_to_u64(const void *ptr)
2079 return (__u64)(unsigned long)ptr;
2082 static int test_big_btf_info(unsigned int test_num)
2084 const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
2085 uint8_t *raw_btf = NULL, *user_btf = NULL;
2086 unsigned int raw_btf_size;
2088 struct bpf_btf_info info;
2091 struct bpf_btf_info *info;
2092 int btf_fd = -1, err;
2095 raw_btf = btf_raw_create(&hdr_tmpl,
2104 *btf_log_buf = '\0';
2106 user_btf = malloc(raw_btf_size);
2107 if (CHECK(!user_btf, "!user_btf")) {
2112 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
2113 btf_log_buf, BTF_LOG_BUF_SIZE,
2115 if (CHECK(btf_fd == -1, "errno:%d", errno)) {
2121 * GET_INFO should error out if the userspace info
2122 * has non zero tailing bytes.
2124 info = &info_garbage.info;
2125 memset(info, 0, sizeof(*info));
2126 info_garbage.garbage = 0xdeadbeef;
2127 info_len = sizeof(info_garbage);
2128 info->btf = ptr_to_u64(user_btf);
2129 info->btf_size = raw_btf_size;
2131 err = bpf_obj_get_info_by_fd(btf_fd, info, &info_len);
2132 if (CHECK(!err, "!err")) {
2138 * GET_INFO should succeed even info_len is larger than
2139 * the kernel supported as long as tailing bytes are zero.
2140 * The kernel supported info len should also be returned
2143 info_garbage.garbage = 0;
2144 err = bpf_obj_get_info_by_fd(btf_fd, info, &info_len);
2145 if (CHECK(err || info_len != sizeof(*info),
2146 "err:%d errno:%d info_len:%u sizeof(*info):%lu",
2147 err, errno, info_len, sizeof(*info))) {
2152 fprintf(stderr, "OK");
2155 if (*btf_log_buf && (err || args.always_log))
2156 fprintf(stderr, "\n%s", btf_log_buf);
2167 static int test_btf_id(unsigned int test_num)
2169 const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
2170 struct bpf_create_map_attr create_attr = {};
2171 uint8_t *raw_btf = NULL, *user_btf[2] = {};
2172 int btf_fd[2] = {-1, -1}, map_fd = -1;
2173 struct bpf_map_info map_info = {};
2174 struct bpf_btf_info info[2] = {};
2175 unsigned int raw_btf_size;
2179 raw_btf = btf_raw_create(&hdr_tmpl,
2188 *btf_log_buf = '\0';
2190 for (i = 0; i < 2; i++) {
2191 user_btf[i] = malloc(raw_btf_size);
2192 if (CHECK(!user_btf[i], "!user_btf[%d]", i)) {
2196 info[i].btf = ptr_to_u64(user_btf[i]);
2197 info[i].btf_size = raw_btf_size;
2200 btf_fd[0] = bpf_load_btf(raw_btf, raw_btf_size,
2201 btf_log_buf, BTF_LOG_BUF_SIZE,
2203 if (CHECK(btf_fd[0] == -1, "errno:%d", errno)) {
2208 /* Test BPF_OBJ_GET_INFO_BY_ID on btf_id */
2209 info_len = sizeof(info[0]);
2210 err = bpf_obj_get_info_by_fd(btf_fd[0], &info[0], &info_len);
2211 if (CHECK(err, "errno:%d", errno)) {
2216 btf_fd[1] = bpf_btf_get_fd_by_id(info[0].id);
2217 if (CHECK(btf_fd[1] == -1, "errno:%d", errno)) {
2223 err = bpf_obj_get_info_by_fd(btf_fd[1], &info[1], &info_len);
2224 if (CHECK(err || info[0].id != info[1].id ||
2225 info[0].btf_size != info[1].btf_size ||
2226 (ret = memcmp(user_btf[0], user_btf[1], info[0].btf_size)),
2227 "err:%d errno:%d id0:%u id1:%u btf_size0:%u btf_size1:%u memcmp:%d",
2228 err, errno, info[0].id, info[1].id,
2229 info[0].btf_size, info[1].btf_size, ret)) {
2234 /* Test btf members in struct bpf_map_info */
2235 create_attr.name = "test_btf_id";
2236 create_attr.map_type = BPF_MAP_TYPE_ARRAY;
2237 create_attr.key_size = sizeof(int);
2238 create_attr.value_size = sizeof(unsigned int);
2239 create_attr.max_entries = 4;
2240 create_attr.btf_fd = btf_fd[0];
2241 create_attr.btf_key_type_id = 1;
2242 create_attr.btf_value_type_id = 2;
2244 map_fd = bpf_create_map_xattr(&create_attr);
2245 if (CHECK(map_fd == -1, "errno:%d", errno)) {
2250 info_len = sizeof(map_info);
2251 err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
2252 if (CHECK(err || map_info.btf_id != info[0].id ||
2253 map_info.btf_key_type_id != 1 || map_info.btf_value_type_id != 2,
2254 "err:%d errno:%d info.id:%u btf_id:%u btf_key_type_id:%u btf_value_type_id:%u",
2255 err, errno, info[0].id, map_info.btf_id, map_info.btf_key_type_id,
2256 map_info.btf_value_type_id)) {
2261 for (i = 0; i < 2; i++) {
2266 /* Test BTF ID is removed from the kernel */
2267 btf_fd[0] = bpf_btf_get_fd_by_id(map_info.btf_id);
2268 if (CHECK(btf_fd[0] == -1, "errno:%d", errno)) {
2275 /* The map holds the last ref to BTF and its btf_id */
2278 btf_fd[0] = bpf_btf_get_fd_by_id(map_info.btf_id);
2279 if (CHECK(btf_fd[0] != -1, "BTF lingers")) {
2284 fprintf(stderr, "OK");
2287 if (*btf_log_buf && (err || args.always_log))
2288 fprintf(stderr, "\n%s", btf_log_buf);
2293 for (i = 0; i < 2; i++) {
2295 if (btf_fd[i] != -1)
2302 static int do_test_get_info(unsigned int test_num)
2304 const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
2305 unsigned int raw_btf_size, user_btf_size, expected_nbytes;
2306 uint8_t *raw_btf = NULL, *user_btf = NULL;
2307 struct bpf_btf_info info = {};
2308 int btf_fd = -1, err, ret;
2311 fprintf(stderr, "BTF GET_INFO test[%u] (%s): ",
2312 test_num, test->descr);
2314 if (test->special_test)
2315 return test->special_test(test_num);
2317 raw_btf = btf_raw_create(&hdr_tmpl,
2326 *btf_log_buf = '\0';
2328 user_btf = malloc(raw_btf_size);
2329 if (CHECK(!user_btf, "!user_btf")) {
2334 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
2335 btf_log_buf, BTF_LOG_BUF_SIZE,
2337 if (CHECK(btf_fd == -1, "errno:%d", errno)) {
2342 user_btf_size = (int)raw_btf_size + test->btf_size_delta;
2343 expected_nbytes = min(raw_btf_size, user_btf_size);
2344 if (raw_btf_size > expected_nbytes)
2345 memset(user_btf + expected_nbytes, 0xff,
2346 raw_btf_size - expected_nbytes);
2348 info_len = sizeof(info);
2349 info.btf = ptr_to_u64(user_btf);
2350 info.btf_size = user_btf_size;
2353 err = bpf_obj_get_info_by_fd(btf_fd, &info, &info_len);
2354 if (CHECK(err || !info.id || info_len != sizeof(info) ||
2355 info.btf_size != raw_btf_size ||
2356 (ret = memcmp(raw_btf, user_btf, expected_nbytes)),
2357 "err:%d errno:%d info.id:%u info_len:%u sizeof(info):%lu raw_btf_size:%u info.btf_size:%u expected_nbytes:%u memcmp:%d",
2358 err, errno, info.id, info_len, sizeof(info),
2359 raw_btf_size, info.btf_size, expected_nbytes, ret)) {
2364 while (expected_nbytes < raw_btf_size) {
2365 fprintf(stderr, "%u...", expected_nbytes);
2366 if (CHECK(user_btf[expected_nbytes++] != 0xff,
2367 "user_btf[%u]:%x != 0xff", expected_nbytes - 1,
2368 user_btf[expected_nbytes - 1])) {
2374 fprintf(stderr, "OK");
2377 if (*btf_log_buf && (err || args.always_log))
2378 fprintf(stderr, "\n%s", btf_log_buf);
2389 static int test_get_info(void)
2394 if (args.get_info_test_num)
2395 return count_result(do_test_get_info(args.get_info_test_num));
2397 for (i = 1; i <= ARRAY_SIZE(get_info_tests); i++)
2398 err |= count_result(do_test_get_info(i));
2403 struct btf_file_test {
2405 bool btf_kv_notfound;
2408 static struct btf_file_test file_tests[] = {
2410 .file = "test_btf_haskv.o",
2413 .file = "test_btf_nokv.o",
2414 .btf_kv_notfound = true,
2418 static int file_has_btf_elf(const char *fn, bool *has_btf_ext)
2420 Elf_Scn *scn = NULL;
2426 if (CHECK(elf_version(EV_CURRENT) == EV_NONE,
2427 "elf_version(EV_CURRENT) == EV_NONE"))
2430 elf_fd = open(fn, O_RDONLY);
2431 if (CHECK(elf_fd == -1, "open(%s): errno:%d", fn, errno))
2434 elf = elf_begin(elf_fd, ELF_C_READ, NULL);
2435 if (CHECK(!elf, "elf_begin(%s): %s", fn, elf_errmsg(elf_errno()))) {
2440 if (CHECK(!gelf_getehdr(elf, &ehdr), "!gelf_getehdr(%s)", fn)) {
2445 while ((scn = elf_nextscn(elf, scn))) {
2446 const char *sh_name;
2449 if (CHECK(gelf_getshdr(scn, &sh) != &sh,
2450 "file:%s gelf_getshdr != &sh", fn)) {
2455 sh_name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
2456 if (!strcmp(sh_name, BTF_ELF_SEC))
2458 if (!strcmp(sh_name, BTF_EXT_ELF_SEC))
2459 *has_btf_ext = true;
2468 static int do_test_file(unsigned int test_num)
2470 const struct btf_file_test *test = &file_tests[test_num - 1];
2471 const char *expected_fnames[] = {"_dummy_tracepoint",
2472 "test_long_fname_1",
2473 "test_long_fname_2"};
2474 struct bpf_prog_info info = {};
2475 struct bpf_object *obj = NULL;
2476 struct bpf_func_info *finfo;
2477 struct bpf_program *prog;
2478 __u32 info_len, rec_size;
2479 bool has_btf_ext = false;
2480 struct btf *btf = NULL;
2481 void *func_info = NULL;
2482 struct bpf_map *map;
2483 int i, err, prog_fd;
2485 fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
2488 err = file_has_btf_elf(test->file, &has_btf_ext);
2493 fprintf(stderr, "SKIP. No ELF %s found", BTF_ELF_SEC);
2498 obj = bpf_object__open(test->file);
2499 if (CHECK(IS_ERR(obj), "obj: %ld", PTR_ERR(obj)))
2500 return PTR_ERR(obj);
2502 err = bpf_object__btf_fd(obj);
2503 if (CHECK(err == -1, "bpf_object__btf_fd: -1"))
2506 prog = bpf_program__next(NULL, obj);
2507 if (CHECK(!prog, "Cannot find bpf_prog")) {
2512 bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
2513 err = bpf_object__load(obj);
2514 if (CHECK(err < 0, "bpf_object__load: %d", err))
2516 prog_fd = bpf_program__fd(prog);
2518 map = bpf_object__find_map_by_name(obj, "btf_map");
2519 if (CHECK(!map, "btf_map not found")) {
2524 err = (bpf_map__btf_key_type_id(map) == 0 || bpf_map__btf_value_type_id(map) == 0)
2525 != test->btf_kv_notfound;
2526 if (CHECK(err, "btf_key_type_id:%u btf_value_type_id:%u test->btf_kv_notfound:%u",
2527 bpf_map__btf_key_type_id(map), bpf_map__btf_value_type_id(map),
2528 test->btf_kv_notfound))
2534 /* get necessary program info */
2535 info_len = sizeof(struct bpf_prog_info);
2536 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
2538 if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
2539 fprintf(stderr, "%s\n", btf_log_buf);
2543 if (CHECK(info.func_info_cnt != 3,
2544 "incorrect info.func_info_cnt (1st) %d",
2545 info.func_info_cnt)) {
2549 rec_size = info.func_info_rec_size;
2550 if (CHECK(rec_size < 4,
2551 "incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {
2556 func_info = malloc(info.func_info_cnt * rec_size);
2557 if (CHECK(!func_info, "out of memory")) {
2562 /* reset info to only retrieve func_info related data */
2563 memset(&info, 0, sizeof(info));
2564 info.func_info_cnt = 3;
2565 info.func_info_rec_size = rec_size;
2566 info.func_info = ptr_to_u64(func_info);
2568 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
2570 if (CHECK(err == -1, "invalid get info (2nd) errno:%d", errno)) {
2571 fprintf(stderr, "%s\n", btf_log_buf);
2575 if (CHECK(info.func_info_cnt != 3,
2576 "incorrect info.func_info_cnt (2nd) %d",
2577 info.func_info_cnt)) {
2581 if (CHECK(info.func_info_rec_size != rec_size,
2582 "incorrect info.func_info_rec_size (2nd) %d",
2583 info.func_info_rec_size)) {
2588 err = btf_get_from_id(info.btf_id, &btf);
2589 if (CHECK(err, "cannot get btf from kernel, err: %d", err))
2592 /* check three functions */
2594 for (i = 0; i < 3; i++) {
2595 const struct btf_type *t;
2598 t = btf__type_by_id(btf, finfo->type_id);
2599 if (CHECK(!t, "btf__type_by_id failure: id %u",
2605 fname = btf__name_by_offset(btf, t->name_off);
2606 err = strcmp(fname, expected_fnames[i]);
2607 /* for the second and third functions in .text section,
2608 * the compiler may order them either way.
2611 err = strcmp(fname, expected_fnames[3 - i]);
2612 if (CHECK(err, "incorrect fname %s", fname ? : "")) {
2617 finfo = (void *)finfo + rec_size;
2621 fprintf(stderr, "OK");
2625 bpf_object__close(obj);
2629 static int test_file(void)
2634 if (args.file_test_num)
2635 return count_result(do_test_file(args.file_test_num));
2637 for (i = 1; i <= ARRAY_SIZE(file_tests); i++)
2638 err |= count_result(do_test_file(i));
2643 const char *pprint_enum_str[] = {
2650 struct pprint_mapv {
2655 uint32_t unused_bits2a:2,
2670 static struct btf_raw_test pprint_test_template = {
2672 /* unsighed char */ /* [1] */
2673 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
2674 /* unsigned short */ /* [2] */
2675 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2),
2676 /* unsigned int */ /* [3] */
2677 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),
2679 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
2680 /* unsigned long long */ /* [5] */
2681 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8),
2682 /* 2 bits */ /* [6] */
2683 BTF_TYPE_INT_ENC(0, 0, 0, 2, 2),
2684 /* 28 bits */ /* [7] */
2685 BTF_TYPE_INT_ENC(0, 0, 0, 28, 4),
2686 /* uint8_t[8] */ /* [8] */
2687 BTF_TYPE_ARRAY_ENC(9, 1, 8),
2688 /* typedef unsigned char uint8_t */ /* [9] */
2689 BTF_TYPEDEF_ENC(NAME_TBD, 1),
2690 /* typedef unsigned short uint16_t */ /* [10] */
2691 BTF_TYPEDEF_ENC(NAME_TBD, 2),
2692 /* typedef unsigned int uint32_t */ /* [11] */
2693 BTF_TYPEDEF_ENC(NAME_TBD, 3),
2694 /* typedef int int32_t */ /* [12] */
2695 BTF_TYPEDEF_ENC(NAME_TBD, 4),
2696 /* typedef unsigned long long uint64_t *//* [13] */
2697 BTF_TYPEDEF_ENC(NAME_TBD, 5),
2698 /* union (anon) */ /* [14] */
2699 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 0, 2), 8),
2700 BTF_MEMBER_ENC(NAME_TBD, 13, 0),/* uint64_t ui64; */
2701 BTF_MEMBER_ENC(NAME_TBD, 8, 0), /* uint8_t ui8a[8]; */
2702 /* enum (anon) */ /* [15] */
2703 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 4), 4),
2704 BTF_ENUM_ENC(NAME_TBD, 0),
2705 BTF_ENUM_ENC(NAME_TBD, 1),
2706 BTF_ENUM_ENC(NAME_TBD, 2),
2707 BTF_ENUM_ENC(NAME_TBD, 3),
2708 /* struct pprint_mapv */ /* [16] */
2709 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
2710 BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */
2711 BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */
2712 BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */
2713 BTF_MEMBER_ENC(NAME_TBD, 6, 96), /* unused_bits2a */
2714 BTF_MEMBER_ENC(NAME_TBD, 7, 98), /* bits28 */
2715 BTF_MEMBER_ENC(NAME_TBD, 6, 126), /* unused_bits2b */
2716 BTF_MEMBER_ENC(0, 14, 128), /* union (anon) */
2717 BTF_MEMBER_ENC(NAME_TBD, 15, 192), /* aenum */
2720 .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",
2721 .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"),
2722 .key_size = sizeof(unsigned int),
2723 .value_size = sizeof(struct pprint_mapv),
2724 .key_type_id = 3, /* unsigned int */
2725 .value_type_id = 16, /* struct pprint_mapv */
2726 .max_entries = 128 * 1024,
2729 static struct btf_pprint_test_meta {
2731 enum bpf_map_type map_type;
2732 const char *map_name;
2736 } pprint_tests_meta[] = {
2738 .descr = "BTF pretty print array",
2739 .map_type = BPF_MAP_TYPE_ARRAY,
2740 .map_name = "pprint_test_array",
2741 .ordered_map = true,
2742 .lossless_map = true,
2743 .percpu_map = false,
2747 .descr = "BTF pretty print hash",
2748 .map_type = BPF_MAP_TYPE_HASH,
2749 .map_name = "pprint_test_hash",
2750 .ordered_map = false,
2751 .lossless_map = true,
2752 .percpu_map = false,
2756 .descr = "BTF pretty print lru hash",
2757 .map_type = BPF_MAP_TYPE_LRU_HASH,
2758 .map_name = "pprint_test_lru_hash",
2759 .ordered_map = false,
2760 .lossless_map = false,
2761 .percpu_map = false,
2765 .descr = "BTF pretty print percpu array",
2766 .map_type = BPF_MAP_TYPE_PERCPU_ARRAY,
2767 .map_name = "pprint_test_percpu_array",
2768 .ordered_map = true,
2769 .lossless_map = true,
2774 .descr = "BTF pretty print percpu hash",
2775 .map_type = BPF_MAP_TYPE_PERCPU_HASH,
2776 .map_name = "pprint_test_percpu_hash",
2777 .ordered_map = false,
2778 .lossless_map = true,
2783 .descr = "BTF pretty print lru percpu hash",
2784 .map_type = BPF_MAP_TYPE_LRU_PERCPU_HASH,
2785 .map_name = "pprint_test_lru_percpu_hash",
2786 .ordered_map = false,
2787 .lossless_map = false,
2794 static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
2795 int num_cpus, int rounded_value_size)
2799 for (cpu = 0; cpu < num_cpus; cpu++) {
2802 v->unused_bits2a = 3;
2804 v->unused_bits2b = 3;
2806 v->aenum = i & 0x03;
2807 v = (void *)v + rounded_value_size;
2811 static int check_line(const char *expected_line, int nexpected_line,
2812 int expected_line_len, const char *line)
2814 if (CHECK(nexpected_line == expected_line_len,
2815 "expected_line is too long"))
2818 if (strcmp(expected_line, line)) {
2819 fprintf(stderr, "unexpected pprint output\n");
2820 fprintf(stderr, "expected: %s", expected_line);
2821 fprintf(stderr, " read: %s", line);
2829 static int do_test_pprint(void)
2831 const struct btf_raw_test *test = &pprint_test_template;
2832 struct bpf_create_map_attr create_attr = {};
2833 bool ordered_map, lossless_map, percpu_map;
2834 int err, ret, num_cpus, rounded_value_size;
2835 struct pprint_mapv *mapv = NULL;
2836 unsigned int key, nr_read_elems;
2837 int map_fd = -1, btf_fd = -1;
2838 unsigned int raw_btf_size;
2839 char expected_line[255];
2840 FILE *pin_file = NULL;
2842 size_t line_len = 0;
2847 fprintf(stderr, "%s......", test->descr);
2848 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
2849 test->str_sec, test->str_sec_size,
2855 *btf_log_buf = '\0';
2856 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
2857 btf_log_buf, BTF_LOG_BUF_SIZE,
2861 if (CHECK(btf_fd == -1, "errno:%d", errno)) {
2866 create_attr.name = test->map_name;
2867 create_attr.map_type = test->map_type;
2868 create_attr.key_size = test->key_size;
2869 create_attr.value_size = test->value_size;
2870 create_attr.max_entries = test->max_entries;
2871 create_attr.btf_fd = btf_fd;
2872 create_attr.btf_key_type_id = test->key_type_id;
2873 create_attr.btf_value_type_id = test->value_type_id;
2875 map_fd = bpf_create_map_xattr(&create_attr);
2876 if (CHECK(map_fd == -1, "errno:%d", errno)) {
2881 ret = snprintf(pin_path, sizeof(pin_path), "%s/%s",
2882 "/sys/fs/bpf", test->map_name);
2884 if (CHECK(ret == sizeof(pin_path), "pin_path %s/%s is too long",
2885 "/sys/fs/bpf", test->map_name)) {
2890 err = bpf_obj_pin(map_fd, pin_path);
2891 if (CHECK(err, "bpf_obj_pin(%s): errno:%d.", pin_path, errno))
2894 percpu_map = test->percpu_map;
2895 num_cpus = percpu_map ? bpf_num_possible_cpus() : 1;
2896 rounded_value_size = round_up(sizeof(struct pprint_mapv), 8);
2897 mapv = calloc(num_cpus, rounded_value_size);
2898 if (CHECK(!mapv, "mapv allocation failure")) {
2903 for (key = 0; key < test->max_entries; key++) {
2904 set_pprint_mapv(mapv, key, num_cpus, rounded_value_size);
2905 bpf_map_update_elem(map_fd, &key, mapv, 0);
2908 pin_file = fopen(pin_path, "r");
2909 if (CHECK(!pin_file, "fopen(%s): errno:%d", pin_path, errno)) {
2914 /* Skip lines start with '#' */
2915 while ((nread = getline(&line, &line_len, pin_file)) > 0 &&
2919 if (CHECK(nread <= 0, "Unexpected EOF")) {
2925 ordered_map = test->ordered_map;
2926 lossless_map = test->lossless_map;
2928 struct pprint_mapv *cmapv;
2929 ssize_t nexpected_line;
2930 unsigned int next_key;
2933 next_key = ordered_map ? nr_read_elems : atoi(line);
2934 set_pprint_mapv(mapv, next_key, num_cpus, rounded_value_size);
2937 for (cpu = 0; cpu < num_cpus; cpu++) {
2939 /* for percpu map, the format looks like:
2941 * cpu0: <value_on_cpu0>
2942 * cpu1: <value_on_cpu1>
2944 * cpun: <value_on_cpun>
2947 * let us verify the line containing the key here.
2950 nexpected_line = snprintf(expected_line,
2951 sizeof(expected_line),
2955 err = check_line(expected_line, nexpected_line,
2956 sizeof(expected_line), line);
2961 /* read value@cpu */
2962 nread = getline(&line, &line_len, pin_file);
2967 nexpected_line = snprintf(expected_line, sizeof(expected_line),
2968 "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
2969 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
2970 percpu_map ? "\tcpu" : "",
2971 percpu_map ? cpu : next_key,
2972 cmapv->ui32, cmapv->si32,
2973 cmapv->unused_bits2a,
2975 cmapv->unused_bits2b,
2977 cmapv->ui8a[0], cmapv->ui8a[1],
2978 cmapv->ui8a[2], cmapv->ui8a[3],
2979 cmapv->ui8a[4], cmapv->ui8a[5],
2980 cmapv->ui8a[6], cmapv->ui8a[7],
2981 pprint_enum_str[cmapv->aenum]);
2983 err = check_line(expected_line, nexpected_line,
2984 sizeof(expected_line), line);
2988 cmapv = (void *)cmapv + rounded_value_size;
2992 /* skip the last bracket for the percpu map */
2993 nread = getline(&line, &line_len, pin_file);
2998 nread = getline(&line, &line_len, pin_file);
2999 } while (++nr_read_elems < test->max_entries && nread > 0);
3002 CHECK(nr_read_elems < test->max_entries,
3003 "Unexpected EOF. nr_read_elems:%u test->max_entries:%u",
3004 nr_read_elems, test->max_entries)) {
3009 if (CHECK(nread > 0, "Unexpected extra pprint output: %s", line)) {
3020 fprintf(stderr, "OK");
3021 if (*btf_log_buf && (err || args.always_log))
3022 fprintf(stderr, "\n%s", btf_log_buf);
3035 static int test_pprint(void)
3040 for (i = 0; i < ARRAY_SIZE(pprint_tests_meta); i++) {
3041 pprint_test_template.descr = pprint_tests_meta[i].descr;
3042 pprint_test_template.map_type = pprint_tests_meta[i].map_type;
3043 pprint_test_template.map_name = pprint_tests_meta[i].map_name;
3044 pprint_test_template.ordered_map = pprint_tests_meta[i].ordered_map;
3045 pprint_test_template.lossless_map = pprint_tests_meta[i].lossless_map;
3046 pprint_test_template.percpu_map = pprint_tests_meta[i].percpu_map;
3048 err |= count_result(do_test_pprint());
3054 static struct btf_func_type_test {
3056 const char *str_sec;
3057 __u32 raw_types[MAX_NR_RAW_TYPES];
3059 struct bpf_insn insns[MAX_INSNS];
3061 __u32 func_info[MAX_SUBPROGS][2];
3062 __u32 func_info_rec_size;
3063 __u32 func_info_cnt;
3064 bool expected_prog_load_failure;
3065 } func_type_test[] = {
3067 .descr = "func_type (main func + one sub)",
3069 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3070 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3071 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3072 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3073 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3074 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3075 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3076 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3077 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3078 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3081 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3082 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3084 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3085 BPF_MOV64_IMM(BPF_REG_0, 1),
3087 BPF_MOV64_IMM(BPF_REG_0, 2),
3090 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3091 .func_info = { {0, 5}, {3, 6} },
3092 .func_info_rec_size = 8,
3097 .descr = "func_type (Incorrect func_info_rec_size)",
3099 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3100 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3101 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3102 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3103 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3104 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3105 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3106 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3107 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3108 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3111 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3112 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3114 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3115 BPF_MOV64_IMM(BPF_REG_0, 1),
3117 BPF_MOV64_IMM(BPF_REG_0, 2),
3120 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3121 .func_info = { {0, 5}, {3, 6} },
3122 .func_info_rec_size = 4,
3124 .expected_prog_load_failure = true,
3128 .descr = "func_type (Incorrect func_info_cnt)",
3130 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3131 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3132 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3133 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3134 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3135 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3136 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3137 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3138 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3139 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3142 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3143 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3145 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3146 BPF_MOV64_IMM(BPF_REG_0, 1),
3148 BPF_MOV64_IMM(BPF_REG_0, 2),
3151 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3152 .func_info = { {0, 5}, {3, 6} },
3153 .func_info_rec_size = 8,
3155 .expected_prog_load_failure = true,
3159 .descr = "func_type (Incorrect bpf_func_info.insn_offset)",
3161 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4), /* [1] */
3162 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4), /* [2] */
3163 BTF_FUNC_PROTO_ENC(1, 2), /* [3] */
3164 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3165 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3166 BTF_FUNC_PROTO_ENC(1, 2), /* [4] */
3167 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 2),
3168 BTF_FUNC_PROTO_ARG_ENC(NAME_TBD, 1),
3169 BTF_FUNC_ENC(NAME_TBD, 3), /* [5] */
3170 BTF_FUNC_ENC(NAME_TBD, 4), /* [6] */
3173 .str_sec = "\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB",
3174 .str_sec_size = sizeof("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB"),
3176 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
3177 BPF_MOV64_IMM(BPF_REG_0, 1),
3179 BPF_MOV64_IMM(BPF_REG_0, 2),
3182 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
3183 .func_info = { {0, 5}, {2, 6} },
3184 .func_info_rec_size = 8,
3186 .expected_prog_load_failure = true,
3191 static size_t probe_prog_length(const struct bpf_insn *fp)
3195 for (len = MAX_INSNS - 1; len > 0; --len)
3196 if (fp[len].code != 0 || fp[len].imm != 0)
3201 static int do_test_func_type(int test_num)
3203 const struct btf_func_type_test *test = &func_type_test[test_num];
3204 unsigned int raw_btf_size, info_len, rec_size;
3205 int i, btf_fd = -1, prog_fd = -1, err = 0;
3206 struct bpf_load_program_attr attr = {};
3207 void *raw_btf, *func_info = NULL;
3208 struct bpf_prog_info info = {};
3209 struct bpf_func_info *finfo;
3211 fprintf(stderr, "%s......", test->descr);
3212 raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
3213 test->str_sec, test->str_sec_size,
3219 *btf_log_buf = '\0';
3220 btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
3221 btf_log_buf, BTF_LOG_BUF_SIZE,
3225 if (CHECK(btf_fd == -1, "invalid btf_fd errno:%d", errno)) {
3230 if (*btf_log_buf && args.always_log)
3231 fprintf(stderr, "\n%s", btf_log_buf);
3233 attr.prog_type = test->prog_type;
3234 attr.insns = test->insns;
3235 attr.insns_cnt = probe_prog_length(attr.insns);
3236 attr.license = "GPL";
3237 attr.prog_btf_fd = btf_fd;
3238 attr.func_info_rec_size = test->func_info_rec_size;
3239 attr.func_info_cnt = test->func_info_cnt;
3240 attr.func_info = test->func_info;
3242 *btf_log_buf = '\0';
3243 prog_fd = bpf_load_program_xattr(&attr, btf_log_buf,
3245 if (test->expected_prog_load_failure && prog_fd == -1) {
3249 if (CHECK(prog_fd == -1, "invalid prog_id errno:%d", errno)) {
3250 fprintf(stderr, "%s\n", btf_log_buf);
3255 /* get necessary lens */
3256 info_len = sizeof(struct bpf_prog_info);
3257 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3258 if (CHECK(err == -1, "invalid get info (1st) errno:%d", errno)) {
3259 fprintf(stderr, "%s\n", btf_log_buf);
3263 if (CHECK(info.func_info_cnt != 2,
3264 "incorrect info.func_info_cnt (1st) %d\n",
3265 info.func_info_cnt)) {
3269 rec_size = info.func_info_rec_size;
3270 if (CHECK(rec_size < 4,
3271 "incorrect info.func_info_rec_size (1st) %d\n", rec_size)) {
3276 func_info = malloc(info.func_info_cnt * rec_size);
3277 if (CHECK(!func_info, "out of memory")) {
3282 /* reset info to only retrieve func_info related data */
3283 memset(&info, 0, sizeof(info));
3284 info.func_info_cnt = 2;
3285 info.func_info_rec_size = rec_size;
3286 info.func_info = ptr_to_u64(func_info);
3287 err = bpf_obj_get_info_by_fd(prog_fd, &info, &info_len);
3288 if (CHECK(err == -1, "invalid get info (2nd) errno:%d", errno)) {
3289 fprintf(stderr, "%s\n", btf_log_buf);
3293 if (CHECK(info.func_info_cnt != 2,
3294 "incorrect info.func_info_cnt (2nd) %d\n",
3295 info.func_info_cnt)) {
3299 if (CHECK(info.func_info_rec_size != rec_size,
3300 "incorrect info.func_info_rec_size (2nd) %d\n",
3301 info.func_info_rec_size)) {
3307 for (i = 0; i < 2; i++) {
3308 if (CHECK(finfo->type_id != test->func_info[i][1],
3309 "incorrect func_type %u expected %u",
3310 finfo->type_id, test->func_info[i][1])) {
3314 finfo = (void *)finfo + rec_size;
3318 if (*btf_log_buf && (err || args.always_log))
3319 fprintf(stderr, "\n%s", btf_log_buf);
3329 static int test_func_type(void)
3334 for (i = 0; i < ARRAY_SIZE(func_type_test); i++)
3335 err |= count_result(do_test_func_type(i));
3340 static void usage(const char *cmd)
3342 fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] |"
3343 " [-g test_num (1 - %zu)] |"
3344 " [-f test_num (1 - %zu)] | [-p] | [-k] ]\n",
3345 cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),
3346 ARRAY_SIZE(file_tests));
3349 static int parse_args(int argc, char **argv)
3351 const char *optstr = "lpkf:r:g:";
3354 while ((opt = getopt(argc, argv, optstr)) != -1) {
3357 args.always_log = true;
3360 args.file_test_num = atoi(optarg);
3361 args.file_test = true;
3364 args.raw_test_num = atoi(optarg);
3365 args.raw_test = true;
3368 args.get_info_test_num = atoi(optarg);
3369 args.get_info_test = true;
3372 args.pprint_test = true;
3375 args.func_type_test = true;
3386 if (args.raw_test_num &&
3387 (args.raw_test_num < 1 ||
3388 args.raw_test_num > ARRAY_SIZE(raw_tests))) {
3389 fprintf(stderr, "BTF raw test number must be [1 - %zu]\n",
3390 ARRAY_SIZE(raw_tests));
3394 if (args.file_test_num &&
3395 (args.file_test_num < 1 ||
3396 args.file_test_num > ARRAY_SIZE(file_tests))) {
3397 fprintf(stderr, "BTF file test number must be [1 - %zu]\n",
3398 ARRAY_SIZE(file_tests));
3402 if (args.get_info_test_num &&
3403 (args.get_info_test_num < 1 ||
3404 args.get_info_test_num > ARRAY_SIZE(get_info_tests))) {
3405 fprintf(stderr, "BTF get info test number must be [1 - %zu]\n",
3406 ARRAY_SIZE(get_info_tests));
3413 static void print_summary(void)
3415 fprintf(stderr, "PASS:%u SKIP:%u FAIL:%u\n",
3416 pass_cnt - skip_cnt, skip_cnt, error_cnt);
3419 int main(int argc, char **argv)
3423 err = parse_args(argc, argv);
3427 if (args.always_log)
3428 libbpf_set_print(__base_pr, __base_pr, __base_pr);
3433 if (args.get_info_test)
3434 err |= test_get_info();
3439 if (args.pprint_test)
3440 err |= test_pprint();
3442 if (args.func_type_test)
3443 err |= test_func_type();
3445 if (args.raw_test || args.get_info_test || args.file_test ||
3446 args.pprint_test || args.func_type_test)
3450 err |= test_get_info();