diff options
author | Yonghong Song <yhs@fb.com> | 2018-12-16 09:13:58 +0300 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2018-12-18 03:12:00 +0300 |
commit | 8772c8bc093b2d5823125475e1206b80664f8acb (patch) | |
tree | 0e68981876d990fcdb98e6b1d2e6a6645e52a6ae /tools/bpf/bpftool/btf_dumper.c | |
parent | 9f95e37e31a4eabd7c8152f2ddcdbea5eafdb7c8 (diff) | |
download | linux-8772c8bc093b2d5823125475e1206b80664f8acb.tar.xz |
tools: bpftool: support pretty print with kind_flag set
The following example shows map pretty print with structures
which include bitfield members.
enum A { A1, A2, A3, A4, A5 };
typedef enum A ___A;
struct tmp_t {
char a1:4;
int a2:4;
int :4;
__u32 a3:4;
int b;
___A b1:4;
enum A b2:4;
};
struct bpf_map_def SEC("maps") tmpmap = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(__u32),
.value_size = sizeof(struct tmp_t),
.max_entries = 1,
};
BPF_ANNOTATE_KV_PAIR(tmpmap, int, struct tmp_t);
and the following map update in the bpf program:
key = 0;
struct tmp_t t = {};
t.a1 = 2;
t.a2 = 4;
t.a3 = 6;
t.b = 7;
t.b1 = 8;
t.b2 = 10;
bpf_map_update_elem(&tmpmap, &key, &t, 0);
With this patch, I am able to print out the map values
correctly with this patch:
bpftool map dump id 187
[{
"key": 0,
"value": {
"a1": 0x2,
"a2": 0x4,
"a3": 0x6,
"b": 7,
"b1": 0x8,
"b2": 0xa
}
}
]
Previously, if a function prototype argument has a typedef
type, the prototype is not printed since
function __btf_dumper_type_only() bailed out with error
if the type is a typedef. This commit corrected this
behavior by printing out typedef properly.
The following example shows forward type and
typedef type can be properly printed in function prototype
with modified test_btf_haskv.c.
struct t;
union u;
__attribute__((noinline))
static int test_long_fname_1(struct dummy_tracepoint_args *arg,
struct t *p1, union u *p2,
__u32 unused)
...
int _dummy_tracepoint(struct dummy_tracepoint_args *arg) {
return test_long_fname_1(arg, 0, 0, 0);
}
$ bpftool p d xlated id 24
...
int test_long_fname_1(struct dummy_tracepoint_args * arg,
struct t * p1, union u * p2,
__u32 unused)
...
Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/bpf/bpftool/btf_dumper.c')
-rw-r--r-- | tools/bpf/bpftool/btf_dumper.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c index 06e3d2bbf6d1..3f0629edbca5 100644 --- a/tools/bpf/bpftool/btf_dumper.c +++ b/tools/bpf/bpftool/btf_dumper.c @@ -193,6 +193,7 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id, const struct btf_type *t; struct btf_member *m; const void *data_off; + int kind_flag; int ret = 0; int i, vlen; @@ -200,18 +201,32 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id, if (!t) return -EINVAL; + kind_flag = BTF_INFO_KFLAG(t->info); vlen = BTF_INFO_VLEN(t->info); jsonw_start_object(d->jw); m = (struct btf_member *)(t + 1); for (i = 0; i < vlen; i++) { - data_off = data + BITS_ROUNDDOWN_BYTES(m[i].offset); + __u32 bit_offset = m[i].offset; + __u32 bitfield_size = 0; + + if (kind_flag) { + bitfield_size = BTF_MEMBER_BITFIELD_SIZE(bit_offset); + bit_offset = BTF_MEMBER_BIT_OFFSET(bit_offset); + } + jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off)); - ret = btf_dumper_do_type(d, m[i].type, - BITS_PER_BYTE_MASKED(m[i].offset), - data_off); - if (ret) - break; + if (bitfield_size) { + btf_dumper_bitfield(bitfield_size, bit_offset, + data, d->jw, d->is_plain_text); + } else { + data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset); + ret = btf_dumper_do_type(d, m[i].type, + BITS_PER_BYTE_MASKED(bit_offset), + data_off); + if (ret) + break; + } } jsonw_end_object(d->jw); @@ -298,6 +313,7 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, switch (BTF_INFO_KIND(t->info)) { case BTF_KIND_INT: + case BTF_KIND_TYPEDEF: BTF_PRINT_ARG("%s ", btf__name_by_offset(btf, t->name_off)); break; case BTF_KIND_STRUCT: @@ -321,10 +337,11 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, BTF_PRINT_TYPE(t->type); BTF_PRINT_ARG("* "); break; - case BTF_KIND_UNKN: case BTF_KIND_FWD: - case BTF_KIND_TYPEDEF: - return -1; + BTF_PRINT_ARG("%s %s ", + BTF_INFO_KFLAG(t->info) ? "union" : "struct", + btf__name_by_offset(btf, t->name_off)); + break; case BTF_KIND_VOLATILE: BTF_PRINT_ARG("volatile "); BTF_PRINT_TYPE(t->type); @@ -348,6 +365,7 @@ static int __btf_dumper_type_only(const struct btf *btf, __u32 type_id, if (pos == -1) return -1; break; + case BTF_KIND_UNKN: default: return -1; } |