Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpftool: Dump more info about DATASEC members

Dump succinct information for each member of DATASEC: its kinds and name. This
is extremely helpful to see at a quick glance what is inside each DATASEC of
a given BTF. Without this, one has to jump around BTF data to just find out
the name of a VAR or FUNC. DATASEC's var_secinfo member is special in that
regard because it doesn't itself contain the name of the member, delegating
that to the referenced VAR and FUNC kinds. Other kinds, like
STRUCT/UNION/FUNC/ENUM, encode member names directly and thus are clearly
identifiable in BTF dump.

The new output looks like this:

[35] DATASEC '.bss' size=0 vlen=6
type_id=8 offset=0 size=4 (VAR 'input_bss1')
type_id=13 offset=0 size=4 (VAR 'input_bss_weak')
type_id=16 offset=0 size=4 (VAR 'output_bss1')
type_id=17 offset=0 size=4 (VAR 'output_data1')
type_id=18 offset=0 size=4 (VAR 'output_rodata1')
type_id=20 offset=0 size=8 (VAR 'output_sink1')
[36] DATASEC '.data' size=0 vlen=2
type_id=9 offset=0 size=4 (VAR 'input_data1')
type_id=14 offset=0 size=4 (VAR 'input_data_weak')
[37] DATASEC '.kconfig' size=0 vlen=2
type_id=25 offset=0 size=4 (VAR 'LINUX_KERNEL_VERSION')
type_id=28 offset=0 size=1 (VAR 'CONFIG_BPF_SYSCALL')
[38] DATASEC '.ksyms' size=0 vlen=1
type_id=30 offset=0 size=1 (VAR 'bpf_link_fops')
[39] DATASEC '.rodata' size=0 vlen=2
type_id=12 offset=0 size=4 (VAR 'input_rodata1')
type_id=15 offset=0 size=4 (VAR 'input_rodata_weak')
[40] DATASEC 'license' size=0 vlen=1
type_id=24 offset=0 size=4 (VAR 'LICENSE')

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/bpf/20210423181348.1801389-3-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
5b438f01 0dd7e456

+18 -8
+18 -8
tools/bpf/bpftool/btf.c
··· 100 100 return btf__name_by_offset(btf, off) ? : "(invalid)"; 101 101 } 102 102 103 + static int btf_kind_safe(int kind) 104 + { 105 + return kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN; 106 + } 107 + 103 108 static int dump_btf_type(const struct btf *btf, __u32 id, 104 109 const struct btf_type *t) 105 110 { 106 111 json_writer_t *w = json_wtr; 107 - int kind, safe_kind; 108 - 109 - kind = BTF_INFO_KIND(t->info); 110 - safe_kind = kind <= BTF_KIND_MAX ? kind : BTF_KIND_UNKN; 112 + int kind = btf_kind(t); 111 113 112 114 if (json_output) { 113 115 jsonw_start_object(w); 114 116 jsonw_uint_field(w, "id", id); 115 - jsonw_string_field(w, "kind", btf_kind_str[safe_kind]); 117 + jsonw_string_field(w, "kind", btf_kind_str[btf_kind_safe(kind)]); 116 118 jsonw_string_field(w, "name", btf_str(btf, t->name_off)); 117 119 } else { 118 - printf("[%u] %s '%s'", id, btf_kind_str[safe_kind], 120 + printf("[%u] %s '%s'", id, btf_kind_str[btf_kind_safe(kind)], 119 121 btf_str(btf, t->name_off)); 120 122 } 121 123 122 - switch (BTF_INFO_KIND(t->info)) { 124 + switch (kind) { 123 125 case BTF_KIND_INT: { 124 126 __u32 v = *(__u32 *)(t + 1); 125 127 const char *enc; ··· 304 302 break; 305 303 } 306 304 case BTF_KIND_DATASEC: { 307 - const struct btf_var_secinfo *v = (const void *)(t+1); 305 + const struct btf_var_secinfo *v = (const void *)(t + 1); 306 + const struct btf_type *vt; 308 307 __u16 vlen = BTF_INFO_VLEN(t->info); 309 308 int i; 310 309 ··· 327 324 } else { 328 325 printf("\n\ttype_id=%u offset=%u size=%u", 329 326 v->type, v->offset, v->size); 327 + 328 + if (v->type <= btf__get_nr_types(btf)) { 329 + vt = btf__type_by_id(btf, v->type); 330 + printf(" (%s '%s')", 331 + btf_kind_str[btf_kind_safe(btf_kind(vt))], 332 + btf_str(btf, vt->name_off)); 333 + } 330 334 } 331 335 } 332 336 if (json_output)