Merge tag 'vfio-v4.20-rc1.v2' of git://github.com/awilliam/linux-vfio
[linux-2.6-block.git] / 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 <linux/kernel.h>
8 #include <bpf/bpf.h>
9 #include <sys/resource.h>
10 #include <libelf.h>
11 #include <gelf.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <stdarg.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 #include <bpf/libbpf.h>
20 #include <bpf/btf.h>
21
22 #include "bpf_rlimit.h"
23 #include "bpf_util.h"
24
25 static uint32_t pass_cnt;
26 static uint32_t error_cnt;
27 static uint32_t skip_cnt;
28
29 #define CHECK(condition, format...) ({                                  \
30         int __ret = !!(condition);                                      \
31         if (__ret) {                                                    \
32                 fprintf(stderr, "%s:%d:FAIL ", __func__, __LINE__);     \
33                 fprintf(stderr, format);                                \
34         }                                                               \
35         __ret;                                                          \
36 })
37
38 static int count_result(int err)
39 {
40         if (err)
41                 error_cnt++;
42         else
43                 pass_cnt++;
44
45         fprintf(stderr, "\n");
46         return err;
47 }
48
49 #define __printf(a, b)  __attribute__((format(printf, a, b)))
50
51 __printf(1, 2)
52 static int __base_pr(const char *format, ...)
53 {
54         va_list args;
55         int err;
56
57         va_start(args, format);
58         err = vfprintf(stderr, format, args);
59         va_end(args);
60         return err;
61 }
62
63 #define BTF_INFO_ENC(kind, root, vlen)                  \
64         ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
65
66 #define BTF_TYPE_ENC(name, info, size_or_type)  \
67         (name), (info), (size_or_type)
68
69 #define BTF_INT_ENC(encoding, bits_offset, nr_bits)     \
70         ((encoding) << 24 | (bits_offset) << 16 | (nr_bits))
71 #define BTF_TYPE_INT_ENC(name, encoding, bits_offset, bits, sz) \
72         BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), sz),       \
73         BTF_INT_ENC(encoding, bits_offset, bits)
74
75 #define BTF_ARRAY_ENC(type, index_type, nr_elems)       \
76         (type), (index_type), (nr_elems)
77 #define BTF_TYPE_ARRAY_ENC(type, index_type, nr_elems) \
78         BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 0), \
79         BTF_ARRAY_ENC(type, index_type, nr_elems)
80
81 #define BTF_MEMBER_ENC(name, type, bits_offset) \
82         (name), (type), (bits_offset)
83 #define BTF_ENUM_ENC(name, val) (name), (val)
84
85 #define BTF_TYPEDEF_ENC(name, type) \
86         BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), type)
87
88 #define BTF_PTR_ENC(name, type) \
89         BTF_TYPE_ENC(name, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), type)
90
91 #define BTF_END_RAW 0xdeadbeef
92 #define NAME_TBD 0xdeadb33f
93
94 #define MAX_NR_RAW_TYPES 1024
95 #define BTF_LOG_BUF_SIZE 65535
96
97 static struct args {
98         unsigned int raw_test_num;
99         unsigned int file_test_num;
100         unsigned int get_info_test_num;
101         bool raw_test;
102         bool file_test;
103         bool get_info_test;
104         bool pprint_test;
105         bool always_log;
106 } args;
107
108 static char btf_log_buf[BTF_LOG_BUF_SIZE];
109
110 static struct btf_header hdr_tmpl = {
111         .magic = BTF_MAGIC,
112         .version = BTF_VERSION,
113         .hdr_len = sizeof(struct btf_header),
114 };
115
116 struct btf_raw_test {
117         const char *descr;
118         const char *str_sec;
119         const char *map_name;
120         const char *err_str;
121         __u32 raw_types[MAX_NR_RAW_TYPES];
122         __u32 str_sec_size;
123         enum bpf_map_type map_type;
124         __u32 key_size;
125         __u32 value_size;
126         __u32 key_type_id;
127         __u32 value_type_id;
128         __u32 max_entries;
129         bool btf_load_err;
130         bool map_create_err;
131         bool ordered_map;
132         bool lossless_map;
133         bool percpu_map;
134         int hdr_len_delta;
135         int type_off_delta;
136         int str_off_delta;
137         int str_len_delta;
138 };
139
140 static struct btf_raw_test raw_tests[] = {
141 /* enum E {
142  *     E0,
143  *     E1,
144  * };
145  *
146  * struct A {
147  *      unsigned long long m;
148  *      int n;
149  *      char o;
150  *      [3 bytes hole]
151  *      int p[8];
152  *      int q[4][8];
153  *      enum E r;
154  * };
155  */
156 {
157         .descr = "struct test #1",
158         .raw_types = {
159                 /* int */
160                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
161                 /* unsigned long long */
162                 BTF_TYPE_INT_ENC(0, 0, 0, 64, 8),               /* [2] */
163                 /* char */
164                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 8, 1),   /* [3] */
165                 /* int[8] */
166                 BTF_TYPE_ARRAY_ENC(1, 1, 8),                    /* [4] */
167                 /* struct A { */                                /* [5] */
168                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 6), 180),
169                 BTF_MEMBER_ENC(NAME_TBD, 2, 0), /* unsigned long long m;*/
170                 BTF_MEMBER_ENC(NAME_TBD, 1, 64),/* int n;               */
171                 BTF_MEMBER_ENC(NAME_TBD, 3, 96),/* char o;              */
172                 BTF_MEMBER_ENC(NAME_TBD, 4, 128),/* int p[8]            */
173                 BTF_MEMBER_ENC(NAME_TBD, 6, 384),/* int q[4][8]         */
174                 BTF_MEMBER_ENC(NAME_TBD, 7, 1408), /* enum E r          */
175                 /* } */
176                 /* int[4][8] */
177                 BTF_TYPE_ARRAY_ENC(4, 1, 4),                    /* [6] */
178                 /* enum E */                                    /* [7] */
179                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)),
180                 BTF_ENUM_ENC(NAME_TBD, 0),
181                 BTF_ENUM_ENC(NAME_TBD, 1),
182                 BTF_END_RAW,
183         },
184         .str_sec = "\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1",
185         .str_sec_size = sizeof("\0A\0m\0n\0o\0p\0q\0r\0E\0E0\0E1"),
186         .map_type = BPF_MAP_TYPE_ARRAY,
187         .map_name = "struct_test1_map",
188         .key_size = sizeof(int),
189         .value_size = 180,
190         .key_type_id = 1,
191         .value_type_id = 5,
192         .max_entries = 4,
193 },
194
195 /* typedef struct b Struct_B;
196  *
197  * struct A {
198  *     int m;
199  *     struct b n[4];
200  *     const Struct_B o[4];
201  * };
202  *
203  * struct B {
204  *     int m;
205  *     int n;
206  * };
207  */
208 {
209         .descr = "struct test #2",
210         .raw_types = {
211                 /* int */                                       /* [1] */
212                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
213                 /* struct b [4] */                              /* [2] */
214                 BTF_TYPE_ARRAY_ENC(4, 1, 4),
215
216                 /* struct A { */                                /* [3] */
217                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 3), 68),
218                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m;               */
219                 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct B n[4]        */
220                 BTF_MEMBER_ENC(NAME_TBD, 8, 288),/* const Struct_B o[4];*/
221                 /* } */
222
223                 /* struct B { */                                /* [4] */
224                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
225                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
226                 BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */
227                 /* } */
228
229                 /* const int */                                 /* [5] */
230                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),
231                 /* typedef struct b Struct_B */ /* [6] */
232                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_TYPEDEF, 0, 0), 4),
233                 /* const Struct_B */                            /* [7] */
234                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 6),
235                 /* const Struct_B [4] */                        /* [8] */
236                 BTF_TYPE_ARRAY_ENC(7, 1, 4),
237                 BTF_END_RAW,
238         },
239         .str_sec = "\0A\0m\0n\0o\0B\0m\0n\0Struct_B",
240         .str_sec_size = sizeof("\0A\0m\0n\0o\0B\0m\0n\0Struct_B"),
241         .map_type = BPF_MAP_TYPE_ARRAY,
242         .map_name = "struct_test2_map",
243         .key_size = sizeof(int),
244         .value_size = 68,
245         .key_type_id = 1,
246         .value_type_id = 3,
247         .max_entries = 4,
248 },
249
250 {
251         .descr = "struct test #3 Invalid member offset",
252         .raw_types = {
253                 /* int */                                       /* [1] */
254                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
255                 /* int64 */                                     /* [2] */
256                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 64, 8),
257
258                 /* struct A { */                                /* [3] */
259                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 16),
260                 BTF_MEMBER_ENC(NAME_TBD, 1, 64),        /* int m;               */
261                 BTF_MEMBER_ENC(NAME_TBD, 2, 0),         /* int64 n; */
262                 /* } */
263                 BTF_END_RAW,
264         },
265         .str_sec = "\0A\0m\0n\0",
266         .str_sec_size = sizeof("\0A\0m\0n\0"),
267         .map_type = BPF_MAP_TYPE_ARRAY,
268         .map_name = "struct_test3_map",
269         .key_size = sizeof(int),
270         .value_size = 16,
271         .key_type_id = 1,
272         .value_type_id = 3,
273         .max_entries = 4,
274         .btf_load_err = true,
275         .err_str = "Invalid member bits_offset",
276 },
277
278 /* Test member exceeds the size of struct.
279  *
280  * struct A {
281  *     int m;
282  *     int n;
283  * };
284  */
285 {
286         .descr = "size check test #1",
287         .raw_types = {
288                 /* int */                                       /* [1] */
289                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
290                 /* struct A { */                                /* [2] */
291                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 -  1),
292                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
293                 BTF_MEMBER_ENC(NAME_TBD, 1, 32),/* int n; */
294                 /* } */
295                 BTF_END_RAW,
296         },
297         .str_sec = "\0A\0m\0n",
298         .str_sec_size = sizeof("\0A\0m\0n"),
299         .map_type = BPF_MAP_TYPE_ARRAY,
300         .map_name = "size_check1_map",
301         .key_size = sizeof(int),
302         .value_size = 1,
303         .key_type_id = 1,
304         .value_type_id = 2,
305         .max_entries = 4,
306         .btf_load_err = true,
307         .err_str = "Member exceeds struct_size",
308 },
309
310 /* Test member exeeds the size of struct
311  *
312  * struct A {
313  *     int m;
314  *     int n[2];
315  * };
316  */
317 {
318         .descr = "size check test #2",
319         .raw_types = {
320                 /* int */                                       /* [1] */
321                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
322                 /* int[2] */                                    /* [2] */
323                 BTF_TYPE_ARRAY_ENC(1, 1, 2),
324                 /* struct A { */                                /* [3] */
325                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 3 - 1),
326                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
327                 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* int n[2]; */
328                 /* } */
329                 BTF_END_RAW,
330         },
331         .str_sec = "\0A\0m\0n",
332         .str_sec_size = sizeof("\0A\0m\0n"),
333         .map_type = BPF_MAP_TYPE_ARRAY,
334         .map_name = "size_check2_map",
335         .key_size = sizeof(int),
336         .value_size = 1,
337         .key_type_id = 1,
338         .value_type_id = 3,
339         .max_entries = 4,
340         .btf_load_err = true,
341         .err_str = "Member exceeds struct_size",
342 },
343
344 /* Test member exeeds the size of struct
345  *
346  * struct A {
347  *     int m;
348  *     void *n;
349  * };
350  */
351 {
352         .descr = "size check test #3",
353         .raw_types = {
354                 /* int */                                       /* [1] */
355                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
356                 /* void* */                                     /* [2] */
357                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
358                 /* struct A { */                                /* [3] */
359                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) + sizeof(void *) - 1),
360                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
361                 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* void *n; */
362                 /* } */
363                 BTF_END_RAW,
364         },
365         .str_sec = "\0A\0m\0n",
366         .str_sec_size = sizeof("\0A\0m\0n"),
367         .map_type = BPF_MAP_TYPE_ARRAY,
368         .map_name = "size_check3_map",
369         .key_size = sizeof(int),
370         .value_size = 1,
371         .key_type_id = 1,
372         .value_type_id = 3,
373         .max_entries = 4,
374         .btf_load_err = true,
375         .err_str = "Member exceeds struct_size",
376 },
377
378 /* Test member exceeds the size of struct
379  *
380  * enum E {
381  *     E0,
382  *     E1,
383  * };
384  *
385  * struct A {
386  *     int m;
387  *     enum E n;
388  * };
389  */
390 {
391         .descr = "size check test #4",
392         .raw_types = {
393                 /* int */                       /* [1] */
394                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, sizeof(int)),
395                 /* enum E { */                  /* [2] */
396                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 2), sizeof(int)),
397                 BTF_ENUM_ENC(NAME_TBD, 0),
398                 BTF_ENUM_ENC(NAME_TBD, 1),
399                 /* } */
400                 /* struct A { */                /* [3] */
401                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), sizeof(int) * 2 - 1),
402                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int m; */
403                 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* enum E n; */
404                 /* } */
405                 BTF_END_RAW,
406         },
407         .str_sec = "\0E\0E0\0E1\0A\0m\0n",
408         .str_sec_size = sizeof("\0E\0E0\0E1\0A\0m\0n"),
409         .map_type = BPF_MAP_TYPE_ARRAY,
410         .map_name = "size_check4_map",
411         .key_size = sizeof(int),
412         .value_size = 1,
413         .key_type_id = 1,
414         .value_type_id = 3,
415         .max_entries = 4,
416         .btf_load_err = true,
417         .err_str = "Member exceeds struct_size",
418 },
419
420 /* typedef const void * const_void_ptr;
421  * struct A {
422  *      const_void_ptr m;
423  * };
424  */
425 {
426         .descr = "void test #1",
427         .raw_types = {
428                 /* int */               /* [1] */
429                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
430                 /* const void */        /* [2] */
431                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
432                 /* const void* */       /* [3] */
433                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
434                 /* typedef const void * const_void_ptr */
435                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
436                 /* struct A { */        /* [4] */
437                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
438                 /* const_void_ptr m; */
439                 BTF_MEMBER_ENC(NAME_TBD, 3, 0),
440                 /* } */
441                 BTF_END_RAW,
442         },
443         .str_sec = "\0const_void_ptr\0A\0m",
444         .str_sec_size = sizeof("\0const_void_ptr\0A\0m"),
445         .map_type = BPF_MAP_TYPE_ARRAY,
446         .map_name = "void_test1_map",
447         .key_size = sizeof(int),
448         .value_size = sizeof(void *),
449         .key_type_id = 1,
450         .value_type_id = 4,
451         .max_entries = 4,
452 },
453
454 /* struct A {
455  *     const void m;
456  * };
457  */
458 {
459         .descr = "void test #2",
460         .raw_types = {
461                 /* int */               /* [1] */
462                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
463                 /* const void */        /* [2] */
464                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
465                 /* struct A { */        /* [3] */
466                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), 8),
467                 /* const void m; */
468                 BTF_MEMBER_ENC(NAME_TBD, 2, 0),
469                 /* } */
470                 BTF_END_RAW,
471         },
472         .str_sec = "\0A\0m",
473         .str_sec_size = sizeof("\0A\0m"),
474         .map_type = BPF_MAP_TYPE_ARRAY,
475         .map_name = "void_test2_map",
476         .key_size = sizeof(int),
477         .value_size = sizeof(void *),
478         .key_type_id = 1,
479         .value_type_id = 3,
480         .max_entries = 4,
481         .btf_load_err = true,
482         .err_str = "Invalid member",
483 },
484
485 /* typedef const void * const_void_ptr;
486  * const_void_ptr[4]
487  */
488 {
489         .descr = "void test #3",
490         .raw_types = {
491                 /* int */               /* [1] */
492                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
493                 /* const void */        /* [2] */
494                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
495                 /* const void* */       /* [3] */
496                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 2),
497                 /* typedef const void * const_void_ptr */       /* [4] */
498                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
499                 /* const_void_ptr[4] */ /* [5] */
500                 BTF_TYPE_ARRAY_ENC(3, 1, 4),
501                 BTF_END_RAW,
502         },
503         .str_sec = "\0const_void_ptr",
504         .str_sec_size = sizeof("\0const_void_ptr"),
505         .map_type = BPF_MAP_TYPE_ARRAY,
506         .map_name = "void_test3_map",
507         .key_size = sizeof(int),
508         .value_size = sizeof(void *) * 4,
509         .key_type_id = 1,
510         .value_type_id = 5,
511         .max_entries = 4,
512 },
513
514 /* const void[4]  */
515 {
516         .descr = "void test #4",
517         .raw_types = {
518                 /* int */               /* [1] */
519                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
520                 /* const void */        /* [2] */
521                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
522                 /* const void[4] */     /* [3] */
523                 BTF_TYPE_ARRAY_ENC(2, 1, 4),
524                 BTF_END_RAW,
525         },
526         .str_sec = "\0A\0m",
527         .str_sec_size = sizeof("\0A\0m"),
528         .map_type = BPF_MAP_TYPE_ARRAY,
529         .map_name = "void_test4_map",
530         .key_size = sizeof(int),
531         .value_size = sizeof(void *) * 4,
532         .key_type_id = 1,
533         .value_type_id = 3,
534         .max_entries = 4,
535         .btf_load_err = true,
536         .err_str = "Invalid elem",
537 },
538
539 /* Array_A  <------------------+
540  *     elem_type == Array_B    |
541  *                    |        |
542  *                    |        |
543  * Array_B  <-------- +        |
544  *      elem_type == Array A --+
545  */
546 {
547         .descr = "loop test #1",
548         .raw_types = {
549                 /* int */                       /* [1] */
550                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
551                 /* Array_A */                   /* [2] */
552                 BTF_TYPE_ARRAY_ENC(3, 1, 8),
553                 /* Array_B */                   /* [3] */
554                 BTF_TYPE_ARRAY_ENC(2, 1, 8),
555                 BTF_END_RAW,
556         },
557         .str_sec = "",
558         .str_sec_size = sizeof(""),
559         .map_type = BPF_MAP_TYPE_ARRAY,
560         .map_name = "loop_test1_map",
561         .key_size = sizeof(int),
562         .value_size = sizeof(sizeof(int) * 8),
563         .key_type_id = 1,
564         .value_type_id = 2,
565         .max_entries = 4,
566         .btf_load_err = true,
567         .err_str = "Loop detected",
568 },
569
570 /* typedef is _before_ the BTF type of Array_A and Array_B
571  *
572  * typedef Array_B int_array;
573  *
574  * Array_A  <------------------+
575  *     elem_type == int_array  |
576  *                    |        |
577  *                    |        |
578  * Array_B  <-------- +        |
579  *      elem_type == Array_A --+
580  */
581 {
582         .descr = "loop test #2",
583         .raw_types = {
584                 /* int */
585                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
586                 /* typedef Array_B int_array */
587                 BTF_TYPEDEF_ENC(1, 4),                          /* [2] */
588                 /* Array_A */
589                 BTF_TYPE_ARRAY_ENC(2, 1, 8),                    /* [3] */
590                 /* Array_B */
591                 BTF_TYPE_ARRAY_ENC(3, 1, 8),                    /* [4] */
592                 BTF_END_RAW,
593         },
594         .str_sec = "\0int_array\0",
595         .str_sec_size = sizeof("\0int_array"),
596         .map_type = BPF_MAP_TYPE_ARRAY,
597         .map_name = "loop_test2_map",
598         .key_size = sizeof(int),
599         .value_size = sizeof(sizeof(int) * 8),
600         .key_type_id = 1,
601         .value_type_id = 2,
602         .max_entries = 4,
603         .btf_load_err = true,
604         .err_str = "Loop detected",
605 },
606
607 /* Array_A  <------------------+
608  *     elem_type == Array_B    |
609  *                    |        |
610  *                    |        |
611  * Array_B  <-------- +        |
612  *      elem_type == Array_A --+
613  */
614 {
615         .descr = "loop test #3",
616         .raw_types = {
617                 /* int */                               /* [1] */
618                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
619                 /* Array_A */                           /* [2] */
620                 BTF_TYPE_ARRAY_ENC(3, 1, 8),
621                 /* Array_B */                           /* [3] */
622                 BTF_TYPE_ARRAY_ENC(2, 1, 8),
623                 BTF_END_RAW,
624         },
625         .str_sec = "",
626         .str_sec_size = sizeof(""),
627         .map_type = BPF_MAP_TYPE_ARRAY,
628         .map_name = "loop_test3_map",
629         .key_size = sizeof(int),
630         .value_size = sizeof(sizeof(int) * 8),
631         .key_type_id = 1,
632         .value_type_id = 2,
633         .max_entries = 4,
634         .btf_load_err = true,
635         .err_str = "Loop detected",
636 },
637
638 /* typedef is _between_ the BTF type of Array_A and Array_B
639  *
640  * typedef Array_B int_array;
641  *
642  * Array_A  <------------------+
643  *     elem_type == int_array  |
644  *                    |        |
645  *                    |        |
646  * Array_B  <-------- +        |
647  *      elem_type == Array_A --+
648  */
649 {
650         .descr = "loop test #4",
651         .raw_types = {
652                 /* int */                               /* [1] */
653                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
654                 /* Array_A */                           /* [2] */
655                 BTF_TYPE_ARRAY_ENC(3, 1, 8),
656                 /* typedef Array_B int_array */         /* [3] */
657                 BTF_TYPEDEF_ENC(NAME_TBD, 4),
658                 /* Array_B */                           /* [4] */
659                 BTF_TYPE_ARRAY_ENC(2, 1, 8),
660                 BTF_END_RAW,
661         },
662         .str_sec = "\0int_array\0",
663         .str_sec_size = sizeof("\0int_array"),
664         .map_type = BPF_MAP_TYPE_ARRAY,
665         .map_name = "loop_test4_map",
666         .key_size = sizeof(int),
667         .value_size = sizeof(sizeof(int) * 8),
668         .key_type_id = 1,
669         .value_type_id = 2,
670         .max_entries = 4,
671         .btf_load_err = true,
672         .err_str = "Loop detected",
673 },
674
675 /* typedef struct B Struct_B
676  *
677  * struct A {
678  *     int x;
679  *     Struct_B y;
680  * };
681  *
682  * struct B {
683  *     int x;
684  *     struct A y;
685  * };
686  */
687 {
688         .descr = "loop test #5",
689         .raw_types = {
690                 /* int */
691                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
692                 /* struct A */                                  /* [2] */
693                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
694                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x;       */
695                 BTF_MEMBER_ENC(NAME_TBD, 3, 32),/* Struct_B y;  */
696                 /* typedef struct B Struct_B */
697                 BTF_TYPEDEF_ENC(NAME_TBD, 4),                   /* [3] */
698                 /* struct B */                                  /* [4] */
699                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
700                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x;       */
701                 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A y;  */
702                 BTF_END_RAW,
703         },
704         .str_sec = "\0A\0x\0y\0Struct_B\0B\0x\0y",
705         .str_sec_size = sizeof("\0A\0x\0y\0Struct_B\0B\0x\0y"),
706         .map_type = BPF_MAP_TYPE_ARRAY,
707         .map_name = "loop_test5_map",
708         .key_size = sizeof(int),
709         .value_size = 8,
710         .key_type_id = 1,
711         .value_type_id = 2,
712         .max_entries = 4,
713         .btf_load_err = true,
714         .err_str = "Loop detected",
715 },
716
717 /* struct A {
718  *     int x;
719  *     struct A array_a[4];
720  * };
721  */
722 {
723         .descr = "loop test #6",
724         .raw_types = {
725                 /* int */
726                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
727                 BTF_TYPE_ARRAY_ENC(3, 1, 4),                    /* [2] */
728                 /* struct A */                                  /* [3] */
729                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 2), 8),
730                 BTF_MEMBER_ENC(NAME_TBD, 1, 0), /* int x;               */
731                 BTF_MEMBER_ENC(NAME_TBD, 2, 32),/* struct A array_a[4]; */
732                 BTF_END_RAW,
733         },
734         .str_sec = "\0A\0x\0y",
735         .str_sec_size = sizeof("\0A\0x\0y"),
736         .map_type = BPF_MAP_TYPE_ARRAY,
737         .map_name = "loop_test6_map",
738         .key_size = sizeof(int),
739         .value_size = 8,
740         .key_type_id = 1,
741         .value_type_id = 2,
742         .max_entries = 4,
743         .btf_load_err = true,
744         .err_str = "Loop detected",
745 },
746
747 {
748         .descr = "loop test #7",
749         .raw_types = {
750                 /* int */                               /* [1] */
751                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
752                 /* struct A { */                        /* [2] */
753                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
754                 /*     const void *m;   */
755                 BTF_MEMBER_ENC(NAME_TBD, 3, 0),
756                 /* CONST type_id=3      */              /* [3] */
757                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
758                 /* PTR type_id=2        */              /* [4] */
759                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 3),
760                 BTF_END_RAW,
761         },
762         .str_sec = "\0A\0m",
763         .str_sec_size = sizeof("\0A\0m"),
764         .map_type = BPF_MAP_TYPE_ARRAY,
765         .map_name = "loop_test7_map",
766         .key_size = sizeof(int),
767         .value_size = sizeof(void *),
768         .key_type_id = 1,
769         .value_type_id = 2,
770         .max_entries = 4,
771         .btf_load_err = true,
772         .err_str = "Loop detected",
773 },
774
775 {
776         .descr = "loop test #8",
777         .raw_types = {
778                 /* int */                               /* [1] */
779                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
780                 /* struct A { */                        /* [2] */
781                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
782                 /*     const void *m;   */
783                 BTF_MEMBER_ENC(NAME_TBD, 4, 0),
784                 /* struct B { */                        /* [3] */
785                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 1), sizeof(void *)),
786                 /*     const void *n;   */
787                 BTF_MEMBER_ENC(NAME_TBD, 6, 0),
788                 /* CONST type_id=5      */              /* [4] */
789                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 5),
790                 /* PTR type_id=6        */              /* [5] */
791                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 6),
792                 /* CONST type_id=7      */              /* [6] */
793                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 7),
794                 /* PTR type_id=4        */              /* [7] */
795                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 4),
796                 BTF_END_RAW,
797         },
798         .str_sec = "\0A\0m\0B\0n",
799         .str_sec_size = sizeof("\0A\0m\0B\0n"),
800         .map_type = BPF_MAP_TYPE_ARRAY,
801         .map_name = "loop_test8_map",
802         .key_size = sizeof(int),
803         .value_size = sizeof(void *),
804         .key_type_id = 1,
805         .value_type_id = 2,
806         .max_entries = 4,
807         .btf_load_err = true,
808         .err_str = "Loop detected",
809 },
810
811 {
812         .descr = "string section does not end with null",
813         .raw_types = {
814                 /* int */                               /* [1] */
815                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
816                 BTF_END_RAW,
817         },
818         .str_sec = "\0int",
819         .str_sec_size = sizeof("\0int") - 1,
820         .map_type = BPF_MAP_TYPE_ARRAY,
821         .map_name = "hdr_test_map",
822         .key_size = sizeof(int),
823         .value_size = sizeof(int),
824         .key_type_id = 1,
825         .value_type_id = 1,
826         .max_entries = 4,
827         .btf_load_err = true,
828         .err_str = "Invalid string section",
829 },
830
831 {
832         .descr = "empty string section",
833         .raw_types = {
834                 /* int */                               /* [1] */
835                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
836                 BTF_END_RAW,
837         },
838         .str_sec = "",
839         .str_sec_size = 0,
840         .map_type = BPF_MAP_TYPE_ARRAY,
841         .map_name = "hdr_test_map",
842         .key_size = sizeof(int),
843         .value_size = sizeof(int),
844         .key_type_id = 1,
845         .value_type_id = 1,
846         .max_entries = 4,
847         .btf_load_err = true,
848         .err_str = "Invalid string section",
849 },
850
851 {
852         .descr = "empty type section",
853         .raw_types = {
854                 BTF_END_RAW,
855         },
856         .str_sec = "\0int",
857         .str_sec_size = sizeof("\0int"),
858         .map_type = BPF_MAP_TYPE_ARRAY,
859         .map_name = "hdr_test_map",
860         .key_size = sizeof(int),
861         .value_size = sizeof(int),
862         .key_type_id = 1,
863         .value_type_id = 1,
864         .max_entries = 4,
865         .btf_load_err = true,
866         .err_str = "No type found",
867 },
868
869 {
870         .descr = "btf_header test. Longer hdr_len",
871         .raw_types = {
872                 /* int */                               /* [1] */
873                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
874                 BTF_END_RAW,
875         },
876         .str_sec = "\0int",
877         .str_sec_size = sizeof("\0int"),
878         .map_type = BPF_MAP_TYPE_ARRAY,
879         .map_name = "hdr_test_map",
880         .key_size = sizeof(int),
881         .value_size = sizeof(int),
882         .key_type_id = 1,
883         .value_type_id = 1,
884         .max_entries = 4,
885         .btf_load_err = true,
886         .hdr_len_delta = 4,
887         .err_str = "Unsupported btf_header",
888 },
889
890 {
891         .descr = "btf_header test. Gap between hdr and type",
892         .raw_types = {
893                 /* int */                               /* [1] */
894                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
895                 BTF_END_RAW,
896         },
897         .str_sec = "\0int",
898         .str_sec_size = sizeof("\0int"),
899         .map_type = BPF_MAP_TYPE_ARRAY,
900         .map_name = "hdr_test_map",
901         .key_size = sizeof(int),
902         .value_size = sizeof(int),
903         .key_type_id = 1,
904         .value_type_id = 1,
905         .max_entries = 4,
906         .btf_load_err = true,
907         .type_off_delta = 4,
908         .err_str = "Unsupported section found",
909 },
910
911 {
912         .descr = "btf_header test. Gap between type and str",
913         .raw_types = {
914                 /* int */                               /* [1] */
915                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
916                 BTF_END_RAW,
917         },
918         .str_sec = "\0int",
919         .str_sec_size = sizeof("\0int"),
920         .map_type = BPF_MAP_TYPE_ARRAY,
921         .map_name = "hdr_test_map",
922         .key_size = sizeof(int),
923         .value_size = sizeof(int),
924         .key_type_id = 1,
925         .value_type_id = 1,
926         .max_entries = 4,
927         .btf_load_err = true,
928         .str_off_delta = 4,
929         .err_str = "Unsupported section found",
930 },
931
932 {
933         .descr = "btf_header test. Overlap between type and str",
934         .raw_types = {
935                 /* int */                               /* [1] */
936                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
937                 BTF_END_RAW,
938         },
939         .str_sec = "\0int",
940         .str_sec_size = sizeof("\0int"),
941         .map_type = BPF_MAP_TYPE_ARRAY,
942         .map_name = "hdr_test_map",
943         .key_size = sizeof(int),
944         .value_size = sizeof(int),
945         .key_type_id = 1,
946         .value_type_id = 1,
947         .max_entries = 4,
948         .btf_load_err = true,
949         .str_off_delta = -4,
950         .err_str = "Section overlap found",
951 },
952
953 {
954         .descr = "btf_header test. Larger BTF size",
955         .raw_types = {
956                 /* int */                               /* [1] */
957                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
958                 BTF_END_RAW,
959         },
960         .str_sec = "\0int",
961         .str_sec_size = sizeof("\0int"),
962         .map_type = BPF_MAP_TYPE_ARRAY,
963         .map_name = "hdr_test_map",
964         .key_size = sizeof(int),
965         .value_size = sizeof(int),
966         .key_type_id = 1,
967         .value_type_id = 1,
968         .max_entries = 4,
969         .btf_load_err = true,
970         .str_len_delta = -4,
971         .err_str = "Unsupported section found",
972 },
973
974 {
975         .descr = "btf_header test. Smaller BTF size",
976         .raw_types = {
977                 /* int */                               /* [1] */
978                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
979                 BTF_END_RAW,
980         },
981         .str_sec = "\0int",
982         .str_sec_size = sizeof("\0int"),
983         .map_type = BPF_MAP_TYPE_ARRAY,
984         .map_name = "hdr_test_map",
985         .key_size = sizeof(int),
986         .value_size = sizeof(int),
987         .key_type_id = 1,
988         .value_type_id = 1,
989         .max_entries = 4,
990         .btf_load_err = true,
991         .str_len_delta = 4,
992         .err_str = "Total section length too long",
993 },
994
995 {
996         .descr = "array test. index_type/elem_type \"int\"",
997         .raw_types = {
998                 /* int */                               /* [1] */
999                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1000                 /* int[16] */                           /* [2] */
1001                 BTF_TYPE_ARRAY_ENC(1, 1, 16),
1002                 BTF_END_RAW,
1003         },
1004         .str_sec = "",
1005         .str_sec_size = sizeof(""),
1006         .map_type = BPF_MAP_TYPE_ARRAY,
1007         .map_name = "array_test_map",
1008         .key_size = sizeof(int),
1009         .value_size = sizeof(int),
1010         .key_type_id = 1,
1011         .value_type_id = 1,
1012         .max_entries = 4,
1013 },
1014
1015 {
1016         .descr = "array test. index_type/elem_type \"const int\"",
1017         .raw_types = {
1018                 /* int */                               /* [1] */
1019                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1020                 /* int[16] */                           /* [2] */
1021                 BTF_TYPE_ARRAY_ENC(3, 3, 16),
1022                 /* CONST type_id=1 */                   /* [3] */
1023                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 1),
1024                 BTF_END_RAW,
1025         },
1026         .str_sec = "",
1027         .str_sec_size = sizeof(""),
1028         .map_type = BPF_MAP_TYPE_ARRAY,
1029         .map_name = "array_test_map",
1030         .key_size = sizeof(int),
1031         .value_size = sizeof(int),
1032         .key_type_id = 1,
1033         .value_type_id = 1,
1034         .max_entries = 4,
1035 },
1036
1037 {
1038         .descr = "array test. index_type \"const int:31\"",
1039         .raw_types = {
1040                 /* int */                               /* [1] */
1041                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1042                 /* int:31 */                            /* [2] */
1043                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 31, 4),
1044                 /* int[16] */                           /* [3] */
1045                 BTF_TYPE_ARRAY_ENC(1, 4, 16),
1046                 /* CONST type_id=2 */                   /* [4] */
1047                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2),
1048                 BTF_END_RAW,
1049         },
1050         .str_sec = "",
1051         .str_sec_size = sizeof(""),
1052         .map_type = BPF_MAP_TYPE_ARRAY,
1053         .map_name = "array_test_map",
1054         .key_size = sizeof(int),
1055         .value_size = sizeof(int),
1056         .key_type_id = 1,
1057         .value_type_id = 1,
1058         .max_entries = 4,
1059         .btf_load_err = true,
1060         .err_str = "Invalid index",
1061 },
1062
1063 {
1064         .descr = "array test. elem_type \"const int:31\"",
1065         .raw_types = {
1066                 /* int */                               /* [1] */
1067                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1068                 /* int:31 */                            /* [2] */
1069                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 31, 4),
1070                 /* int[16] */                           /* [3] */
1071                 BTF_TYPE_ARRAY_ENC(4, 1, 16),
1072                 /* CONST type_id=2 */                   /* [4] */
1073                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 2),
1074                 BTF_END_RAW,
1075         },
1076         .str_sec = "",
1077         .str_sec_size = sizeof(""),
1078         .map_type = BPF_MAP_TYPE_ARRAY,
1079         .map_name = "array_test_map",
1080         .key_size = sizeof(int),
1081         .value_size = sizeof(int),
1082         .key_type_id = 1,
1083         .value_type_id = 1,
1084         .max_entries = 4,
1085         .btf_load_err = true,
1086         .err_str = "Invalid array of int",
1087 },
1088
1089 {
1090         .descr = "array test. index_type \"void\"",
1091         .raw_types = {
1092                 /* int */                               /* [1] */
1093                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1094                 /* int[16] */                           /* [2] */
1095                 BTF_TYPE_ARRAY_ENC(1, 0, 16),
1096                 BTF_END_RAW,
1097         },
1098         .str_sec = "",
1099         .str_sec_size = sizeof(""),
1100         .map_type = BPF_MAP_TYPE_ARRAY,
1101         .map_name = "array_test_map",
1102         .key_size = sizeof(int),
1103         .value_size = sizeof(int),
1104         .key_type_id = 1,
1105         .value_type_id = 1,
1106         .max_entries = 4,
1107         .btf_load_err = true,
1108         .err_str = "Invalid index",
1109 },
1110
1111 {
1112         .descr = "array test. index_type \"const void\"",
1113         .raw_types = {
1114                 /* int */                               /* [1] */
1115                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1116                 /* int[16] */                           /* [2] */
1117                 BTF_TYPE_ARRAY_ENC(1, 3, 16),
1118                 /* CONST type_id=0 (void) */            /* [3] */
1119                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
1120                 BTF_END_RAW,
1121         },
1122         .str_sec = "",
1123         .str_sec_size = sizeof(""),
1124         .map_type = BPF_MAP_TYPE_ARRAY,
1125         .map_name = "array_test_map",
1126         .key_size = sizeof(int),
1127         .value_size = sizeof(int),
1128         .key_type_id = 1,
1129         .value_type_id = 1,
1130         .max_entries = 4,
1131         .btf_load_err = true,
1132         .err_str = "Invalid index",
1133 },
1134
1135 {
1136         .descr = "array test. elem_type \"const void\"",
1137         .raw_types = {
1138                 /* int */                               /* [1] */
1139                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1140                 /* int[16] */                           /* [2] */
1141                 BTF_TYPE_ARRAY_ENC(3, 1, 16),
1142                 /* CONST type_id=0 (void) */            /* [3] */
1143                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 0),
1144                 BTF_END_RAW,
1145         },
1146         .str_sec = "",
1147         .str_sec_size = sizeof(""),
1148         .map_type = BPF_MAP_TYPE_ARRAY,
1149         .map_name = "array_test_map",
1150         .key_size = sizeof(int),
1151         .value_size = sizeof(int),
1152         .key_type_id = 1,
1153         .value_type_id = 1,
1154         .max_entries = 4,
1155         .btf_load_err = true,
1156         .err_str = "Invalid elem",
1157 },
1158
1159 {
1160         .descr = "array test. elem_type \"const void *\"",
1161         .raw_types = {
1162                 /* int */                               /* [1] */
1163                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1164                 /* const void *[16] */                  /* [2] */
1165                 BTF_TYPE_ARRAY_ENC(3, 1, 16),
1166                 /* CONST type_id=4 */                   /* [3] */
1167                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
1168                 /* void* */                             /* [4] */
1169                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
1170                 BTF_END_RAW,
1171         },
1172         .str_sec = "",
1173         .str_sec_size = sizeof(""),
1174         .map_type = BPF_MAP_TYPE_ARRAY,
1175         .map_name = "array_test_map",
1176         .key_size = sizeof(int),
1177         .value_size = sizeof(int),
1178         .key_type_id = 1,
1179         .value_type_id = 1,
1180         .max_entries = 4,
1181 },
1182
1183 {
1184         .descr = "array test. index_type \"const void *\"",
1185         .raw_types = {
1186                 /* int */                               /* [1] */
1187                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1188                 /* const void *[16] */                  /* [2] */
1189                 BTF_TYPE_ARRAY_ENC(3, 3, 16),
1190                 /* CONST type_id=4 */                   /* [3] */
1191                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 4),
1192                 /* void* */                             /* [4] */
1193                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_PTR, 0, 0), 0),
1194                 BTF_END_RAW,
1195         },
1196         .str_sec = "",
1197         .str_sec_size = sizeof(""),
1198         .map_type = BPF_MAP_TYPE_ARRAY,
1199         .map_name = "array_test_map",
1200         .key_size = sizeof(int),
1201         .value_size = sizeof(int),
1202         .key_type_id = 1,
1203         .value_type_id = 1,
1204         .max_entries = 4,
1205         .btf_load_err = true,
1206         .err_str = "Invalid index",
1207 },
1208
1209 {
1210         .descr = "array test. t->size != 0\"",
1211         .raw_types = {
1212                 /* int */                               /* [1] */
1213                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1214                 /* int[16] */                           /* [2] */
1215                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ARRAY, 0, 0), 1),
1216                 BTF_ARRAY_ENC(1, 1, 16),
1217                 BTF_END_RAW,
1218         },
1219         .str_sec = "",
1220         .str_sec_size = sizeof(""),
1221         .map_type = BPF_MAP_TYPE_ARRAY,
1222         .map_name = "array_test_map",
1223         .key_size = sizeof(int),
1224         .value_size = sizeof(int),
1225         .key_type_id = 1,
1226         .value_type_id = 1,
1227         .max_entries = 4,
1228         .btf_load_err = true,
1229         .err_str = "size != 0",
1230 },
1231
1232 {
1233         .descr = "int test. invalid int_data",
1234         .raw_types = {
1235                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_INT, 0, 0), 4),
1236                 0x10000000,
1237                 BTF_END_RAW,
1238         },
1239         .str_sec = "",
1240         .str_sec_size = sizeof(""),
1241         .map_type = BPF_MAP_TYPE_ARRAY,
1242         .map_name = "array_test_map",
1243         .key_size = sizeof(int),
1244         .value_size = sizeof(int),
1245         .key_type_id = 1,
1246         .value_type_id = 1,
1247         .max_entries = 4,
1248         .btf_load_err = true,
1249         .err_str = "Invalid int_data",
1250 },
1251
1252 {
1253         .descr = "invalid BTF_INFO",
1254         .raw_types = {
1255                 /* int */                               /* [1] */
1256                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1257                 BTF_TYPE_ENC(0, 0x10000000, 4),
1258                 BTF_END_RAW,
1259         },
1260         .str_sec = "",
1261         .str_sec_size = sizeof(""),
1262         .map_type = BPF_MAP_TYPE_ARRAY,
1263         .map_name = "array_test_map",
1264         .key_size = sizeof(int),
1265         .value_size = sizeof(int),
1266         .key_type_id = 1,
1267         .value_type_id = 1,
1268         .max_entries = 4,
1269         .btf_load_err = true,
1270         .err_str = "Invalid btf_info",
1271 },
1272
1273 {
1274         .descr = "fwd test. t->type != 0\"",
1275         .raw_types = {
1276                 /* int */                               /* [1] */
1277                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1278                 /* fwd type */                          /* [2] */
1279                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_FWD, 0, 0), 1),
1280                 BTF_END_RAW,
1281         },
1282         .str_sec = "",
1283         .str_sec_size = sizeof(""),
1284         .map_type = BPF_MAP_TYPE_ARRAY,
1285         .map_name = "fwd_test_map",
1286         .key_size = sizeof(int),
1287         .value_size = sizeof(int),
1288         .key_type_id = 1,
1289         .value_type_id = 1,
1290         .max_entries = 4,
1291         .btf_load_err = true,
1292         .err_str = "type != 0",
1293 },
1294
1295 {
1296         .descr = "arraymap invalid btf key (a bit field)",
1297         .raw_types = {
1298                 /* int */                               /* [1] */
1299                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1300                 /* 32 bit int with 32 bit offset */     /* [2] */
1301                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 32, 32, 8),
1302                 BTF_END_RAW,
1303         },
1304         .str_sec = "",
1305         .str_sec_size = sizeof(""),
1306         .map_type = BPF_MAP_TYPE_ARRAY,
1307         .map_name = "array_map_check_btf",
1308         .key_size = sizeof(int),
1309         .value_size = sizeof(int),
1310         .key_type_id = 2,
1311         .value_type_id = 1,
1312         .max_entries = 4,
1313         .map_create_err = true,
1314 },
1315
1316 {
1317         .descr = "arraymap invalid btf key (!= 32 bits)",
1318         .raw_types = {
1319                 /* int */                               /* [1] */
1320                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1321                 /* 16 bit int with 0 bit offset */      /* [2] */
1322                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 16, 2),
1323                 BTF_END_RAW,
1324         },
1325         .str_sec = "",
1326         .str_sec_size = sizeof(""),
1327         .map_type = BPF_MAP_TYPE_ARRAY,
1328         .map_name = "array_map_check_btf",
1329         .key_size = sizeof(int),
1330         .value_size = sizeof(int),
1331         .key_type_id = 2,
1332         .value_type_id = 1,
1333         .max_entries = 4,
1334         .map_create_err = true,
1335 },
1336
1337 {
1338         .descr = "arraymap invalid btf value (too small)",
1339         .raw_types = {
1340                 /* int */                               /* [1] */
1341                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1342                 BTF_END_RAW,
1343         },
1344         .str_sec = "",
1345         .str_sec_size = sizeof(""),
1346         .map_type = BPF_MAP_TYPE_ARRAY,
1347         .map_name = "array_map_check_btf",
1348         .key_size = sizeof(int),
1349         /* btf_value_size < map->value_size */
1350         .value_size = sizeof(__u64),
1351         .key_type_id = 1,
1352         .value_type_id = 1,
1353         .max_entries = 4,
1354         .map_create_err = true,
1355 },
1356
1357 {
1358         .descr = "arraymap invalid btf value (too big)",
1359         .raw_types = {
1360                 /* int */                               /* [1] */
1361                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1362                 BTF_END_RAW,
1363         },
1364         .str_sec = "",
1365         .str_sec_size = sizeof(""),
1366         .map_type = BPF_MAP_TYPE_ARRAY,
1367         .map_name = "array_map_check_btf",
1368         .key_size = sizeof(int),
1369         /* btf_value_size > map->value_size */
1370         .value_size = sizeof(__u16),
1371         .key_type_id = 1,
1372         .value_type_id = 1,
1373         .max_entries = 4,
1374         .map_create_err = true,
1375 },
1376
1377 }; /* struct btf_raw_test raw_tests[] */
1378
1379 static const char *get_next_str(const char *start, const char *end)
1380 {
1381         return start < end - 1 ? start + 1 : NULL;
1382 }
1383
1384 static int get_type_sec_size(const __u32 *raw_types)
1385 {
1386         int i;
1387
1388         for (i = MAX_NR_RAW_TYPES - 1;
1389              i >= 0 && raw_types[i] != BTF_END_RAW;
1390              i--)
1391                 ;
1392
1393         return i < 0 ? i : i * sizeof(raw_types[0]);
1394 }
1395
1396 static void *btf_raw_create(const struct btf_header *hdr,
1397                             const __u32 *raw_types,
1398                             const char *str,
1399                             unsigned int str_sec_size,
1400                             unsigned int *btf_size)
1401 {
1402         const char *next_str = str, *end_str = str + str_sec_size;
1403         unsigned int size_needed, offset;
1404         struct btf_header *ret_hdr;
1405         int i, type_sec_size;
1406         uint32_t *ret_types;
1407         void *raw_btf;
1408
1409         type_sec_size = get_type_sec_size(raw_types);
1410         if (CHECK(type_sec_size < 0, "Cannot get nr_raw_types"))
1411                 return NULL;
1412
1413         size_needed = sizeof(*hdr) + type_sec_size + str_sec_size;
1414         raw_btf = malloc(size_needed);
1415         if (CHECK(!raw_btf, "Cannot allocate memory for raw_btf"))
1416                 return NULL;
1417
1418         /* Copy header */
1419         memcpy(raw_btf, hdr, sizeof(*hdr));
1420         offset = sizeof(*hdr);
1421
1422         /* Copy type section */
1423         ret_types = raw_btf + offset;
1424         for (i = 0; i < type_sec_size / sizeof(raw_types[0]); i++) {
1425                 if (raw_types[i] == NAME_TBD) {
1426                         next_str = get_next_str(next_str, end_str);
1427                         if (CHECK(!next_str, "Error in getting next_str")) {
1428                                 free(raw_btf);
1429                                 return NULL;
1430                         }
1431                         ret_types[i] = next_str - str;
1432                         next_str += strlen(next_str);
1433                 } else {
1434                         ret_types[i] = raw_types[i];
1435                 }
1436         }
1437         offset += type_sec_size;
1438
1439         /* Copy string section */
1440         memcpy(raw_btf + offset, str, str_sec_size);
1441
1442         ret_hdr = (struct btf_header *)raw_btf;
1443         ret_hdr->type_len = type_sec_size;
1444         ret_hdr->str_off = type_sec_size;
1445         ret_hdr->str_len = str_sec_size;
1446
1447         *btf_size = size_needed;
1448
1449         return raw_btf;
1450 }
1451
1452 static int do_test_raw(unsigned int test_num)
1453 {
1454         struct btf_raw_test *test = &raw_tests[test_num - 1];
1455         struct bpf_create_map_attr create_attr = {};
1456         int map_fd = -1, btf_fd = -1;
1457         unsigned int raw_btf_size;
1458         struct btf_header *hdr;
1459         void *raw_btf;
1460         int err;
1461
1462         fprintf(stderr, "BTF raw test[%u] (%s): ", test_num, test->descr);
1463         raw_btf = btf_raw_create(&hdr_tmpl,
1464                                  test->raw_types,
1465                                  test->str_sec,
1466                                  test->str_sec_size,
1467                                  &raw_btf_size);
1468
1469         if (!raw_btf)
1470                 return -1;
1471
1472         hdr = raw_btf;
1473
1474         hdr->hdr_len = (int)hdr->hdr_len + test->hdr_len_delta;
1475         hdr->type_off = (int)hdr->type_off + test->type_off_delta;
1476         hdr->str_off = (int)hdr->str_off + test->str_off_delta;
1477         hdr->str_len = (int)hdr->str_len + test->str_len_delta;
1478
1479         *btf_log_buf = '\0';
1480         btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
1481                               btf_log_buf, BTF_LOG_BUF_SIZE,
1482                               args.always_log);
1483         free(raw_btf);
1484
1485         err = ((btf_fd == -1) != test->btf_load_err);
1486         if (CHECK(err, "btf_fd:%d test->btf_load_err:%u",
1487                   btf_fd, test->btf_load_err) ||
1488             CHECK(test->err_str && !strstr(btf_log_buf, test->err_str),
1489                   "expected err_str:%s", test->err_str)) {
1490                 err = -1;
1491                 goto done;
1492         }
1493
1494         if (err || btf_fd == -1)
1495                 goto done;
1496
1497         create_attr.name = test->map_name;
1498         create_attr.map_type = test->map_type;
1499         create_attr.key_size = test->key_size;
1500         create_attr.value_size = test->value_size;
1501         create_attr.max_entries = test->max_entries;
1502         create_attr.btf_fd = btf_fd;
1503         create_attr.btf_key_type_id = test->key_type_id;
1504         create_attr.btf_value_type_id = test->value_type_id;
1505
1506         map_fd = bpf_create_map_xattr(&create_attr);
1507
1508         err = ((map_fd == -1) != test->map_create_err);
1509         CHECK(err, "map_fd:%d test->map_create_err:%u",
1510               map_fd, test->map_create_err);
1511
1512 done:
1513         if (!err)
1514                 fprintf(stderr, "OK");
1515
1516         if (*btf_log_buf && (err || args.always_log))
1517                 fprintf(stderr, "\n%s", btf_log_buf);
1518
1519         if (btf_fd != -1)
1520                 close(btf_fd);
1521         if (map_fd != -1)
1522                 close(map_fd);
1523
1524         return err;
1525 }
1526
1527 static int test_raw(void)
1528 {
1529         unsigned int i;
1530         int err = 0;
1531
1532         if (args.raw_test_num)
1533                 return count_result(do_test_raw(args.raw_test_num));
1534
1535         for (i = 1; i <= ARRAY_SIZE(raw_tests); i++)
1536                 err |= count_result(do_test_raw(i));
1537
1538         return err;
1539 }
1540
1541 struct btf_get_info_test {
1542         const char *descr;
1543         const char *str_sec;
1544         __u32 raw_types[MAX_NR_RAW_TYPES];
1545         __u32 str_sec_size;
1546         int btf_size_delta;
1547         int (*special_test)(unsigned int test_num);
1548 };
1549
1550 static int test_big_btf_info(unsigned int test_num);
1551 static int test_btf_id(unsigned int test_num);
1552
1553 const struct btf_get_info_test get_info_tests[] = {
1554 {
1555         .descr = "== raw_btf_size+1",
1556         .raw_types = {
1557                 /* int */                               /* [1] */
1558                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1559                 BTF_END_RAW,
1560         },
1561         .str_sec = "",
1562         .str_sec_size = sizeof(""),
1563         .btf_size_delta = 1,
1564 },
1565 {
1566         .descr = "== raw_btf_size-3",
1567         .raw_types = {
1568                 /* int */                               /* [1] */
1569                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1570                 BTF_END_RAW,
1571         },
1572         .str_sec = "",
1573         .str_sec_size = sizeof(""),
1574         .btf_size_delta = -3,
1575 },
1576 {
1577         .descr = "Large bpf_btf_info",
1578         .raw_types = {
1579                 /* int */                               /* [1] */
1580                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1581                 BTF_END_RAW,
1582         },
1583         .str_sec = "",
1584         .str_sec_size = sizeof(""),
1585         .special_test = test_big_btf_info,
1586 },
1587 {
1588         .descr = "BTF ID",
1589         .raw_types = {
1590                 /* int */                               /* [1] */
1591                 BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),
1592                 /* unsigned int */                      /* [2] */
1593                 BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),
1594                 BTF_END_RAW,
1595         },
1596         .str_sec = "",
1597         .str_sec_size = sizeof(""),
1598         .special_test = test_btf_id,
1599 },
1600 };
1601
1602 static inline __u64 ptr_to_u64(const void *ptr)
1603 {
1604         return (__u64)(unsigned long)ptr;
1605 }
1606
1607 static int test_big_btf_info(unsigned int test_num)
1608 {
1609         const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
1610         uint8_t *raw_btf = NULL, *user_btf = NULL;
1611         unsigned int raw_btf_size;
1612         struct {
1613                 struct bpf_btf_info info;
1614                 uint64_t garbage;
1615         } info_garbage;
1616         struct bpf_btf_info *info;
1617         int btf_fd = -1, err;
1618         uint32_t info_len;
1619
1620         raw_btf = btf_raw_create(&hdr_tmpl,
1621                                  test->raw_types,
1622                                  test->str_sec,
1623                                  test->str_sec_size,
1624                                  &raw_btf_size);
1625
1626         if (!raw_btf)
1627                 return -1;
1628
1629         *btf_log_buf = '\0';
1630
1631         user_btf = malloc(raw_btf_size);
1632         if (CHECK(!user_btf, "!user_btf")) {
1633                 err = -1;
1634                 goto done;
1635         }
1636
1637         btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
1638                               btf_log_buf, BTF_LOG_BUF_SIZE,
1639                               args.always_log);
1640         if (CHECK(btf_fd == -1, "errno:%d", errno)) {
1641                 err = -1;
1642                 goto done;
1643         }
1644
1645         /*
1646          * GET_INFO should error out if the userspace info
1647          * has non zero tailing bytes.
1648          */
1649         info = &info_garbage.info;
1650         memset(info, 0, sizeof(*info));
1651         info_garbage.garbage = 0xdeadbeef;
1652         info_len = sizeof(info_garbage);
1653         info->btf = ptr_to_u64(user_btf);
1654         info->btf_size = raw_btf_size;
1655
1656         err = bpf_obj_get_info_by_fd(btf_fd, info, &info_len);
1657         if (CHECK(!err, "!err")) {
1658                 err = -1;
1659                 goto done;
1660         }
1661
1662         /*
1663          * GET_INFO should succeed even info_len is larger than
1664          * the kernel supported as long as tailing bytes are zero.
1665          * The kernel supported info len should also be returned
1666          * to userspace.
1667          */
1668         info_garbage.garbage = 0;
1669         err = bpf_obj_get_info_by_fd(btf_fd, info, &info_len);
1670         if (CHECK(err || info_len != sizeof(*info),
1671                   "err:%d errno:%d info_len:%u sizeof(*info):%lu",
1672                   err, errno, info_len, sizeof(*info))) {
1673                 err = -1;
1674                 goto done;
1675         }
1676
1677         fprintf(stderr, "OK");
1678
1679 done:
1680         if (*btf_log_buf && (err || args.always_log))
1681                 fprintf(stderr, "\n%s", btf_log_buf);
1682
1683         free(raw_btf);
1684         free(user_btf);
1685
1686         if (btf_fd != -1)
1687                 close(btf_fd);
1688
1689         return err;
1690 }
1691
1692 static int test_btf_id(unsigned int test_num)
1693 {
1694         const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
1695         struct bpf_create_map_attr create_attr = {};
1696         uint8_t *raw_btf = NULL, *user_btf[2] = {};
1697         int btf_fd[2] = {-1, -1}, map_fd = -1;
1698         struct bpf_map_info map_info = {};
1699         struct bpf_btf_info info[2] = {};
1700         unsigned int raw_btf_size;
1701         uint32_t info_len;
1702         int err, i, ret;
1703
1704         raw_btf = btf_raw_create(&hdr_tmpl,
1705                                  test->raw_types,
1706                                  test->str_sec,
1707                                  test->str_sec_size,
1708                                  &raw_btf_size);
1709
1710         if (!raw_btf)
1711                 return -1;
1712
1713         *btf_log_buf = '\0';
1714
1715         for (i = 0; i < 2; i++) {
1716                 user_btf[i] = malloc(raw_btf_size);
1717                 if (CHECK(!user_btf[i], "!user_btf[%d]", i)) {
1718                         err = -1;
1719                         goto done;
1720                 }
1721                 info[i].btf = ptr_to_u64(user_btf[i]);
1722                 info[i].btf_size = raw_btf_size;
1723         }
1724
1725         btf_fd[0] = bpf_load_btf(raw_btf, raw_btf_size,
1726                                  btf_log_buf, BTF_LOG_BUF_SIZE,
1727                                  args.always_log);
1728         if (CHECK(btf_fd[0] == -1, "errno:%d", errno)) {
1729                 err = -1;
1730                 goto done;
1731         }
1732
1733         /* Test BPF_OBJ_GET_INFO_BY_ID on btf_id */
1734         info_len = sizeof(info[0]);
1735         err = bpf_obj_get_info_by_fd(btf_fd[0], &info[0], &info_len);
1736         if (CHECK(err, "errno:%d", errno)) {
1737                 err = -1;
1738                 goto done;
1739         }
1740
1741         btf_fd[1] = bpf_btf_get_fd_by_id(info[0].id);
1742         if (CHECK(btf_fd[1] == -1, "errno:%d", errno)) {
1743                 err = -1;
1744                 goto done;
1745         }
1746
1747         ret = 0;
1748         err = bpf_obj_get_info_by_fd(btf_fd[1], &info[1], &info_len);
1749         if (CHECK(err || info[0].id != info[1].id ||
1750                   info[0].btf_size != info[1].btf_size ||
1751                   (ret = memcmp(user_btf[0], user_btf[1], info[0].btf_size)),
1752                   "err:%d errno:%d id0:%u id1:%u btf_size0:%u btf_size1:%u memcmp:%d",
1753                   err, errno, info[0].id, info[1].id,
1754                   info[0].btf_size, info[1].btf_size, ret)) {
1755                 err = -1;
1756                 goto done;
1757         }
1758
1759         /* Test btf members in struct bpf_map_info */
1760         create_attr.name = "test_btf_id";
1761         create_attr.map_type = BPF_MAP_TYPE_ARRAY;
1762         create_attr.key_size = sizeof(int);
1763         create_attr.value_size = sizeof(unsigned int);
1764         create_attr.max_entries = 4;
1765         create_attr.btf_fd = btf_fd[0];
1766         create_attr.btf_key_type_id = 1;
1767         create_attr.btf_value_type_id = 2;
1768
1769         map_fd = bpf_create_map_xattr(&create_attr);
1770         if (CHECK(map_fd == -1, "errno:%d", errno)) {
1771                 err = -1;
1772                 goto done;
1773         }
1774
1775         info_len = sizeof(map_info);
1776         err = bpf_obj_get_info_by_fd(map_fd, &map_info, &info_len);
1777         if (CHECK(err || map_info.btf_id != info[0].id ||
1778                   map_info.btf_key_type_id != 1 || map_info.btf_value_type_id != 2,
1779                   "err:%d errno:%d info.id:%u btf_id:%u btf_key_type_id:%u btf_value_type_id:%u",
1780                   err, errno, info[0].id, map_info.btf_id, map_info.btf_key_type_id,
1781                   map_info.btf_value_type_id)) {
1782                 err = -1;
1783                 goto done;
1784         }
1785
1786         for (i = 0; i < 2; i++) {
1787                 close(btf_fd[i]);
1788                 btf_fd[i] = -1;
1789         }
1790
1791         /* Test BTF ID is removed from the kernel */
1792         btf_fd[0] = bpf_btf_get_fd_by_id(map_info.btf_id);
1793         if (CHECK(btf_fd[0] == -1, "errno:%d", errno)) {
1794                 err = -1;
1795                 goto done;
1796         }
1797         close(btf_fd[0]);
1798         btf_fd[0] = -1;
1799
1800         /* The map holds the last ref to BTF and its btf_id */
1801         close(map_fd);
1802         map_fd = -1;
1803         btf_fd[0] = bpf_btf_get_fd_by_id(map_info.btf_id);
1804         if (CHECK(btf_fd[0] != -1, "BTF lingers")) {
1805                 err = -1;
1806                 goto done;
1807         }
1808
1809         fprintf(stderr, "OK");
1810
1811 done:
1812         if (*btf_log_buf && (err || args.always_log))
1813                 fprintf(stderr, "\n%s", btf_log_buf);
1814
1815         free(raw_btf);
1816         if (map_fd != -1)
1817                 close(map_fd);
1818         for (i = 0; i < 2; i++) {
1819                 free(user_btf[i]);
1820                 if (btf_fd[i] != -1)
1821                         close(btf_fd[i]);
1822         }
1823
1824         return err;
1825 }
1826
1827 static int do_test_get_info(unsigned int test_num)
1828 {
1829         const struct btf_get_info_test *test = &get_info_tests[test_num - 1];
1830         unsigned int raw_btf_size, user_btf_size, expected_nbytes;
1831         uint8_t *raw_btf = NULL, *user_btf = NULL;
1832         struct bpf_btf_info info = {};
1833         int btf_fd = -1, err, ret;
1834         uint32_t info_len;
1835
1836         fprintf(stderr, "BTF GET_INFO test[%u] (%s): ",
1837                 test_num, test->descr);
1838
1839         if (test->special_test)
1840                 return test->special_test(test_num);
1841
1842         raw_btf = btf_raw_create(&hdr_tmpl,
1843                                  test->raw_types,
1844                                  test->str_sec,
1845                                  test->str_sec_size,
1846                                  &raw_btf_size);
1847
1848         if (!raw_btf)
1849                 return -1;
1850
1851         *btf_log_buf = '\0';
1852
1853         user_btf = malloc(raw_btf_size);
1854         if (CHECK(!user_btf, "!user_btf")) {
1855                 err = -1;
1856                 goto done;
1857         }
1858
1859         btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
1860                               btf_log_buf, BTF_LOG_BUF_SIZE,
1861                               args.always_log);
1862         if (CHECK(btf_fd == -1, "errno:%d", errno)) {
1863                 err = -1;
1864                 goto done;
1865         }
1866
1867         user_btf_size = (int)raw_btf_size + test->btf_size_delta;
1868         expected_nbytes = min(raw_btf_size, user_btf_size);
1869         if (raw_btf_size > expected_nbytes)
1870                 memset(user_btf + expected_nbytes, 0xff,
1871                        raw_btf_size - expected_nbytes);
1872
1873         info_len = sizeof(info);
1874         info.btf = ptr_to_u64(user_btf);
1875         info.btf_size = user_btf_size;
1876
1877         ret = 0;
1878         err = bpf_obj_get_info_by_fd(btf_fd, &info, &info_len);
1879         if (CHECK(err || !info.id || info_len != sizeof(info) ||
1880                   info.btf_size != raw_btf_size ||
1881                   (ret = memcmp(raw_btf, user_btf, expected_nbytes)),
1882                   "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",
1883                   err, errno, info.id, info_len, sizeof(info),
1884                   raw_btf_size, info.btf_size, expected_nbytes, ret)) {
1885                 err = -1;
1886                 goto done;
1887         }
1888
1889         while (expected_nbytes < raw_btf_size) {
1890                 fprintf(stderr, "%u...", expected_nbytes);
1891                 if (CHECK(user_btf[expected_nbytes++] != 0xff,
1892                           "user_btf[%u]:%x != 0xff", expected_nbytes - 1,
1893                           user_btf[expected_nbytes - 1])) {
1894                         err = -1;
1895                         goto done;
1896                 }
1897         }
1898
1899         fprintf(stderr, "OK");
1900
1901 done:
1902         if (*btf_log_buf && (err || args.always_log))
1903                 fprintf(stderr, "\n%s", btf_log_buf);
1904
1905         free(raw_btf);
1906         free(user_btf);
1907
1908         if (btf_fd != -1)
1909                 close(btf_fd);
1910
1911         return err;
1912 }
1913
1914 static int test_get_info(void)
1915 {
1916         unsigned int i;
1917         int err = 0;
1918
1919         if (args.get_info_test_num)
1920                 return count_result(do_test_get_info(args.get_info_test_num));
1921
1922         for (i = 1; i <= ARRAY_SIZE(get_info_tests); i++)
1923                 err |= count_result(do_test_get_info(i));
1924
1925         return err;
1926 }
1927
1928 struct btf_file_test {
1929         const char *file;
1930         bool btf_kv_notfound;
1931 };
1932
1933 static struct btf_file_test file_tests[] = {
1934 {
1935         .file = "test_btf_haskv.o",
1936 },
1937 {
1938         .file = "test_btf_nokv.o",
1939         .btf_kv_notfound = true,
1940 },
1941 };
1942
1943 static int file_has_btf_elf(const char *fn)
1944 {
1945         Elf_Scn *scn = NULL;
1946         GElf_Ehdr ehdr;
1947         int elf_fd;
1948         Elf *elf;
1949         int ret;
1950
1951         if (CHECK(elf_version(EV_CURRENT) == EV_NONE,
1952                   "elf_version(EV_CURRENT) == EV_NONE"))
1953                 return -1;
1954
1955         elf_fd = open(fn, O_RDONLY);
1956         if (CHECK(elf_fd == -1, "open(%s): errno:%d", fn, errno))
1957                 return -1;
1958
1959         elf = elf_begin(elf_fd, ELF_C_READ, NULL);
1960         if (CHECK(!elf, "elf_begin(%s): %s", fn, elf_errmsg(elf_errno()))) {
1961                 ret = -1;
1962                 goto done;
1963         }
1964
1965         if (CHECK(!gelf_getehdr(elf, &ehdr), "!gelf_getehdr(%s)", fn)) {
1966                 ret = -1;
1967                 goto done;
1968         }
1969
1970         while ((scn = elf_nextscn(elf, scn))) {
1971                 const char *sh_name;
1972                 GElf_Shdr sh;
1973
1974                 if (CHECK(gelf_getshdr(scn, &sh) != &sh,
1975                           "file:%s gelf_getshdr != &sh", fn)) {
1976                         ret = -1;
1977                         goto done;
1978                 }
1979
1980                 sh_name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
1981                 if (!strcmp(sh_name, BTF_ELF_SEC)) {
1982                         ret = 1;
1983                         goto done;
1984                 }
1985         }
1986
1987         ret = 0;
1988
1989 done:
1990         close(elf_fd);
1991         elf_end(elf);
1992         return ret;
1993 }
1994
1995 static int do_test_file(unsigned int test_num)
1996 {
1997         const struct btf_file_test *test = &file_tests[test_num - 1];
1998         struct bpf_object *obj = NULL;
1999         struct bpf_program *prog;
2000         struct bpf_map *map;
2001         int err;
2002
2003         fprintf(stderr, "BTF libbpf test[%u] (%s): ", test_num,
2004                 test->file);
2005
2006         err = file_has_btf_elf(test->file);
2007         if (err == -1)
2008                 return err;
2009
2010         if (err == 0) {
2011                 fprintf(stderr, "SKIP. No ELF %s found", BTF_ELF_SEC);
2012                 skip_cnt++;
2013                 return 0;
2014         }
2015
2016         obj = bpf_object__open(test->file);
2017         if (CHECK(IS_ERR(obj), "obj: %ld", PTR_ERR(obj)))
2018                 return PTR_ERR(obj);
2019
2020         err = bpf_object__btf_fd(obj);
2021         if (CHECK(err == -1, "bpf_object__btf_fd: -1"))
2022                 goto done;
2023
2024         prog = bpf_program__next(NULL, obj);
2025         if (CHECK(!prog, "Cannot find bpf_prog")) {
2026                 err = -1;
2027                 goto done;
2028         }
2029
2030         bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
2031         err = bpf_object__load(obj);
2032         if (CHECK(err < 0, "bpf_object__load: %d", err))
2033                 goto done;
2034
2035         map = bpf_object__find_map_by_name(obj, "btf_map");
2036         if (CHECK(!map, "btf_map not found")) {
2037                 err = -1;
2038                 goto done;
2039         }
2040
2041         err = (bpf_map__btf_key_type_id(map) == 0 || bpf_map__btf_value_type_id(map) == 0)
2042                 != test->btf_kv_notfound;
2043         if (CHECK(err, "btf_key_type_id:%u btf_value_type_id:%u test->btf_kv_notfound:%u",
2044                   bpf_map__btf_key_type_id(map), bpf_map__btf_value_type_id(map),
2045                   test->btf_kv_notfound))
2046                 goto done;
2047
2048         fprintf(stderr, "OK");
2049
2050 done:
2051         bpf_object__close(obj);
2052         return err;
2053 }
2054
2055 static int test_file(void)
2056 {
2057         unsigned int i;
2058         int err = 0;
2059
2060         if (args.file_test_num)
2061                 return count_result(do_test_file(args.file_test_num));
2062
2063         for (i = 1; i <= ARRAY_SIZE(file_tests); i++)
2064                 err |= count_result(do_test_file(i));
2065
2066         return err;
2067 }
2068
2069 const char *pprint_enum_str[] = {
2070         "ENUM_ZERO",
2071         "ENUM_ONE",
2072         "ENUM_TWO",
2073         "ENUM_THREE",
2074 };
2075
2076 struct pprint_mapv {
2077         uint32_t ui32;
2078         uint16_t ui16;
2079         /* 2 bytes hole */
2080         int32_t si32;
2081         uint32_t unused_bits2a:2,
2082                 bits28:28,
2083                 unused_bits2b:2;
2084         union {
2085                 uint64_t ui64;
2086                 uint8_t ui8a[8];
2087         };
2088         enum {
2089                 ENUM_ZERO,
2090                 ENUM_ONE,
2091                 ENUM_TWO,
2092                 ENUM_THREE,
2093         } aenum;
2094 };
2095
2096 static struct btf_raw_test pprint_test_template = {
2097         .raw_types = {
2098                 /* unsighed char */                     /* [1] */
2099                 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 8, 1),
2100                 /* unsigned short */                    /* [2] */
2101                 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 16, 2),
2102                 /* unsigned int */                      /* [3] */
2103                 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 32, 4),
2104                 /* int */                               /* [4] */
2105                 BTF_TYPE_INT_ENC(NAME_TBD, BTF_INT_SIGNED, 0, 32, 4),
2106                 /* unsigned long long */                /* [5] */
2107                 BTF_TYPE_INT_ENC(NAME_TBD, 0, 0, 64, 8),
2108                 /* 2 bits */                            /* [6] */
2109                 BTF_TYPE_INT_ENC(0, 0, 0, 2, 2),
2110                 /* 28 bits */                           /* [7] */
2111                 BTF_TYPE_INT_ENC(0, 0, 0, 28, 4),
2112                 /* uint8_t[8] */                        /* [8] */
2113                 BTF_TYPE_ARRAY_ENC(9, 1, 8),
2114                 /* typedef unsigned char uint8_t */     /* [9] */
2115                 BTF_TYPEDEF_ENC(NAME_TBD, 1),
2116                 /* typedef unsigned short uint16_t */   /* [10] */
2117                 BTF_TYPEDEF_ENC(NAME_TBD, 2),
2118                 /* typedef unsigned int uint32_t */     /* [11] */
2119                 BTF_TYPEDEF_ENC(NAME_TBD, 3),
2120                 /* typedef int int32_t */               /* [12] */
2121                 BTF_TYPEDEF_ENC(NAME_TBD, 4),
2122                 /* typedef unsigned long long uint64_t *//* [13] */
2123                 BTF_TYPEDEF_ENC(NAME_TBD, 5),
2124                 /* union (anon) */                      /* [14] */
2125                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_UNION, 0, 2), 8),
2126                 BTF_MEMBER_ENC(NAME_TBD, 13, 0),/* uint64_t ui64; */
2127                 BTF_MEMBER_ENC(NAME_TBD, 8, 0), /* uint8_t ui8a[8]; */
2128                 /* enum (anon) */                       /* [15] */
2129                 BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_ENUM, 0, 4), 4),
2130                 BTF_ENUM_ENC(NAME_TBD, 0),
2131                 BTF_ENUM_ENC(NAME_TBD, 1),
2132                 BTF_ENUM_ENC(NAME_TBD, 2),
2133                 BTF_ENUM_ENC(NAME_TBD, 3),
2134                 /* struct pprint_mapv */                /* [16] */
2135                 BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
2136                 BTF_MEMBER_ENC(NAME_TBD, 11, 0),        /* uint32_t ui32 */
2137                 BTF_MEMBER_ENC(NAME_TBD, 10, 32),       /* uint16_t ui16 */
2138                 BTF_MEMBER_ENC(NAME_TBD, 12, 64),       /* int32_t si32 */
2139                 BTF_MEMBER_ENC(NAME_TBD, 6, 96),        /* unused_bits2a */
2140                 BTF_MEMBER_ENC(NAME_TBD, 7, 98),        /* bits28 */
2141                 BTF_MEMBER_ENC(NAME_TBD, 6, 126),       /* unused_bits2b */
2142                 BTF_MEMBER_ENC(0, 14, 128),             /* union (anon) */
2143                 BTF_MEMBER_ENC(NAME_TBD, 15, 192),      /* aenum */
2144                 BTF_END_RAW,
2145         },
2146         .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",
2147         .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"),
2148         .key_size = sizeof(unsigned int),
2149         .value_size = sizeof(struct pprint_mapv),
2150         .key_type_id = 3,       /* unsigned int */
2151         .value_type_id = 16,    /* struct pprint_mapv */
2152         .max_entries = 128 * 1024,
2153 };
2154
2155 static struct btf_pprint_test_meta {
2156         const char *descr;
2157         enum bpf_map_type map_type;
2158         const char *map_name;
2159         bool ordered_map;
2160         bool lossless_map;
2161         bool percpu_map;
2162 } pprint_tests_meta[] = {
2163 {
2164         .descr = "BTF pretty print array",
2165         .map_type = BPF_MAP_TYPE_ARRAY,
2166         .map_name = "pprint_test_array",
2167         .ordered_map = true,
2168         .lossless_map = true,
2169         .percpu_map = false,
2170 },
2171
2172 {
2173         .descr = "BTF pretty print hash",
2174         .map_type = BPF_MAP_TYPE_HASH,
2175         .map_name = "pprint_test_hash",
2176         .ordered_map = false,
2177         .lossless_map = true,
2178         .percpu_map = false,
2179 },
2180
2181 {
2182         .descr = "BTF pretty print lru hash",
2183         .map_type = BPF_MAP_TYPE_LRU_HASH,
2184         .map_name = "pprint_test_lru_hash",
2185         .ordered_map = false,
2186         .lossless_map = false,
2187         .percpu_map = false,
2188 },
2189
2190 {
2191         .descr = "BTF pretty print percpu array",
2192         .map_type = BPF_MAP_TYPE_PERCPU_ARRAY,
2193         .map_name = "pprint_test_percpu_array",
2194         .ordered_map = true,
2195         .lossless_map = true,
2196         .percpu_map = true,
2197 },
2198
2199 {
2200         .descr = "BTF pretty print percpu hash",
2201         .map_type = BPF_MAP_TYPE_PERCPU_HASH,
2202         .map_name = "pprint_test_percpu_hash",
2203         .ordered_map = false,
2204         .lossless_map = true,
2205         .percpu_map = true,
2206 },
2207
2208 {
2209         .descr = "BTF pretty print lru percpu hash",
2210         .map_type = BPF_MAP_TYPE_LRU_PERCPU_HASH,
2211         .map_name = "pprint_test_lru_percpu_hash",
2212         .ordered_map = false,
2213         .lossless_map = false,
2214         .percpu_map = true,
2215 },
2216
2217 };
2218
2219
2220 static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
2221                             int num_cpus, int rounded_value_size)
2222 {
2223         int cpu;
2224
2225         for (cpu = 0; cpu < num_cpus; cpu++) {
2226                 v->ui32 = i + cpu;
2227                 v->si32 = -i;
2228                 v->unused_bits2a = 3;
2229                 v->bits28 = i;
2230                 v->unused_bits2b = 3;
2231                 v->ui64 = i;
2232                 v->aenum = i & 0x03;
2233                 v = (void *)v + rounded_value_size;
2234         }
2235 }
2236
2237 static int check_line(const char *expected_line, int nexpected_line,
2238                       int expected_line_len, const char *line)
2239 {
2240         if (CHECK(nexpected_line == expected_line_len,
2241                   "expected_line is too long"))
2242                 return -1;
2243
2244         if (strcmp(expected_line, line)) {
2245                 fprintf(stderr, "unexpected pprint output\n");
2246                 fprintf(stderr, "expected: %s", expected_line);
2247                 fprintf(stderr, "    read: %s", line);
2248                 return -1;
2249         }
2250
2251         return 0;
2252 }
2253
2254
2255 static int do_test_pprint(void)
2256 {
2257         const struct btf_raw_test *test = &pprint_test_template;
2258         struct bpf_create_map_attr create_attr = {};
2259         bool ordered_map, lossless_map, percpu_map;
2260         int err, ret, num_cpus, rounded_value_size;
2261         struct pprint_mapv *mapv = NULL;
2262         unsigned int key, nr_read_elems;
2263         int map_fd = -1, btf_fd = -1;
2264         unsigned int raw_btf_size;
2265         char expected_line[255];
2266         FILE *pin_file = NULL;
2267         char pin_path[255];
2268         size_t line_len = 0;
2269         char *line = NULL;
2270         uint8_t *raw_btf;
2271         ssize_t nread;
2272
2273         fprintf(stderr, "%s......", test->descr);
2274         raw_btf = btf_raw_create(&hdr_tmpl, test->raw_types,
2275                                  test->str_sec, test->str_sec_size,
2276                                  &raw_btf_size);
2277
2278         if (!raw_btf)
2279                 return -1;
2280
2281         *btf_log_buf = '\0';
2282         btf_fd = bpf_load_btf(raw_btf, raw_btf_size,
2283                               btf_log_buf, BTF_LOG_BUF_SIZE,
2284                               args.always_log);
2285         free(raw_btf);
2286
2287         if (CHECK(btf_fd == -1, "errno:%d", errno)) {
2288                 err = -1;
2289                 goto done;
2290         }
2291
2292         create_attr.name = test->map_name;
2293         create_attr.map_type = test->map_type;
2294         create_attr.key_size = test->key_size;
2295         create_attr.value_size = test->value_size;
2296         create_attr.max_entries = test->max_entries;
2297         create_attr.btf_fd = btf_fd;
2298         create_attr.btf_key_type_id = test->key_type_id;
2299         create_attr.btf_value_type_id = test->value_type_id;
2300
2301         map_fd = bpf_create_map_xattr(&create_attr);
2302         if (CHECK(map_fd == -1, "errno:%d", errno)) {
2303                 err = -1;
2304                 goto done;
2305         }
2306
2307         ret = snprintf(pin_path, sizeof(pin_path), "%s/%s",
2308                        "/sys/fs/bpf", test->map_name);
2309
2310         if (CHECK(ret == sizeof(pin_path), "pin_path %s/%s is too long",
2311                   "/sys/fs/bpf", test->map_name)) {
2312                 err = -1;
2313                 goto done;
2314         }
2315
2316         err = bpf_obj_pin(map_fd, pin_path);
2317         if (CHECK(err, "bpf_obj_pin(%s): errno:%d.", pin_path, errno))
2318                 goto done;
2319
2320         percpu_map = test->percpu_map;
2321         num_cpus = percpu_map ? bpf_num_possible_cpus() : 1;
2322         rounded_value_size = round_up(sizeof(struct pprint_mapv), 8);
2323         mapv = calloc(num_cpus, rounded_value_size);
2324         if (CHECK(!mapv, "mapv allocation failure")) {
2325                 err = -1;
2326                 goto done;
2327         }
2328
2329         for (key = 0; key < test->max_entries; key++) {
2330                 set_pprint_mapv(mapv, key, num_cpus, rounded_value_size);
2331                 bpf_map_update_elem(map_fd, &key, mapv, 0);
2332         }
2333
2334         pin_file = fopen(pin_path, "r");
2335         if (CHECK(!pin_file, "fopen(%s): errno:%d", pin_path, errno)) {
2336                 err = -1;
2337                 goto done;
2338         }
2339
2340         /* Skip lines start with '#' */
2341         while ((nread = getline(&line, &line_len, pin_file)) > 0 &&
2342                *line == '#')
2343                 ;
2344
2345         if (CHECK(nread <= 0, "Unexpected EOF")) {
2346                 err = -1;
2347                 goto done;
2348         }
2349
2350         nr_read_elems = 0;
2351         ordered_map = test->ordered_map;
2352         lossless_map = test->lossless_map;
2353         do {
2354                 struct pprint_mapv *cmapv;
2355                 ssize_t nexpected_line;
2356                 unsigned int next_key;
2357                 int cpu;
2358
2359                 next_key = ordered_map ? nr_read_elems : atoi(line);
2360                 set_pprint_mapv(mapv, next_key, num_cpus, rounded_value_size);
2361                 cmapv = mapv;
2362
2363                 for (cpu = 0; cpu < num_cpus; cpu++) {
2364                         if (percpu_map) {
2365                                 /* for percpu map, the format looks like:
2366                                  * <key>: {
2367                                  *      cpu0: <value_on_cpu0>
2368                                  *      cpu1: <value_on_cpu1>
2369                                  *      ...
2370                                  *      cpun: <value_on_cpun>
2371                                  * }
2372                                  *
2373                                  * let us verify the line containing the key here.
2374                                  */
2375                                 if (cpu == 0) {
2376                                         nexpected_line = snprintf(expected_line,
2377                                                                   sizeof(expected_line),
2378                                                                   "%u: {\n",
2379                                                                   next_key);
2380
2381                                         err = check_line(expected_line, nexpected_line,
2382                                                          sizeof(expected_line), line);
2383                                         if (err == -1)
2384                                                 goto done;
2385                                 }
2386
2387                                 /* read value@cpu */
2388                                 nread = getline(&line, &line_len, pin_file);
2389                                 if (nread < 0)
2390                                         break;
2391                         }
2392
2393                         nexpected_line = snprintf(expected_line, sizeof(expected_line),
2394                                                   "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
2395                                                   "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
2396                                                   percpu_map ? "\tcpu" : "",
2397                                                   percpu_map ? cpu : next_key,
2398                                                   cmapv->ui32, cmapv->si32,
2399                                                   cmapv->unused_bits2a,
2400                                                   cmapv->bits28,
2401                                                   cmapv->unused_bits2b,
2402                                                   cmapv->ui64,
2403                                                   cmapv->ui8a[0], cmapv->ui8a[1],
2404                                                   cmapv->ui8a[2], cmapv->ui8a[3],
2405                                                   cmapv->ui8a[4], cmapv->ui8a[5],
2406                                                   cmapv->ui8a[6], cmapv->ui8a[7],
2407                                                   pprint_enum_str[cmapv->aenum]);
2408
2409                         err = check_line(expected_line, nexpected_line,
2410                                          sizeof(expected_line), line);
2411                         if (err == -1)
2412                                 goto done;
2413
2414                         cmapv = (void *)cmapv + rounded_value_size;
2415                 }
2416
2417                 if (percpu_map) {
2418                         /* skip the last bracket for the percpu map */
2419                         nread = getline(&line, &line_len, pin_file);
2420                         if (nread < 0)
2421                                 break;
2422                 }
2423
2424                 nread = getline(&line, &line_len, pin_file);
2425         } while (++nr_read_elems < test->max_entries && nread > 0);
2426
2427         if (lossless_map &&
2428             CHECK(nr_read_elems < test->max_entries,
2429                   "Unexpected EOF. nr_read_elems:%u test->max_entries:%u",
2430                   nr_read_elems, test->max_entries)) {
2431                 err = -1;
2432                 goto done;
2433         }
2434
2435         if (CHECK(nread > 0, "Unexpected extra pprint output: %s", line)) {
2436                 err = -1;
2437                 goto done;
2438         }
2439
2440         err = 0;
2441
2442 done:
2443         if (mapv)
2444                 free(mapv);
2445         if (!err)
2446                 fprintf(stderr, "OK");
2447         if (*btf_log_buf && (err || args.always_log))
2448                 fprintf(stderr, "\n%s", btf_log_buf);
2449         if (btf_fd != -1)
2450                 close(btf_fd);
2451         if (map_fd != -1)
2452                 close(map_fd);
2453         if (pin_file)
2454                 fclose(pin_file);
2455         unlink(pin_path);
2456         free(line);
2457
2458         return err;
2459 }
2460
2461 static int test_pprint(void)
2462 {
2463         unsigned int i;
2464         int err = 0;
2465
2466         for (i = 0; i < ARRAY_SIZE(pprint_tests_meta); i++) {
2467                 pprint_test_template.descr = pprint_tests_meta[i].descr;
2468                 pprint_test_template.map_type = pprint_tests_meta[i].map_type;
2469                 pprint_test_template.map_name = pprint_tests_meta[i].map_name;
2470                 pprint_test_template.ordered_map = pprint_tests_meta[i].ordered_map;
2471                 pprint_test_template.lossless_map = pprint_tests_meta[i].lossless_map;
2472                 pprint_test_template.percpu_map = pprint_tests_meta[i].percpu_map;
2473
2474                 err |= count_result(do_test_pprint());
2475         }
2476
2477         return err;
2478 }
2479
2480 static void usage(const char *cmd)
2481 {
2482         fprintf(stderr, "Usage: %s [-l] [[-r test_num (1 - %zu)] | [-g test_num (1 - %zu)] | [-f test_num (1 - %zu)] | [-p]]\n",
2483                 cmd, ARRAY_SIZE(raw_tests), ARRAY_SIZE(get_info_tests),
2484                 ARRAY_SIZE(file_tests));
2485 }
2486
2487 static int parse_args(int argc, char **argv)
2488 {
2489         const char *optstr = "lpf:r:g:";
2490         int opt;
2491
2492         while ((opt = getopt(argc, argv, optstr)) != -1) {
2493                 switch (opt) {
2494                 case 'l':
2495                         args.always_log = true;
2496                         break;
2497                 case 'f':
2498                         args.file_test_num = atoi(optarg);
2499                         args.file_test = true;
2500                         break;
2501                 case 'r':
2502                         args.raw_test_num = atoi(optarg);
2503                         args.raw_test = true;
2504                         break;
2505                 case 'g':
2506                         args.get_info_test_num = atoi(optarg);
2507                         args.get_info_test = true;
2508                         break;
2509                 case 'p':
2510                         args.pprint_test = true;
2511                         break;
2512                 case 'h':
2513                         usage(argv[0]);
2514                         exit(0);
2515                 default:
2516                                 usage(argv[0]);
2517                                 return -1;
2518                 }
2519         }
2520
2521         if (args.raw_test_num &&
2522             (args.raw_test_num < 1 ||
2523              args.raw_test_num > ARRAY_SIZE(raw_tests))) {
2524                 fprintf(stderr, "BTF raw test number must be [1 - %zu]\n",
2525                         ARRAY_SIZE(raw_tests));
2526                 return -1;
2527         }
2528
2529         if (args.file_test_num &&
2530             (args.file_test_num < 1 ||
2531              args.file_test_num > ARRAY_SIZE(file_tests))) {
2532                 fprintf(stderr, "BTF file test number must be [1 - %zu]\n",
2533                         ARRAY_SIZE(file_tests));
2534                 return -1;
2535         }
2536
2537         if (args.get_info_test_num &&
2538             (args.get_info_test_num < 1 ||
2539              args.get_info_test_num > ARRAY_SIZE(get_info_tests))) {
2540                 fprintf(stderr, "BTF get info test number must be [1 - %zu]\n",
2541                         ARRAY_SIZE(get_info_tests));
2542                 return -1;
2543         }
2544
2545         return 0;
2546 }
2547
2548 static void print_summary(void)
2549 {
2550         fprintf(stderr, "PASS:%u SKIP:%u FAIL:%u\n",
2551                 pass_cnt - skip_cnt, skip_cnt, error_cnt);
2552 }
2553
2554 int main(int argc, char **argv)
2555 {
2556         int err = 0;
2557
2558         err = parse_args(argc, argv);
2559         if (err)
2560                 return err;
2561
2562         if (args.always_log)
2563                 libbpf_set_print(__base_pr, __base_pr, __base_pr);
2564
2565         if (args.raw_test)
2566                 err |= test_raw();
2567
2568         if (args.get_info_test)
2569                 err |= test_get_info();
2570
2571         if (args.file_test)
2572                 err |= test_file();
2573
2574         if (args.pprint_test)
2575                 err |= test_pprint();
2576
2577         if (args.raw_test || args.get_info_test || args.file_test ||
2578             args.pprint_test)
2579                 goto done;
2580
2581         err |= test_raw();
2582         err |= test_get_info();
2583         err |= test_file();
2584
2585 done:
2586         print_summary();
2587         return err;
2588 }