Re: [PATCH v10 bpf-next 08/10] bpftool: add BTF dump "format meta" to dump header/metadata
Alan Maguire <[email protected]>
| Newsgroups | org.kernel.vger.dwarves,org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
> On Fri, Feb 27, 2026 at 2:05 AM Alan Maguire <[email protected]> wrote: >> >> Provide a way to dump BTF metadata info via bpftool; this >> consists of BTF size, header fields and layout info >> (if available); for example >> >> $ bpftool btf dump file vmlinux format meta >> size 6516862 >> magic 0xeb9f >> version 1 >> flags 0x0 >> hdr_len 32 >> type_len 3929096 >> type_off 0 >> str_len 2587654 >> str_off 3929176 >> layout_len 80 >> layout_off 3929096 >> kind 0 UNKNOWN info_sz 0 elem_sz 0 flags 0 >> kind 1 INT info_sz 4 elem_sz 0 flags 0 >> kind 2 PTR info_sz 0 elem_sz 0 flags 0 >> kind 3 ARRAY info_sz 12 elem_sz 0 flags 0 >> kind 4 STRUCT info_sz 0 elem_sz 12 flags 0 >> kind 5 UNION info_sz 0 elem_sz 12 flags 0 >> kind 6 ENUM info_sz 0 elem_sz 8 flags 0 >> kind 7 FWD info_sz 0 elem_sz 0 flags 0 >> kind 8 TYPEDEF info_sz 0 elem_sz 0 flags 0 >> kind 9 VOLATILE info_sz 0 elem_sz 0 flags 0 >> kind 10 CONST info_sz 0 elem_sz 0 flags 0 >> kind 11 RESTRICT info_sz 0 elem_sz 0 flags 0 >> kind 12 FUNC info_sz 0 elem_sz 0 flags 0 >> kind 13 FUNC_PROTO info_sz 0 elem_sz 8 flags 0 >> kind 14 VAR info_sz 4 elem_sz 0 flags 0 >> kind 15 DATASEC info_sz 0 elem_sz 12 flags 0 >> kind 16 FLOAT info_sz 0 elem_sz 0 flags 0 >> kind 17 DECL_TAG info_sz 4 elem_sz 0 flags 0 >> kind 18 TYPE_TAG info_sz 0 elem_sz 0 flags 0 >> kind 19 ENUM64 info_sz 0 elem_sz 12 flags 0 >> >> JSON output is also supported: >> >> $ bpftool -p btf dump file /var/tmp/vmlinux.kind_layout format meta >> { >> "size": 6516862, >> "header": { >> "magic": 60319, >> "version": 1, >> "flags": 0, >> "hdr_len": 32, >> "type_len": 3929096, >> "type_off": 0, >> "str_len": 2587654, >> "str_off": 3929176, >> "layout_len": 80, >> "layout_off": 3929096 >> }, >> "layouts": [{ >> "kind": 0, >> "name": "UNKNOWN", >> "info_sz": 0, >> "elem_sz": 0, >> "flags": 0 >> },{ >> "kind": 1, >> "name": "INT", >> "info_sz": 4, >> "elem_sz": 0, >> "flags": 0 >> },{ >> "kind": 2, >> "name": "PTR", >> "info_sz": 0, >> "elem_sz": 0, >> "flags": 0 >> },{ >> ... >> >> Signed-off-by: Alan Maguire <[email protected]> >> --- >> tools/bpf/bpftool/bash-completion/bpftool | 2 +- >> tools/bpf/bpftool/btf.c | 91 ++++++++++++++++++++++- >> 2 files changed, 89 insertions(+), 4 deletions(-) >> >> diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool >> index a28f0cc522e4..d49d6a70cb74 100644 >> --- a/tools/bpf/bpftool/bash-completion/bpftool >> +++ b/tools/bpf/bpftool/bash-completion/bpftool >> @@ -950,7 +950,7 @@ _bpftool() >> return 0 >> ;; >> format) >> - COMPREPLY=( $( compgen -W "c raw" -- "$cur" ) ) >> + COMPREPLY=( $( compgen -W "c raw meta" -- "$cur" ) ) >> ;; >> root_id) >> return 0; >> diff --git a/tools/bpf/bpftool/btf.c b/tools/bpf/bpftool/btf.c >> index 946612029dee..08dc6a86bc85 100644 >> --- a/tools/bpf/bpftool/btf.c >> +++ b/tools/bpf/bpftool/btf.c >> @@ -835,6 +835,87 @@ static int dump_btf_c(const struct btf *btf, >> return err; >> } >> >> +static int dump_btf_meta(const struct btf *btf) >> +{ >> + __u32 layout_off = 0, layout_len = 0; >> + __u32 data_sz, i, nr_kinds = 0; >> + const struct btf_header *hdr; >> + const struct btf_layout *l; >> + const void *data; >> + >> + data = btf__raw_data(btf, &data_sz); >> + if (!data) >> + return -ENOMEM; >> + hdr = data; >> + if (json_output) { >> + jsonw_start_object(json_wtr); /* metadata object */ >> + jsonw_uint_field(json_wtr, "size", data_sz); >> + jsonw_name(json_wtr, "header"); >> + jsonw_start_object(json_wtr); /* header object */ >> + jsonw_uint_field(json_wtr, "magic", hdr->magic); >> + jsonw_uint_field(json_wtr, "version", hdr->version); >> + jsonw_uint_field(json_wtr, "flags", hdr->flags); >> + jsonw_uint_field(json_wtr, "hdr_len", hdr->hdr_len); >> + jsonw_uint_field(json_wtr, "type_len", hdr->type_len); >> + jsonw_uint_field(json_wtr, "type_off", hdr->type_off); >> + jsonw_uint_field(json_wtr, "str_len", hdr->str_len); >> + jsonw_uint_field(json_wtr, "str_off", hdr->str_off); > > I don't think this part is useful. > People can hex dump it if they really want to. > >> + } else { >> + printf("size %-10u\n", data_sz); >> + printf("magic 0x%-10x\nversion %-10d\nflags 0x%-10x\nhdr_len %-10u\n", >> + hdr->magic, hdr->version, hdr->flags, hdr->hdr_len); >> + printf("type_len %-10u\ntype_off %-10u\n", hdr->type_len, hdr->type_off); >> + printf("str_len %-10u\nstr_off %-10u\n", hdr->str_len, hdr->str_off); >> + } >> + >> + if (data_sz >= hdr->hdr_len && hdr->hdr_len >= sizeof(struct btf_header)) { >> + layout_off = hdr->layout_off; >> + layout_len = hdr->layout_len; >> + if (layout_len > 0 && >> + (long long)layout_off + layout_len + hdr->hdr_len <= data_sz) { >> + l = (void *)hdr + hdr->hdr_len + layout_off; >> + nr_kinds = layout_len / sizeof(*l); >> + } >> + } else { >> + if (!json_output) >> + return 0; >> + } >> + >> + /* unconditionally display (possibly empty) layout info for json only */ >> + if (json_output) { >> + jsonw_uint_field(json_wtr, "layout_len", layout_len); >> + jsonw_uint_field(json_wtr, "layout_off", layout_off); >> + jsonw_end_object(json_wtr); /* end header object */ >> + >> + jsonw_name(json_wtr, "layouts"); >> + jsonw_start_array(json_wtr); >> + for (i = 0; i < nr_kinds; i++) { >> + jsonw_start_object(json_wtr); >> + jsonw_uint_field(json_wtr, "kind", i); >> + if (i < NR_BTF_KINDS) >> + jsonw_string_field(json_wtr, "name", btf_kind_str[i]); >> + else >> + jsonw_null_field(json_wtr, "name"); >> + jsonw_uint_field(json_wtr, "info_sz", l[i].info_sz); >> + jsonw_uint_field(json_wtr, "elem_sz", l[i].elem_sz); >> + jsonw_uint_field(json_wtr, "flags", l[i].flags); >> + jsonw_end_object(json_wtr); >> + } > > This part, I guess, is ok-ish. > I wouldn't do it either though. Feels like a debug feature. Sure, we can omit the bpftool changes for v11 and add them later if there's a need.