tools: bpftool: Document and add bash completion for -L, -B options
[linux-2.6-microblaze.git] / tools / bpf / bpftool / btf.c
1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2019 Facebook */
3
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/err.h>
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <bpf/bpf.h>
12 #include <bpf/btf.h>
13 #include <bpf/libbpf.h>
14 #include <linux/btf.h>
15 #include <linux/hashtable.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18
19 #include "json_writer.h"
20 #include "main.h"
21
22 static const char * const btf_kind_str[NR_BTF_KINDS] = {
23         [BTF_KIND_UNKN]         = "UNKNOWN",
24         [BTF_KIND_INT]          = "INT",
25         [BTF_KIND_PTR]          = "PTR",
26         [BTF_KIND_ARRAY]        = "ARRAY",
27         [BTF_KIND_STRUCT]       = "STRUCT",
28         [BTF_KIND_UNION]        = "UNION",
29         [BTF_KIND_ENUM]         = "ENUM",
30         [BTF_KIND_FWD]          = "FWD",
31         [BTF_KIND_TYPEDEF]      = "TYPEDEF",
32         [BTF_KIND_VOLATILE]     = "VOLATILE",
33         [BTF_KIND_CONST]        = "CONST",
34         [BTF_KIND_RESTRICT]     = "RESTRICT",
35         [BTF_KIND_FUNC]         = "FUNC",
36         [BTF_KIND_FUNC_PROTO]   = "FUNC_PROTO",
37         [BTF_KIND_VAR]          = "VAR",
38         [BTF_KIND_DATASEC]      = "DATASEC",
39         [BTF_KIND_FLOAT]        = "FLOAT",
40 };
41
42 struct btf_attach_table {
43         DECLARE_HASHTABLE(table, 16);
44 };
45
46 struct btf_attach_point {
47         __u32 obj_id;
48         __u32 btf_id;
49         struct hlist_node hash;
50 };
51
52 static const char *btf_int_enc_str(__u8 encoding)
53 {
54         switch (encoding) {
55         case 0:
56                 return "(none)";
57         case BTF_INT_SIGNED:
58                 return "SIGNED";
59         case BTF_INT_CHAR:
60                 return "CHAR";
61         case BTF_INT_BOOL:
62                 return "BOOL";
63         default:
64                 return "UNKN";
65         }
66 }
67
68 static const char *btf_var_linkage_str(__u32 linkage)
69 {
70         switch (linkage) {
71         case BTF_VAR_STATIC:
72                 return "static";
73         case BTF_VAR_GLOBAL_ALLOCATED:
74                 return "global";
75         case BTF_VAR_GLOBAL_EXTERN:
76                 return "extern";
77         default:
78                 return "(unknown)";
79         }
80 }
81
82 static const char *btf_func_linkage_str(const struct btf_type *t)
83 {
84         switch (btf_vlen(t)) {
85         case BTF_FUNC_STATIC:
86                 return "static";
87         case BTF_FUNC_GLOBAL:
88                 return "global";
89         case BTF_FUNC_EXTERN:
90                 return "extern";
91         default:
92                 return "(unknown)";
93         }
94 }
95
96 static const char *btf_str(const struct btf *btf, __u32 off)
97 {
98         if (!off)
99                 return "(anon)";
100         return btf__name_by_offset(btf, off) ? : "(invalid)";
101 }
102
103 static int btf_kind_safe(int kind)
104 {
105         return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
106 }
107
108 static int dump_btf_type(const struct btf *btf, __u32 id,
109                          const struct btf_type *t)
110 {
111         json_writer_t *w = json_wtr;
112         int kind = btf_kind(t);
113
114         if (json_output) {
115                 jsonw_start_object(w);
116                 jsonw_uint_field(w, "id", id);
117                 jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]);
118                 jsonw_string_field(w, "name", btf_str(btf, t->name_off));
119         } else {
120                 printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)],
121                        btf_str(btf, t->name_off));
122         }
123
124         switch (kind) {
125         case BTF_KIND_INT: {
126                 __u32 v = *(__u32 *)(t + 1);
127                 const char *enc;
128
129                 enc = btf_int_enc_str(BTF_INT_ENCODING(v));
130
131                 if (json_output) {
132                         jsonw_uint_field(w, "size", t->size);
133                         jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
134                         jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
135                         jsonw_string_field(w, "encoding", enc);
136                 } else {
137                         printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
138                                t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
139                                enc);
140                 }
141                 break;
142         }
143         case BTF_KIND_PTR:
144         case BTF_KIND_CONST:
145         case BTF_KIND_VOLATILE:
146         case BTF_KIND_RESTRICT:
147         case BTF_KIND_TYPEDEF:
148                 if (json_output)
149                         jsonw_uint_field(w, "type_id", t->type);
150                 else
151                         printf(" type_id=%u", t->type);
152                 break;
153         case BTF_KIND_ARRAY: {
154                 const struct btf_array *arr = (const void *)(t + 1);
155
156                 if (json_output) {
157                         jsonw_uint_field(w, "type_id", arr->type);
158                         jsonw_uint_field(w, "index_type_id", arr->index_type);
159                         jsonw_uint_field(w, "nr_elems", arr->nelems);
160                 } else {
161                         printf(" type_id=%u index_type_id=%u nr_elems=%u",
162                                arr->type, arr->index_type, arr->nelems);
163                 }
164                 break;
165         }
166         case BTF_KIND_STRUCT:
167         case BTF_KIND_UNION: {
168                 const struct btf_member *m = (const void *)(t + 1);
169                 __u16 vlen = BTF_INFO_VLEN(t->info);
170                 int i;
171
172                 if (json_output) {
173                         jsonw_uint_field(w, "size", t->size);
174                         jsonw_uint_field(w, "vlen", vlen);
175                         jsonw_name(w, "members");
176                         jsonw_start_array(w);
177                 } else {
178                         printf(" size=%u vlen=%u", t->size, vlen);
179                 }
180                 for (i = 0; i < vlen; i++, m++) {
181                         const char *name = btf_str(btf, m->name_off);
182                         __u32 bit_off, bit_sz;
183
184                         if (BTF_INFO_KFLAG(t->info)) {
185                                 bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
186                                 bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
187                         } else {
188                                 bit_off = m->offset;
189                                 bit_sz = 0;
190                         }
191
192                         if (json_output) {
193                                 jsonw_start_object(w);
194                                 jsonw_string_field(w, "name", name);
195                                 jsonw_uint_field(w, "type_id", m->type);
196                                 jsonw_uint_field(w, "bits_offset", bit_off);
197                                 if (bit_sz) {
198                                         jsonw_uint_field(w, "bitfield_size",
199                                                          bit_sz);
200                                 }
201                                 jsonw_end_object(w);
202                         } else {
203                                 printf("\n\t'%s' type_id=%u bits_offset=%u",
204                                        name, m->type, bit_off);
205                                 if (bit_sz)
206                                         printf(" bitfield_size=%u", bit_sz);
207                         }
208                 }
209                 if (json_output)
210                         jsonw_end_array(w);
211                 break;
212         }
213         case BTF_KIND_ENUM: {
214                 const struct btf_enum *v = (const void *)(t + 1);
215                 __u16 vlen = BTF_INFO_VLEN(t->info);
216                 int i;
217
218                 if (json_output) {
219                         jsonw_uint_field(w, "size", t->size);
220                         jsonw_uint_field(w, "vlen", vlen);
221                         jsonw_name(w, "values");
222                         jsonw_start_array(w);
223                 } else {
224                         printf(" size=%u vlen=%u", t->size, vlen);
225                 }
226                 for (i = 0; i < vlen; i++, v++) {
227                         const char *name = btf_str(btf, v->name_off);
228
229                         if (json_output) {
230                                 jsonw_start_object(w);
231                                 jsonw_string_field(w, "name", name);
232                                 jsonw_uint_field(w, "val", v->val);
233                                 jsonw_end_object(w);
234                         } else {
235                                 printf("\n\t'%s' val=%u", name, v->val);
236                         }
237                 }
238                 if (json_output)
239                         jsonw_end_array(w);
240                 break;
241         }
242         case BTF_KIND_FWD: {
243                 const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
244                                                                : "struct";
245
246                 if (json_output)
247                         jsonw_string_field(w, "fwd_kind", fwd_kind);
248                 else
249                         printf(" fwd_kind=%s", fwd_kind);
250                 break;
251         }
252         case BTF_KIND_FUNC: {
253                 const char *linkage = btf_func_linkage_str(t);
254
255                 if (json_output) {
256                         jsonw_uint_field(w, "type_id", t->type);
257                         jsonw_string_field(w, "linkage", linkage);
258                 } else {
259                         printf(" type_id=%u linkage=%s", t->type, linkage);
260                 }
261                 break;
262         }
263         case BTF_KIND_FUNC_PROTO: {
264                 const struct btf_param *p = (const void *)(t + 1);
265                 __u16 vlen = BTF_INFO_VLEN(t->info);
266                 int i;
267
268                 if (json_output) {
269                         jsonw_uint_field(w, "ret_type_id", t->type);
270                         jsonw_uint_field(w, "vlen", vlen);
271                         jsonw_name(w, "params");
272                         jsonw_start_array(w);
273                 } else {
274                         printf(" ret_type_id=%u vlen=%u", t->type, vlen);
275                 }
276                 for (i = 0; i < vlen; i++, p++) {
277                         const char *name = btf_str(btf, p->name_off);
278
279                         if (json_output) {
280                                 jsonw_start_object(w);
281                                 jsonw_string_field(w, "name", name);
282                                 jsonw_uint_field(w, "type_id", p->type);
283                                 jsonw_end_object(w);
284                         } else {
285                                 printf("\n\t'%s' type_id=%u", name, p->type);
286                         }
287                 }
288                 if (json_output)
289                         jsonw_end_array(w);
290                 break;
291         }
292         case BTF_KIND_VAR: {
293                 const struct btf_var *v = (const void *)(t + 1);
294                 const char *linkage;
295
296                 linkage = btf_var_linkage_str(v->linkage);
297
298                 if (json_output) {
299                         jsonw_uint_field(w, "type_id", t->type);
300                         jsonw_string_field(w, "linkage", linkage);
301                 } else {
302                         printf(" type_id=%u, linkage=%s", t->type, linkage);
303                 }
304                 break;
305         }
306         case BTF_KIND_DATASEC: {
307                 const struct btf_var_secinfo *v = (const void *)(t + 1);
308                 const struct btf_type *vt;
309                 __u16 vlen = BTF_INFO_VLEN(t->info);
310                 int i;
311
312                 if (json_output) {
313                         jsonw_uint_field(w, "size", t->size);
314                         jsonw_uint_field(w, "vlen", vlen);
315                         jsonw_name(w, "vars");
316                         jsonw_start_array(w);
317                 } else {
318                         printf(" size=%u vlen=%u", t->size, vlen);
319                 }
320                 for (i = 0; i < vlen; i++, v++) {
321                         if (json_output) {
322                                 jsonw_start_object(w);
323                                 jsonw_uint_field(w, "type_id", v->type);
324                                 jsonw_uint_field(w, "offset", v->offset);
325                                 jsonw_uint_field(w, "size", v->size);
326                                 jsonw_end_object(w);
327                         } else {
328                                 printf("\n\ttype_id=%u offset=%u size=%u",
329                                        v->type, v->offset, v->size);
330
331                                 if (v->type <= btf__get_nr_types(btf)) {
332                                         vt = btf__type_by_id(btf, v->type);
333                                         printf(" (%s '%s')",
334                                                btf_kind_str[btf_kind_safe(btf_kind(vt))],
335                                                btf_str(btf, vt->name_off));
336                                 }
337                         }
338                 }
339                 if (json_output)
340                         jsonw_end_array(w);
341                 break;
342         }
343         case BTF_KIND_FLOAT: {
344                 if (json_output)
345                         jsonw_uint_field(w, "size", t->size);
346                 else
347                         printf(" size=%u", t->size);
348                 break;
349         }
350         default:
351                 break;
352         }
353
354         if (json_output)
355                 jsonw_end_object(json_wtr);
356         else
357                 printf("\n");
358
359         return 0;
360 }
361
362 static int dump_btf_raw(const struct btf *btf,
363                         __u32 *root_type_ids, int root_type_cnt)
364 {
365         const struct btf_type *t;
366         int i;
367
368         if (json_output) {
369                 jsonw_start_object(json_wtr);
370                 jsonw_name(json_wtr, "types");
371                 jsonw_start_array(json_wtr);
372         }
373
374         if (root_type_cnt) {
375                 for (i = 0; i < root_type_cnt; i++) {
376                         t = btf__type_by_id(btf, root_type_ids[i]);
377                         dump_btf_type(btf, root_type_ids[i], t);
378                 }
379         } else {
380                 const struct btf *base;
381                 int cnt = btf__get_nr_types(btf);
382                 int start_id = 1;
383
384                 base = btf__base_btf(btf);
385                 if (base)
386                         start_id = btf__get_nr_types(base) + 1;
387
388                 for (i = start_id; i <= cnt; i++) {
389                         t = btf__type_by_id(btf, i);
390                         dump_btf_type(btf, i, t);
391                 }
392         }
393
394         if (json_output) {
395                 jsonw_end_array(json_wtr);
396                 jsonw_end_object(json_wtr);
397         }
398         return 0;
399 }
400
401 static void __printf(2, 0) btf_dump_printf(void *ctx,
402                                            const char *fmt, va_list args)
403 {
404         vfprintf(stdout, fmt, args);
405 }
406
407 static int dump_btf_c(const struct btf *btf,
408                       __u32 *root_type_ids, int root_type_cnt)
409 {
410         struct btf_dump *d;
411         int err = 0, i;
412
413         d = btf_dump__new(btf, NULL, NULL, btf_dump_printf);
414         if (IS_ERR(d))
415                 return PTR_ERR(d);
416
417         printf("#ifndef __VMLINUX_H__\n");
418         printf("#define __VMLINUX_H__\n");
419         printf("\n");
420         printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
421         printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
422         printf("#endif\n\n");
423
424         if (root_type_cnt) {
425                 for (i = 0; i < root_type_cnt; i++) {
426                         err = btf_dump__dump_type(d, root_type_ids[i]);
427                         if (err)
428                                 goto done;
429                 }
430         } else {
431                 int cnt = btf__get_nr_types(btf);
432
433                 for (i = 1; i <= cnt; i++) {
434                         err = btf_dump__dump_type(d, i);
435                         if (err)
436                                 goto done;
437                 }
438         }
439
440         printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
441         printf("#pragma clang attribute pop\n");
442         printf("#endif\n");
443         printf("\n");
444         printf("#endif /* __VMLINUX_H__ */\n");
445
446 done:
447         btf_dump__free(d);
448         return err;
449 }
450
451 static int do_dump(int argc, char **argv)
452 {
453         struct btf *btf = NULL, *base = NULL;
454         __u32 root_type_ids[2];
455         int root_type_cnt = 0;
456         bool dump_c = false;
457         __u32 btf_id = -1;
458         const char *src;
459         int fd = -1;
460         int err;
461
462         if (!REQ_ARGS(2)) {
463                 usage();
464                 return -1;
465         }
466         src = GET_ARG();
467         if (is_prefix(src, "map")) {
468                 struct bpf_map_info info = {};
469                 __u32 len = sizeof(info);
470
471                 if (!REQ_ARGS(2)) {
472                         usage();
473                         return -1;
474                 }
475
476                 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
477                 if (fd < 0)
478                         return -1;
479
480                 btf_id = info.btf_id;
481                 if (argc && is_prefix(*argv, "key")) {
482                         root_type_ids[root_type_cnt++] = info.btf_key_type_id;
483                         NEXT_ARG();
484                 } else if (argc && is_prefix(*argv, "value")) {
485                         root_type_ids[root_type_cnt++] = info.btf_value_type_id;
486                         NEXT_ARG();
487                 } else if (argc && is_prefix(*argv, "all")) {
488                         NEXT_ARG();
489                 } else if (argc && is_prefix(*argv, "kv")) {
490                         root_type_ids[root_type_cnt++] = info.btf_key_type_id;
491                         root_type_ids[root_type_cnt++] = info.btf_value_type_id;
492                         NEXT_ARG();
493                 } else {
494                         root_type_ids[root_type_cnt++] = info.btf_key_type_id;
495                         root_type_ids[root_type_cnt++] = info.btf_value_type_id;
496                 }
497         } else if (is_prefix(src, "prog")) {
498                 struct bpf_prog_info info = {};
499                 __u32 len = sizeof(info);
500
501                 if (!REQ_ARGS(2)) {
502                         usage();
503                         return -1;
504                 }
505
506                 fd = prog_parse_fd(&argc, &argv);
507                 if (fd < 0)
508                         return -1;
509
510                 err = bpf_obj_get_info_by_fd(fd, &info, &len);
511                 if (err) {
512                         p_err("can't get prog info: %s", strerror(errno));
513                         goto done;
514                 }
515
516                 btf_id = info.btf_id;
517         } else if (is_prefix(src, "id")) {
518                 char *endptr;
519
520                 btf_id = strtoul(*argv, &endptr, 0);
521                 if (*endptr) {
522                         p_err("can't parse %s as ID", *argv);
523                         return -1;
524                 }
525                 NEXT_ARG();
526         } else if (is_prefix(src, "file")) {
527                 const char sysfs_prefix[] = "/sys/kernel/btf/";
528                 const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
529
530                 if (!base_btf &&
531                     strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
532                     strcmp(*argv, sysfs_vmlinux) != 0) {
533                         base = btf__parse(sysfs_vmlinux, NULL);
534                         if (libbpf_get_error(base)) {
535                                 p_err("failed to parse vmlinux BTF at '%s': %ld\n",
536                                       sysfs_vmlinux, libbpf_get_error(base));
537                                 base = NULL;
538                         }
539                 }
540
541                 btf = btf__parse_split(*argv, base ?: base_btf);
542                 if (IS_ERR(btf)) {
543                         err = -PTR_ERR(btf);
544                         btf = NULL;
545                         p_err("failed to load BTF from %s: %s",
546                               *argv, strerror(err));
547                         goto done;
548                 }
549                 NEXT_ARG();
550         } else {
551                 err = -1;
552                 p_err("unrecognized BTF source specifier: '%s'", src);
553                 goto done;
554         }
555
556         while (argc) {
557                 if (is_prefix(*argv, "format")) {
558                         NEXT_ARG();
559                         if (argc < 1) {
560                                 p_err("expecting value for 'format' option\n");
561                                 err = -EINVAL;
562                                 goto done;
563                         }
564                         if (strcmp(*argv, "c") == 0) {
565                                 dump_c = true;
566                         } else if (strcmp(*argv, "raw") == 0) {
567                                 dump_c = false;
568                         } else {
569                                 p_err("unrecognized format specifier: '%s', possible values: raw, c",
570                                       *argv);
571                                 err = -EINVAL;
572                                 goto done;
573                         }
574                         NEXT_ARG();
575                 } else {
576                         p_err("unrecognized option: '%s'", *argv);
577                         err = -EINVAL;
578                         goto done;
579                 }
580         }
581
582         if (!btf) {
583                 btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
584                 err = libbpf_get_error(btf);
585                 if (err) {
586                         p_err("get btf by id (%u): %s", btf_id, strerror(err));
587                         goto done;
588                 }
589         }
590
591         if (dump_c) {
592                 if (json_output) {
593                         p_err("JSON output for C-syntax dump is not supported");
594                         err = -ENOTSUP;
595                         goto done;
596                 }
597                 err = dump_btf_c(btf, root_type_ids, root_type_cnt);
598         } else {
599                 err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
600         }
601
602 done:
603         close(fd);
604         btf__free(btf);
605         btf__free(base);
606         return err;
607 }
608
609 static int btf_parse_fd(int *argc, char ***argv)
610 {
611         unsigned int id;
612         char *endptr;
613         int fd;
614
615         if (!is_prefix(*argv[0], "id")) {
616                 p_err("expected 'id', got: '%s'?", **argv);
617                 return -1;
618         }
619         NEXT_ARGP();
620
621         id = strtoul(**argv, &endptr, 0);
622         if (*endptr) {
623                 p_err("can't parse %s as ID", **argv);
624                 return -1;
625         }
626         NEXT_ARGP();
627
628         fd = bpf_btf_get_fd_by_id(id);
629         if (fd < 0)
630                 p_err("can't get BTF object by id (%u): %s",
631                       id, strerror(errno));
632
633         return fd;
634 }
635
636 static void delete_btf_table(struct btf_attach_table *tab)
637 {
638         struct btf_attach_point *obj;
639         struct hlist_node *tmp;
640
641         unsigned int bkt;
642
643         hash_for_each_safe(tab->table, bkt, tmp, obj, hash) {
644                 hash_del(&obj->hash);
645                 free(obj);
646         }
647 }
648
649 static int
650 build_btf_type_table(struct btf_attach_table *tab, enum bpf_obj_type type,
651                      void *info, __u32 *len)
652 {
653         static const char * const names[] = {
654                 [BPF_OBJ_UNKNOWN]       = "unknown",
655                 [BPF_OBJ_PROG]          = "prog",
656                 [BPF_OBJ_MAP]           = "map",
657         };
658         struct btf_attach_point *obj_node;
659         __u32 btf_id, id = 0;
660         int err;
661         int fd;
662
663         while (true) {
664                 switch (type) {
665                 case BPF_OBJ_PROG:
666                         err = bpf_prog_get_next_id(id, &id);
667                         break;
668                 case BPF_OBJ_MAP:
669                         err = bpf_map_get_next_id(id, &id);
670                         break;
671                 default:
672                         err = -1;
673                         p_err("unexpected object type: %d", type);
674                         goto err_free;
675                 }
676                 if (err) {
677                         if (errno == ENOENT) {
678                                 err = 0;
679                                 break;
680                         }
681                         p_err("can't get next %s: %s%s", names[type],
682                               strerror(errno),
683                               errno == EINVAL ? " -- kernel too old?" : "");
684                         goto err_free;
685                 }
686
687                 switch (type) {
688                 case BPF_OBJ_PROG:
689                         fd = bpf_prog_get_fd_by_id(id);
690                         break;
691                 case BPF_OBJ_MAP:
692                         fd = bpf_map_get_fd_by_id(id);
693                         break;
694                 default:
695                         err = -1;
696                         p_err("unexpected object type: %d", type);
697                         goto err_free;
698                 }
699                 if (fd < 0) {
700                         if (errno == ENOENT)
701                                 continue;
702                         p_err("can't get %s by id (%u): %s", names[type], id,
703                               strerror(errno));
704                         err = -1;
705                         goto err_free;
706                 }
707
708                 memset(info, 0, *len);
709                 err = bpf_obj_get_info_by_fd(fd, info, len);
710                 close(fd);
711                 if (err) {
712                         p_err("can't get %s info: %s", names[type],
713                               strerror(errno));
714                         goto err_free;
715                 }
716
717                 switch (type) {
718                 case BPF_OBJ_PROG:
719                         btf_id = ((struct bpf_prog_info *)info)->btf_id;
720                         break;
721                 case BPF_OBJ_MAP:
722                         btf_id = ((struct bpf_map_info *)info)->btf_id;
723                         break;
724                 default:
725                         err = -1;
726                         p_err("unexpected object type: %d", type);
727                         goto err_free;
728                 }
729                 if (!btf_id)
730                         continue;
731
732                 obj_node = calloc(1, sizeof(*obj_node));
733                 if (!obj_node) {
734                         p_err("failed to allocate memory: %s", strerror(errno));
735                         err = -ENOMEM;
736                         goto err_free;
737                 }
738
739                 obj_node->obj_id = id;
740                 obj_node->btf_id = btf_id;
741                 hash_add(tab->table, &obj_node->hash, obj_node->btf_id);
742         }
743
744         return 0;
745
746 err_free:
747         delete_btf_table(tab);
748         return err;
749 }
750
751 static int
752 build_btf_tables(struct btf_attach_table *btf_prog_table,
753                  struct btf_attach_table *btf_map_table)
754 {
755         struct bpf_prog_info prog_info;
756         __u32 prog_len = sizeof(prog_info);
757         struct bpf_map_info map_info;
758         __u32 map_len = sizeof(map_info);
759         int err = 0;
760
761         err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
762                                    &prog_len);
763         if (err)
764                 return err;
765
766         err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
767                                    &map_len);
768         if (err) {
769                 delete_btf_table(btf_prog_table);
770                 return err;
771         }
772
773         return 0;
774 }
775
776 static void
777 show_btf_plain(struct bpf_btf_info *info, int fd,
778                struct btf_attach_table *btf_prog_table,
779                struct btf_attach_table *btf_map_table)
780 {
781         struct btf_attach_point *obj;
782         const char *name = u64_to_ptr(info->name);
783         int n;
784
785         printf("%u: ", info->id);
786         if (info->kernel_btf)
787                 printf("name [%s]  ", name);
788         else if (name && name[0])
789                 printf("name %s  ", name);
790         else
791                 printf("name <anon>  ");
792         printf("size %uB", info->btf_size);
793
794         n = 0;
795         hash_for_each_possible(btf_prog_table->table, obj, hash, info->id) {
796                 if (obj->btf_id == info->id)
797                         printf("%s%u", n++ == 0 ? "  prog_ids " : ",",
798                                obj->obj_id);
799         }
800
801         n = 0;
802         hash_for_each_possible(btf_map_table->table, obj, hash, info->id) {
803                 if (obj->btf_id == info->id)
804                         printf("%s%u", n++ == 0 ? "  map_ids " : ",",
805                                obj->obj_id);
806         }
807         emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");
808
809         printf("\n");
810 }
811
812 static void
813 show_btf_json(struct bpf_btf_info *info, int fd,
814               struct btf_attach_table *btf_prog_table,
815               struct btf_attach_table *btf_map_table)
816 {
817         struct btf_attach_point *obj;
818         const char *name = u64_to_ptr(info->name);
819
820         jsonw_start_object(json_wtr);   /* btf object */
821         jsonw_uint_field(json_wtr, "id", info->id);
822         jsonw_uint_field(json_wtr, "size", info->btf_size);
823
824         jsonw_name(json_wtr, "prog_ids");
825         jsonw_start_array(json_wtr);    /* prog_ids */
826         hash_for_each_possible(btf_prog_table->table, obj, hash,
827                                info->id) {
828                 if (obj->btf_id == info->id)
829                         jsonw_uint(json_wtr, obj->obj_id);
830         }
831         jsonw_end_array(json_wtr);      /* prog_ids */
832
833         jsonw_name(json_wtr, "map_ids");
834         jsonw_start_array(json_wtr);    /* map_ids */
835         hash_for_each_possible(btf_map_table->table, obj, hash,
836                                info->id) {
837                 if (obj->btf_id == info->id)
838                         jsonw_uint(json_wtr, obj->obj_id);
839         }
840         jsonw_end_array(json_wtr);      /* map_ids */
841
842         emit_obj_refs_json(&refs_table, info->id, json_wtr); /* pids */
843
844         jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
845
846         if (name && name[0])
847                 jsonw_string_field(json_wtr, "name", name);
848
849         jsonw_end_object(json_wtr);     /* btf object */
850 }
851
852 static int
853 show_btf(int fd, struct btf_attach_table *btf_prog_table,
854          struct btf_attach_table *btf_map_table)
855 {
856         struct bpf_btf_info info;
857         __u32 len = sizeof(info);
858         char name[64];
859         int err;
860
861         memset(&info, 0, sizeof(info));
862         err = bpf_obj_get_info_by_fd(fd, &info, &len);
863         if (err) {
864                 p_err("can't get BTF object info: %s", strerror(errno));
865                 return -1;
866         }
867         /* if kernel support emitting BTF object name, pass name pointer */
868         if (info.name_len) {
869                 memset(&info, 0, sizeof(info));
870                 info.name_len = sizeof(name);
871                 info.name = ptr_to_u64(name);
872                 len = sizeof(info);
873
874                 err = bpf_obj_get_info_by_fd(fd, &info, &len);
875                 if (err) {
876                         p_err("can't get BTF object info: %s", strerror(errno));
877                         return -1;
878                 }
879         }
880
881         if (json_output)
882                 show_btf_json(&info, fd, btf_prog_table, btf_map_table);
883         else
884                 show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
885
886         return 0;
887 }
888
889 static int do_show(int argc, char **argv)
890 {
891         struct btf_attach_table btf_prog_table;
892         struct btf_attach_table btf_map_table;
893         int err, fd = -1;
894         __u32 id = 0;
895
896         if (argc == 2) {
897                 fd = btf_parse_fd(&argc, &argv);
898                 if (fd < 0)
899                         return -1;
900         }
901
902         if (argc) {
903                 if (fd >= 0)
904                         close(fd);
905                 return BAD_ARG();
906         }
907
908         hash_init(btf_prog_table.table);
909         hash_init(btf_map_table.table);
910         err = build_btf_tables(&btf_prog_table, &btf_map_table);
911         if (err) {
912                 if (fd >= 0)
913                         close(fd);
914                 return err;
915         }
916         build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
917
918         if (fd >= 0) {
919                 err = show_btf(fd, &btf_prog_table, &btf_map_table);
920                 close(fd);
921                 goto exit_free;
922         }
923
924         if (json_output)
925                 jsonw_start_array(json_wtr);    /* root array */
926
927         while (true) {
928                 err = bpf_btf_get_next_id(id, &id);
929                 if (err) {
930                         if (errno == ENOENT) {
931                                 err = 0;
932                                 break;
933                         }
934                         p_err("can't get next BTF object: %s%s",
935                               strerror(errno),
936                               errno == EINVAL ? " -- kernel too old?" : "");
937                         err = -1;
938                         break;
939                 }
940
941                 fd = bpf_btf_get_fd_by_id(id);
942                 if (fd < 0) {
943                         if (errno == ENOENT)
944                                 continue;
945                         p_err("can't get BTF object by id (%u): %s",
946                               id, strerror(errno));
947                         err = -1;
948                         break;
949                 }
950
951                 err = show_btf(fd, &btf_prog_table, &btf_map_table);
952                 close(fd);
953                 if (err)
954                         break;
955         }
956
957         if (json_output)
958                 jsonw_end_array(json_wtr);      /* root array */
959
960 exit_free:
961         delete_btf_table(&btf_prog_table);
962         delete_btf_table(&btf_map_table);
963         delete_obj_refs_table(&refs_table);
964
965         return err;
966 }
967
968 static int do_help(int argc, char **argv)
969 {
970         if (json_output) {
971                 jsonw_null(json_wtr);
972                 return 0;
973         }
974
975         fprintf(stderr,
976                 "Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
977                 "       %1$s %2$s dump BTF_SRC [format FORMAT]\n"
978                 "       %1$s %2$s help\n"
979                 "\n"
980                 "       BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
981                 "       FORMAT  := { raw | c }\n"
982                 "       " HELP_SPEC_MAP "\n"
983                 "       " HELP_SPEC_PROGRAM "\n"
984                 "       " HELP_SPEC_OPTIONS " |\n"
985                 "                    {-B|--base-btf} }\n"
986                 "",
987                 bin_name, "btf");
988
989         return 0;
990 }
991
992 static const struct cmd cmds[] = {
993         { "show",       do_show },
994         { "list",       do_show },
995         { "help",       do_help },
996         { "dump",       do_dump },
997         { 0 }
998 };
999
1000 int do_btf(int argc, char **argv)
1001 {
1002         return cmd_select(cmds, argc, argv, do_help);
1003 }