1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2019 Facebook */
11 #include <linux/btf.h>
12 #include <sys/types.h>
17 #include <bpf/hashmap.h>
18 #include <bpf/libbpf.h>
20 #include "json_writer.h"
23 static const char * const btf_kind_str[NR_BTF_KINDS] = {
24 [BTF_KIND_UNKN] = "UNKNOWN",
25 [BTF_KIND_INT] = "INT",
26 [BTF_KIND_PTR] = "PTR",
27 [BTF_KIND_ARRAY] = "ARRAY",
28 [BTF_KIND_STRUCT] = "STRUCT",
29 [BTF_KIND_UNION] = "UNION",
30 [BTF_KIND_ENUM] = "ENUM",
31 [BTF_KIND_FWD] = "FWD",
32 [BTF_KIND_TYPEDEF] = "TYPEDEF",
33 [BTF_KIND_VOLATILE] = "VOLATILE",
34 [BTF_KIND_CONST] = "CONST",
35 [BTF_KIND_RESTRICT] = "RESTRICT",
36 [BTF_KIND_FUNC] = "FUNC",
37 [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
38 [BTF_KIND_VAR] = "VAR",
39 [BTF_KIND_DATASEC] = "DATASEC",
40 [BTF_KIND_FLOAT] = "FLOAT",
41 [BTF_KIND_DECL_TAG] = "DECL_TAG",
42 [BTF_KIND_TYPE_TAG] = "TYPE_TAG",
43 [BTF_KIND_ENUM64] = "ENUM64",
46 static const char *btf_int_enc_str(__u8 encoding)
62 static const char *btf_var_linkage_str(__u32 linkage)
67 case BTF_VAR_GLOBAL_ALLOCATED:
69 case BTF_VAR_GLOBAL_EXTERN:
76 static const char *btf_func_linkage_str(const struct btf_type *t)
78 switch (btf_vlen(t)) {
90 static const char *btf_str(const struct btf *btf, __u32 off)
94 return btf__name_by_offset(btf, off) ? : "(invalid)";
97 static int btf_kind_safe(int kind)
99 return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
102 static int dump_btf_type(const struct btf *btf, __u32 id,
103 const struct btf_type *t)
105 json_writer_t *w = json_wtr;
106 int kind = btf_kind(t);
109 jsonw_start_object(w);
110 jsonw_uint_field(w, "id", id);
111 jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]);
112 jsonw_string_field(w, "name", btf_str(btf, t->name_off));
114 printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)],
115 btf_str(btf, t->name_off));
120 __u32 v = *(__u32 *)(t + 1);
123 enc = btf_int_enc_str(BTF_INT_ENCODING(v));
126 jsonw_uint_field(w, "size", t->size);
127 jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
128 jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
129 jsonw_string_field(w, "encoding", enc);
131 printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
132 t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
139 case BTF_KIND_VOLATILE:
140 case BTF_KIND_RESTRICT:
141 case BTF_KIND_TYPEDEF:
142 case BTF_KIND_TYPE_TAG:
144 jsonw_uint_field(w, "type_id", t->type);
146 printf(" type_id=%u", t->type);
148 case BTF_KIND_ARRAY: {
149 const struct btf_array *arr = (const void *)(t + 1);
152 jsonw_uint_field(w, "type_id", arr->type);
153 jsonw_uint_field(w, "index_type_id", arr->index_type);
154 jsonw_uint_field(w, "nr_elems", arr->nelems);
156 printf(" type_id=%u index_type_id=%u nr_elems=%u",
157 arr->type, arr->index_type, arr->nelems);
161 case BTF_KIND_STRUCT:
162 case BTF_KIND_UNION: {
163 const struct btf_member *m = (const void *)(t + 1);
164 __u16 vlen = BTF_INFO_VLEN(t->info);
168 jsonw_uint_field(w, "size", t->size);
169 jsonw_uint_field(w, "vlen", vlen);
170 jsonw_name(w, "members");
171 jsonw_start_array(w);
173 printf(" size=%u vlen=%u", t->size, vlen);
175 for (i = 0; i < vlen; i++, m++) {
176 const char *name = btf_str(btf, m->name_off);
177 __u32 bit_off, bit_sz;
179 if (BTF_INFO_KFLAG(t->info)) {
180 bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
181 bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
188 jsonw_start_object(w);
189 jsonw_string_field(w, "name", name);
190 jsonw_uint_field(w, "type_id", m->type);
191 jsonw_uint_field(w, "bits_offset", bit_off);
193 jsonw_uint_field(w, "bitfield_size",
198 printf("\n\t'%s' type_id=%u bits_offset=%u",
199 name, m->type, bit_off);
201 printf(" bitfield_size=%u", bit_sz);
208 case BTF_KIND_ENUM: {
209 const struct btf_enum *v = (const void *)(t + 1);
210 __u16 vlen = BTF_INFO_VLEN(t->info);
211 const char *encoding;
214 encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
216 jsonw_string_field(w, "encoding", encoding);
217 jsonw_uint_field(w, "size", t->size);
218 jsonw_uint_field(w, "vlen", vlen);
219 jsonw_name(w, "values");
220 jsonw_start_array(w);
222 printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
224 for (i = 0; i < vlen; i++, v++) {
225 const char *name = btf_str(btf, v->name_off);
228 jsonw_start_object(w);
229 jsonw_string_field(w, "name", name);
231 jsonw_int_field(w, "val", v->val);
233 jsonw_uint_field(w, "val", v->val);
237 printf("\n\t'%s' val=%d", name, v->val);
239 printf("\n\t'%s' val=%u", name, v->val);
246 case BTF_KIND_ENUM64: {
247 const struct btf_enum64 *v = btf_enum64(t);
248 __u16 vlen = btf_vlen(t);
249 const char *encoding;
252 encoding = btf_kflag(t) ? "SIGNED" : "UNSIGNED";
254 jsonw_string_field(w, "encoding", encoding);
255 jsonw_uint_field(w, "size", t->size);
256 jsonw_uint_field(w, "vlen", vlen);
257 jsonw_name(w, "values");
258 jsonw_start_array(w);
260 printf(" encoding=%s size=%u vlen=%u", encoding, t->size, vlen);
262 for (i = 0; i < vlen; i++, v++) {
263 const char *name = btf_str(btf, v->name_off);
264 __u64 val = ((__u64)v->val_hi32 << 32) | v->val_lo32;
267 jsonw_start_object(w);
268 jsonw_string_field(w, "name", name);
270 jsonw_int_field(w, "val", val);
272 jsonw_uint_field(w, "val", val);
276 printf("\n\t'%s' val=%lldLL", name,
277 (unsigned long long)val);
279 printf("\n\t'%s' val=%lluULL", name,
280 (unsigned long long)val);
288 const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
292 jsonw_string_field(w, "fwd_kind", fwd_kind);
294 printf(" fwd_kind=%s", fwd_kind);
297 case BTF_KIND_FUNC: {
298 const char *linkage = btf_func_linkage_str(t);
301 jsonw_uint_field(w, "type_id", t->type);
302 jsonw_string_field(w, "linkage", linkage);
304 printf(" type_id=%u linkage=%s", t->type, linkage);
308 case BTF_KIND_FUNC_PROTO: {
309 const struct btf_param *p = (const void *)(t + 1);
310 __u16 vlen = BTF_INFO_VLEN(t->info);
314 jsonw_uint_field(w, "ret_type_id", t->type);
315 jsonw_uint_field(w, "vlen", vlen);
316 jsonw_name(w, "params");
317 jsonw_start_array(w);
319 printf(" ret_type_id=%u vlen=%u", t->type, vlen);
321 for (i = 0; i < vlen; i++, p++) {
322 const char *name = btf_str(btf, p->name_off);
325 jsonw_start_object(w);
326 jsonw_string_field(w, "name", name);
327 jsonw_uint_field(w, "type_id", p->type);
330 printf("\n\t'%s' type_id=%u", name, p->type);
338 const struct btf_var *v = (const void *)(t + 1);
341 linkage = btf_var_linkage_str(v->linkage);
344 jsonw_uint_field(w, "type_id", t->type);
345 jsonw_string_field(w, "linkage", linkage);
347 printf(" type_id=%u, linkage=%s", t->type, linkage);
351 case BTF_KIND_DATASEC: {
352 const struct btf_var_secinfo *v = (const void *)(t + 1);
353 const struct btf_type *vt;
354 __u16 vlen = BTF_INFO_VLEN(t->info);
358 jsonw_uint_field(w, "size", t->size);
359 jsonw_uint_field(w, "vlen", vlen);
360 jsonw_name(w, "vars");
361 jsonw_start_array(w);
363 printf(" size=%u vlen=%u", t->size, vlen);
365 for (i = 0; i < vlen; i++, v++) {
367 jsonw_start_object(w);
368 jsonw_uint_field(w, "type_id", v->type);
369 jsonw_uint_field(w, "offset", v->offset);
370 jsonw_uint_field(w, "size", v->size);
373 printf("\n\ttype_id=%u offset=%u size=%u",
374 v->type, v->offset, v->size);
376 if (v->type < btf__type_cnt(btf)) {
377 vt = btf__type_by_id(btf, v->type);
379 btf_kind_str[btf_kind_safe(btf_kind(vt))],
380 btf_str(btf, vt->name_off));
388 case BTF_KIND_FLOAT: {
390 jsonw_uint_field(w, "size", t->size);
392 printf(" size=%u", t->size);
395 case BTF_KIND_DECL_TAG: {
396 const struct btf_decl_tag *tag = (const void *)(t + 1);
399 jsonw_uint_field(w, "type_id", t->type);
400 jsonw_int_field(w, "component_idx", tag->component_idx);
402 printf(" type_id=%u component_idx=%d", t->type, tag->component_idx);
411 jsonw_end_object(json_wtr);
418 static int dump_btf_raw(const struct btf *btf,
419 __u32 *root_type_ids, int root_type_cnt)
421 const struct btf_type *t;
425 jsonw_start_object(json_wtr);
426 jsonw_name(json_wtr, "types");
427 jsonw_start_array(json_wtr);
431 for (i = 0; i < root_type_cnt; i++) {
432 t = btf__type_by_id(btf, root_type_ids[i]);
433 dump_btf_type(btf, root_type_ids[i], t);
436 const struct btf *base;
437 int cnt = btf__type_cnt(btf);
440 base = btf__base_btf(btf);
442 start_id = btf__type_cnt(base);
444 for (i = start_id; i < cnt; i++) {
445 t = btf__type_by_id(btf, i);
446 dump_btf_type(btf, i, t);
451 jsonw_end_array(json_wtr);
452 jsonw_end_object(json_wtr);
457 static void __printf(2, 0) btf_dump_printf(void *ctx,
458 const char *fmt, va_list args)
460 vfprintf(stdout, fmt, args);
463 static int dump_btf_c(const struct btf *btf,
464 __u32 *root_type_ids, int root_type_cnt)
469 d = btf_dump__new(btf, btf_dump_printf, NULL, NULL);
473 printf("#ifndef __VMLINUX_H__\n");
474 printf("#define __VMLINUX_H__\n");
476 printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
477 printf("#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)\n");
478 printf("#endif\n\n");
481 for (i = 0; i < root_type_cnt; i++) {
482 err = btf_dump__dump_type(d, root_type_ids[i]);
487 int cnt = btf__type_cnt(btf);
489 for (i = 1; i < cnt; i++) {
490 err = btf_dump__dump_type(d, i);
496 printf("#ifndef BPF_NO_PRESERVE_ACCESS_INDEX\n");
497 printf("#pragma clang attribute pop\n");
500 printf("#endif /* __VMLINUX_H__ */\n");
507 static const char sysfs_vmlinux[] = "/sys/kernel/btf/vmlinux";
509 static struct btf *get_vmlinux_btf_from_sysfs(void)
513 base = btf__parse(sysfs_vmlinux, NULL);
515 p_err("failed to parse vmlinux BTF at '%s': %d\n",
516 sysfs_vmlinux, -errno);
521 #define BTF_NAME_BUFF_LEN 64
523 static bool btf_is_kernel_module(__u32 btf_id)
525 struct bpf_btf_info btf_info = {};
526 char btf_name[BTF_NAME_BUFF_LEN];
531 btf_fd = bpf_btf_get_fd_by_id(btf_id);
533 p_err("can't get BTF object by id (%u): %s", btf_id, strerror(errno));
537 len = sizeof(btf_info);
538 btf_info.name = ptr_to_u64(btf_name);
539 btf_info.name_len = sizeof(btf_name);
540 err = bpf_btf_get_info_by_fd(btf_fd, &btf_info, &len);
543 p_err("can't get BTF (ID %u) object info: %s", btf_id, strerror(errno));
547 return btf_info.kernel_btf && strncmp(btf_name, "vmlinux", sizeof(btf_name)) != 0;
550 static int do_dump(int argc, char **argv)
552 struct btf *btf = NULL, *base = NULL;
553 __u32 root_type_ids[2];
554 int root_type_cnt = 0;
566 if (is_prefix(src, "map")) {
567 struct bpf_map_info info = {};
568 __u32 len = sizeof(info);
575 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
579 btf_id = info.btf_id;
580 if (argc && is_prefix(*argv, "key")) {
581 root_type_ids[root_type_cnt++] = info.btf_key_type_id;
583 } else if (argc && is_prefix(*argv, "value")) {
584 root_type_ids[root_type_cnt++] = info.btf_value_type_id;
586 } else if (argc && is_prefix(*argv, "all")) {
588 } else if (argc && is_prefix(*argv, "kv")) {
589 root_type_ids[root_type_cnt++] = info.btf_key_type_id;
590 root_type_ids[root_type_cnt++] = info.btf_value_type_id;
593 root_type_ids[root_type_cnt++] = info.btf_key_type_id;
594 root_type_ids[root_type_cnt++] = info.btf_value_type_id;
596 } else if (is_prefix(src, "prog")) {
597 struct bpf_prog_info info = {};
598 __u32 len = sizeof(info);
605 fd = prog_parse_fd(&argc, &argv);
609 err = bpf_prog_get_info_by_fd(fd, &info, &len);
611 p_err("can't get prog info: %s", strerror(errno));
615 btf_id = info.btf_id;
616 } else if (is_prefix(src, "id")) {
619 btf_id = strtoul(*argv, &endptr, 0);
621 p_err("can't parse %s as ID", *argv);
625 } else if (is_prefix(src, "file")) {
626 const char sysfs_prefix[] = "/sys/kernel/btf/";
629 strncmp(*argv, sysfs_prefix, sizeof(sysfs_prefix) - 1) == 0 &&
630 strcmp(*argv, sysfs_vmlinux) != 0)
631 base = get_vmlinux_btf_from_sysfs();
633 btf = btf__parse_split(*argv, base ?: base_btf);
636 p_err("failed to load BTF from %s: %s",
637 *argv, strerror(errno));
643 p_err("unrecognized BTF source specifier: '%s'", src);
648 if (is_prefix(*argv, "format")) {
651 p_err("expecting value for 'format' option\n");
655 if (strcmp(*argv, "c") == 0) {
657 } else if (strcmp(*argv, "raw") == 0) {
660 p_err("unrecognized format specifier: '%s', possible values: raw, c",
667 p_err("unrecognized option: '%s'", *argv);
674 if (!base_btf && btf_is_kernel_module(btf_id)) {
675 p_info("Warning: valid base BTF was not specified with -B option, falling back to standard base BTF (%s)",
677 base_btf = get_vmlinux_btf_from_sysfs();
680 btf = btf__load_from_kernel_by_id_split(btf_id, base_btf);
683 p_err("get btf by id (%u): %s", btf_id, strerror(errno));
690 p_err("JSON output for C-syntax dump is not supported");
694 err = dump_btf_c(btf, root_type_ids, root_type_cnt);
696 err = dump_btf_raw(btf, root_type_ids, root_type_cnt);
706 static int btf_parse_fd(int *argc, char ***argv)
712 if (!is_prefix(*argv[0], "id")) {
713 p_err("expected 'id', got: '%s'?", **argv);
718 id = strtoul(**argv, &endptr, 0);
720 p_err("can't parse %s as ID", **argv);
725 fd = bpf_btf_get_fd_by_id(id);
727 p_err("can't get BTF object by id (%u): %s",
728 id, strerror(errno));
734 build_btf_type_table(struct hashmap *tab, enum bpf_obj_type type,
735 void *info, __u32 *len)
737 static const char * const names[] = {
738 [BPF_OBJ_UNKNOWN] = "unknown",
739 [BPF_OBJ_PROG] = "prog",
740 [BPF_OBJ_MAP] = "map",
742 __u32 btf_id, id = 0;
749 err = bpf_prog_get_next_id(id, &id);
752 err = bpf_map_get_next_id(id, &id);
756 p_err("unexpected object type: %d", type);
760 if (errno == ENOENT) {
764 p_err("can't get next %s: %s%s", names[type],
766 errno == EINVAL ? " -- kernel too old?" : "");
772 fd = bpf_prog_get_fd_by_id(id);
775 fd = bpf_map_get_fd_by_id(id);
779 p_err("unexpected object type: %d", type);
785 p_err("can't get %s by id (%u): %s", names[type], id,
791 memset(info, 0, *len);
792 if (type == BPF_OBJ_PROG)
793 err = bpf_prog_get_info_by_fd(fd, info, len);
795 err = bpf_map_get_info_by_fd(fd, info, len);
798 p_err("can't get %s info: %s", names[type],
805 btf_id = ((struct bpf_prog_info *)info)->btf_id;
808 btf_id = ((struct bpf_map_info *)info)->btf_id;
812 p_err("unexpected object type: %d", type);
818 err = hashmap__append(tab, btf_id, id);
820 p_err("failed to append entry to hashmap for BTF ID %u, object ID %u: %s",
821 btf_id, id, strerror(-err));
834 build_btf_tables(struct hashmap *btf_prog_table,
835 struct hashmap *btf_map_table)
837 struct bpf_prog_info prog_info;
838 __u32 prog_len = sizeof(prog_info);
839 struct bpf_map_info map_info;
840 __u32 map_len = sizeof(map_info);
843 err = build_btf_type_table(btf_prog_table, BPF_OBJ_PROG, &prog_info,
848 err = build_btf_type_table(btf_map_table, BPF_OBJ_MAP, &map_info,
851 hashmap__free(btf_prog_table);
859 show_btf_plain(struct bpf_btf_info *info, int fd,
860 struct hashmap *btf_prog_table,
861 struct hashmap *btf_map_table)
863 struct hashmap_entry *entry;
864 const char *name = u64_to_ptr(info->name);
867 printf("%u: ", info->id);
868 if (info->kernel_btf)
869 printf("name [%s] ", name);
870 else if (name && name[0])
871 printf("name %s ", name);
873 printf("name <anon> ");
874 printf("size %uB", info->btf_size);
877 hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
878 printf("%s%lu", n++ == 0 ? " prog_ids " : ",", entry->value);
882 hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
883 printf("%s%lu", n++ == 0 ? " map_ids " : ",", entry->value);
886 emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
892 show_btf_json(struct bpf_btf_info *info, int fd,
893 struct hashmap *btf_prog_table,
894 struct hashmap *btf_map_table)
896 struct hashmap_entry *entry;
897 const char *name = u64_to_ptr(info->name);
899 jsonw_start_object(json_wtr); /* btf object */
900 jsonw_uint_field(json_wtr, "id", info->id);
901 jsonw_uint_field(json_wtr, "size", info->btf_size);
903 jsonw_name(json_wtr, "prog_ids");
904 jsonw_start_array(json_wtr); /* prog_ids */
905 hashmap__for_each_key_entry(btf_prog_table, entry, info->id) {
906 jsonw_uint(json_wtr, entry->value);
908 jsonw_end_array(json_wtr); /* prog_ids */
910 jsonw_name(json_wtr, "map_ids");
911 jsonw_start_array(json_wtr); /* map_ids */
912 hashmap__for_each_key_entry(btf_map_table, entry, info->id) {
913 jsonw_uint(json_wtr, entry->value);
915 jsonw_end_array(json_wtr); /* map_ids */
917 emit_obj_refs_json(refs_table, info->id, json_wtr); /* pids */
919 jsonw_bool_field(json_wtr, "kernel", info->kernel_btf);
922 jsonw_string_field(json_wtr, "name", name);
924 jsonw_end_object(json_wtr); /* btf object */
928 show_btf(int fd, struct hashmap *btf_prog_table,
929 struct hashmap *btf_map_table)
931 struct bpf_btf_info info;
932 __u32 len = sizeof(info);
936 memset(&info, 0, sizeof(info));
937 err = bpf_btf_get_info_by_fd(fd, &info, &len);
939 p_err("can't get BTF object info: %s", strerror(errno));
942 /* if kernel support emitting BTF object name, pass name pointer */
944 memset(&info, 0, sizeof(info));
945 info.name_len = sizeof(name);
946 info.name = ptr_to_u64(name);
949 err = bpf_btf_get_info_by_fd(fd, &info, &len);
951 p_err("can't get BTF object info: %s", strerror(errno));
957 show_btf_json(&info, fd, btf_prog_table, btf_map_table);
959 show_btf_plain(&info, fd, btf_prog_table, btf_map_table);
964 static int do_show(int argc, char **argv)
966 struct hashmap *btf_prog_table;
967 struct hashmap *btf_map_table;
972 fd = btf_parse_fd(&argc, &argv);
983 btf_prog_table = hashmap__new(hash_fn_for_key_as_id,
984 equal_fn_for_key_as_id, NULL);
985 btf_map_table = hashmap__new(hash_fn_for_key_as_id,
986 equal_fn_for_key_as_id, NULL);
987 if (IS_ERR(btf_prog_table) || IS_ERR(btf_map_table)) {
988 hashmap__free(btf_prog_table);
989 hashmap__free(btf_map_table);
992 p_err("failed to create hashmap for object references");
995 err = build_btf_tables(btf_prog_table, btf_map_table);
1001 build_obj_refs_table(&refs_table, BPF_OBJ_BTF);
1004 err = show_btf(fd, btf_prog_table, btf_map_table);
1010 jsonw_start_array(json_wtr); /* root array */
1013 err = bpf_btf_get_next_id(id, &id);
1015 if (errno == ENOENT) {
1019 p_err("can't get next BTF object: %s%s",
1021 errno == EINVAL ? " -- kernel too old?" : "");
1026 fd = bpf_btf_get_fd_by_id(id);
1028 if (errno == ENOENT)
1030 p_err("can't get BTF object by id (%u): %s",
1031 id, strerror(errno));
1036 err = show_btf(fd, btf_prog_table, btf_map_table);
1043 jsonw_end_array(json_wtr); /* root array */
1046 hashmap__free(btf_prog_table);
1047 hashmap__free(btf_map_table);
1048 delete_obj_refs_table(refs_table);
1053 static int do_help(int argc, char **argv)
1056 jsonw_null(json_wtr);
1061 "Usage: %1$s %2$s { show | list } [id BTF_ID]\n"
1062 " %1$s %2$s dump BTF_SRC [format FORMAT]\n"
1065 " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
1066 " FORMAT := { raw | c }\n"
1067 " " HELP_SPEC_MAP "\n"
1068 " " HELP_SPEC_PROGRAM "\n"
1069 " " HELP_SPEC_OPTIONS " |\n"
1070 " {-B|--base-btf} }\n"
1077 static const struct cmd cmds[] = {
1078 { "show", do_show },
1079 { "list", do_show },
1080 { "help", do_help },
1081 { "dump", do_dump },
1085 int do_btf(int argc, char **argv)
1087 return cmd_select(cmds, argc, argv, do_help);