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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.