On 12/15/18 1:49 PM, Martin Lau wrote:
> On Fri, Dec 14, 2018 at 03:34:34PM -0800, Yonghong Song wrote:
>> 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
>>          }
>>      }
>>    ]
>>
>> The following example shows forward type can be properly
>> printed in function prototype with modified tst_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);
>>    }
>>
>>    $ bpftool p d xlated id 24
>>    ...
>>    int test_long_fname_1(struct dummy_tracepoint_args * arg,
>>                          struct t * p1, union u * p2,
>>                          __u32 unused)
>>    ...
>>
>> Signed-off-by: Yonghong Song <y...@fb.com>
>> ---
>>   tools/bpf/bpftool/btf_dumper.c | 36 +++++++++++++++++++++++++---------
>>   1 file changed, 27 insertions(+), 9 deletions(-)
>>
>> diff --git a/tools/bpf/bpftool/btf_dumper.c b/tools/bpf/bpftool/btf_dumper.c
>> index ec1da87c3d65..23fc6a84d82b 100644
>> --- a/tools/bpf/bpftool/btf_dumper.c
>> +++ b/tools/bpf/bpftool/btf_dumper.c
>> @@ -190,6 +190,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;
>>   
>> @@ -197,18 +198,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;
> Without always checking the kind_flag first, here is an example
> that accessing the .offset looks incorrect at the first glance.
> 
>> +            __u32 bitfield_size = 0;
>> +
>> +            if (kind_flag) {
> but then I noticed it is fine here ;)
> 
>> +                    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);
>> @@ -295,6 +310,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:
>> @@ -318,10 +334,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:
> hmm.... Is this TYPEDEF change related to this patch?
> If not, a comment in the commit message would help.

TYPEDEF is not related to kind_flag.
I will add a comment in commit message.

> 
> Other than that,
> 
> Acked-by: Martin KaFai Lau <ka...@fb.com>
> 
>> -            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);
>> @@ -345,6 +362,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;
>>      }
>> -- 
>> 2.17.1
>>

Reply via email to