1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2 /* Copyright (C) 2019 Facebook */
13 #include <linux/btf.h>
16 #include "json_writer.h"
19 static const char * const btf_kind_str[NR_BTF_KINDS] = {
20 [BTF_KIND_UNKN] = "UNKNOWN",
21 [BTF_KIND_INT] = "INT",
22 [BTF_KIND_PTR] = "PTR",
23 [BTF_KIND_ARRAY] = "ARRAY",
24 [BTF_KIND_STRUCT] = "STRUCT",
25 [BTF_KIND_UNION] = "UNION",
26 [BTF_KIND_ENUM] = "ENUM",
27 [BTF_KIND_FWD] = "FWD",
28 [BTF_KIND_TYPEDEF] = "TYPEDEF",
29 [BTF_KIND_VOLATILE] = "VOLATILE",
30 [BTF_KIND_CONST] = "CONST",
31 [BTF_KIND_RESTRICT] = "RESTRICT",
32 [BTF_KIND_FUNC] = "FUNC",
33 [BTF_KIND_FUNC_PROTO] = "FUNC_PROTO",
34 [BTF_KIND_VAR] = "VAR",
35 [BTF_KIND_DATASEC] = "DATASEC",
38 static const char *btf_int_enc_str(__u8 encoding)
54 static const char *btf_var_linkage_str(__u32 linkage)
59 case BTF_VAR_GLOBAL_ALLOCATED:
60 return "global-alloc";
66 static const char *btf_str(const struct btf *btf, __u32 off)
70 return btf__name_by_offset(btf, off) ? : "(invalid)";
73 static int dump_btf_type(const struct btf *btf, __u32 id,
74 const struct btf_type *t)
76 json_writer_t *w = json_wtr;
79 kind = BTF_INFO_KIND(t->info);
80 safe_kind = kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN;
83 jsonw_start_object(w);
84 jsonw_uint_field(w, "id", id);
85 jsonw_string_field(w, "kind", btf_kind_str[safe_kind]);
86 jsonw_string_field(w, "name", btf_str(btf, t->name_off));
88 printf("[%u] %s '%s'", id, btf_kind_str[safe_kind],
89 btf_str(btf, t->name_off));
92 switch (BTF_INFO_KIND(t->info)) {
94 __u32 v = *(__u32 *)(t + 1);
97 enc = btf_int_enc_str(BTF_INT_ENCODING(v));
100 jsonw_uint_field(w, "size", t->size);
101 jsonw_uint_field(w, "bits_offset", BTF_INT_OFFSET(v));
102 jsonw_uint_field(w, "nr_bits", BTF_INT_BITS(v));
103 jsonw_string_field(w, "encoding", enc);
105 printf(" size=%u bits_offset=%u nr_bits=%u encoding=%s",
106 t->size, BTF_INT_OFFSET(v), BTF_INT_BITS(v),
113 case BTF_KIND_VOLATILE:
114 case BTF_KIND_RESTRICT:
115 case BTF_KIND_TYPEDEF:
117 jsonw_uint_field(w, "type_id", t->type);
119 printf(" type_id=%u", t->type);
121 case BTF_KIND_ARRAY: {
122 const struct btf_array *arr = (const void *)(t + 1);
125 jsonw_uint_field(w, "type_id", arr->type);
126 jsonw_uint_field(w, "index_type_id", arr->index_type);
127 jsonw_uint_field(w, "nr_elems", arr->nelems);
129 printf(" type_id=%u index_type_id=%u nr_elems=%u",
130 arr->type, arr->index_type, arr->nelems);
134 case BTF_KIND_STRUCT:
135 case BTF_KIND_UNION: {
136 const struct btf_member *m = (const void *)(t + 1);
137 __u16 vlen = BTF_INFO_VLEN(t->info);
141 jsonw_uint_field(w, "size", t->size);
142 jsonw_uint_field(w, "vlen", vlen);
143 jsonw_name(w, "members");
144 jsonw_start_array(w);
146 printf(" size=%u vlen=%u", t->size, vlen);
148 for (i = 0; i < vlen; i++, m++) {
149 const char *name = btf_str(btf, m->name_off);
150 __u32 bit_off, bit_sz;
152 if (BTF_INFO_KFLAG(t->info)) {
153 bit_off = BTF_MEMBER_BIT_OFFSET(m->offset);
154 bit_sz = BTF_MEMBER_BITFIELD_SIZE(m->offset);
161 jsonw_start_object(w);
162 jsonw_string_field(w, "name", name);
163 jsonw_uint_field(w, "type_id", m->type);
164 jsonw_uint_field(w, "bits_offset", bit_off);
166 jsonw_uint_field(w, "bitfield_size",
171 printf("\n\t'%s' type_id=%u bits_offset=%u",
172 name, m->type, bit_off);
174 printf(" bitfield_size=%u", bit_sz);
181 case BTF_KIND_ENUM: {
182 const struct btf_enum *v = (const void *)(t + 1);
183 __u16 vlen = BTF_INFO_VLEN(t->info);
187 jsonw_uint_field(w, "size", t->size);
188 jsonw_uint_field(w, "vlen", vlen);
189 jsonw_name(w, "values");
190 jsonw_start_array(w);
192 printf(" size=%u vlen=%u", t->size, vlen);
194 for (i = 0; i < vlen; i++, v++) {
195 const char *name = btf_str(btf, v->name_off);
198 jsonw_start_object(w);
199 jsonw_string_field(w, "name", name);
200 jsonw_uint_field(w, "val", v->val);
203 printf("\n\t'%s' val=%u", name, v->val);
211 const char *fwd_kind = BTF_INFO_KFLAG(t->info) ? "union"
215 jsonw_string_field(w, "fwd_kind", fwd_kind);
217 printf(" fwd_kind=%s", fwd_kind);
222 jsonw_uint_field(w, "type_id", t->type);
224 printf(" type_id=%u", t->type);
226 case BTF_KIND_FUNC_PROTO: {
227 const struct btf_param *p = (const void *)(t + 1);
228 __u16 vlen = BTF_INFO_VLEN(t->info);
232 jsonw_uint_field(w, "ret_type_id", t->type);
233 jsonw_uint_field(w, "vlen", vlen);
234 jsonw_name(w, "params");
235 jsonw_start_array(w);
237 printf(" ret_type_id=%u vlen=%u", t->type, vlen);
239 for (i = 0; i < vlen; i++, p++) {
240 const char *name = btf_str(btf, p->name_off);
243 jsonw_start_object(w);
244 jsonw_string_field(w, "name", name);
245 jsonw_uint_field(w, "type_id", p->type);
248 printf("\n\t'%s' type_id=%u", name, p->type);
256 const struct btf_var *v = (const void *)(t + 1);
259 linkage = btf_var_linkage_str(v->linkage);
262 jsonw_uint_field(w, "type_id", t->type);
263 jsonw_string_field(w, "linkage", linkage);
265 printf(" type_id=%u, linkage=%s", t->type, linkage);
269 case BTF_KIND_DATASEC: {
270 const struct btf_var_secinfo *v = (const void *)(t+1);
271 __u16 vlen = BTF_INFO_VLEN(t->info);
275 jsonw_uint_field(w, "size", t->size);
276 jsonw_uint_field(w, "vlen", vlen);
277 jsonw_name(w, "vars");
278 jsonw_start_array(w);
280 printf(" size=%u vlen=%u", t->size, vlen);
282 for (i = 0; i < vlen; i++, v++) {
284 jsonw_start_object(w);
285 jsonw_uint_field(w, "type_id", v->type);
286 jsonw_uint_field(w, "offset", v->offset);
287 jsonw_uint_field(w, "size", v->size);
290 printf("\n\ttype_id=%u offset=%u size=%u",
291 v->type, v->offset, v->size);
303 jsonw_end_object(json_wtr);
310 static int dump_btf_raw(const struct btf *btf,
311 __u32 *root_type_ids, int root_type_cnt)
313 const struct btf_type *t;
317 jsonw_start_object(json_wtr);
318 jsonw_name(json_wtr, "types");
319 jsonw_start_array(json_wtr);
323 for (i = 0; i < root_type_cnt; i++) {
324 t = btf__type_by_id(btf, root_type_ids[i]);
325 dump_btf_type(btf, root_type_ids[i], t);
328 int cnt = btf__get_nr_types(btf);
330 for (i = 1; i <= cnt; i++) {
331 t = btf__type_by_id(btf, i);
332 dump_btf_type(btf, i, t);
337 jsonw_end_array(json_wtr);
338 jsonw_end_object(json_wtr);
343 static bool check_btf_endianness(GElf_Ehdr *ehdr)
345 static unsigned int const endian = 1;
347 switch (ehdr->e_ident[EI_DATA]) {
349 return *(unsigned char const *)&endian == 1;
351 return *(unsigned char const *)&endian == 0;
357 static int btf_load_from_elf(const char *path, struct btf **btf)
359 int err = -1, fd = -1, idx = 0;
360 Elf_Data *btf_data = NULL;
365 if (elf_version(EV_CURRENT) == EV_NONE) {
366 p_err("failed to init libelf for %s", path);
370 fd = open(path, O_RDONLY);
372 p_err("failed to open %s: %s", path, strerror(errno));
376 elf = elf_begin(fd, ELF_C_READ, NULL);
378 p_err("failed to open %s as ELF file", path);
381 if (!gelf_getehdr(elf, &ehdr)) {
382 p_err("failed to get EHDR from %s", path);
385 if (!check_btf_endianness(&ehdr)) {
386 p_err("non-native ELF endianness is not supported");
389 if (!elf_rawdata(elf_getscn(elf, ehdr.e_shstrndx), NULL)) {
390 p_err("failed to get e_shstrndx from %s\n", path);
394 while ((scn = elf_nextscn(elf, scn)) != NULL) {
399 if (gelf_getshdr(scn, &sh) != &sh) {
400 p_err("failed to get section(%d) header from %s",
404 name = elf_strptr(elf, ehdr.e_shstrndx, sh.sh_name);
406 p_err("failed to get section(%d) name from %s",
410 if (strcmp(name, BTF_ELF_SEC) == 0) {
411 btf_data = elf_getdata(scn, 0);
413 p_err("failed to get section(%d, %s) data from %s",
422 p_err("%s ELF section not found in %s", BTF_ELF_SEC, path);
426 *btf = btf__new(btf_data->d_buf, btf_data->d_size);
430 p_err("failed to load BTF data from %s: %s",
431 path, strerror(err));
449 static int do_dump(int argc, char **argv)
451 struct btf *btf = NULL;
452 __u32 root_type_ids[2];
453 int root_type_cnt = 0;
465 if (is_prefix(src, "map")) {
466 struct bpf_map_info info = {};
467 __u32 len = sizeof(info);
474 fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
478 btf_id = info.btf_id;
479 if (argc && is_prefix(*argv, "key")) {
480 root_type_ids[root_type_cnt++] = info.btf_key_type_id;
482 } else if (argc && is_prefix(*argv, "value")) {
483 root_type_ids[root_type_cnt++] = info.btf_value_type_id;
485 } else if (argc && is_prefix(*argv, "all")) {
487 } else if (argc && is_prefix(*argv, "kv")) {
488 root_type_ids[root_type_cnt++] = info.btf_key_type_id;
489 root_type_ids[root_type_cnt++] = info.btf_value_type_id;
492 root_type_ids[root_type_cnt++] = info.btf_key_type_id;
493 root_type_ids[root_type_cnt++] = info.btf_value_type_id;
495 } else if (is_prefix(src, "prog")) {
496 struct bpf_prog_info info = {};
497 __u32 len = sizeof(info);
504 fd = prog_parse_fd(&argc, &argv);
508 err = bpf_obj_get_info_by_fd(fd, &info, &len);
510 p_err("can't get prog info: %s", strerror(errno));
514 btf_id = info.btf_id;
515 } else if (is_prefix(src, "id")) {
518 btf_id = strtoul(*argv, &endptr, 0);
520 p_err("can't parse %s as ID", **argv);
524 } else if (is_prefix(src, "file")) {
525 err = btf_load_from_elf(*argv, &btf);
531 p_err("unrecognized BTF source specifier: '%s'", src);
536 err = btf__get_from_id(btf_id, &btf);
538 p_err("get btf by id (%u): %s", btf_id, strerror(err));
543 p_err("can't find btf with ID (%u)", btf_id);
548 dump_btf_raw(btf, root_type_ids, root_type_cnt);
556 static int do_help(int argc, char **argv)
559 jsonw_null(json_wtr);
564 "Usage: %s btf dump BTF_SRC\n"
567 " BTF_SRC := { id BTF_ID | prog PROG | map MAP [{key | value | kv | all}] | file FILE }\n"
568 " " HELP_SPEC_MAP "\n"
569 " " HELP_SPEC_PROGRAM "\n"
570 " " HELP_SPEC_OPTIONS "\n"
577 static const struct cmd cmds[] = {
583 int do_btf(int argc, char **argv)
585 return cmd_select(cmds, argc, argv, do_help);