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