Commit fb4129b9 authored by Daniel Borkmann's avatar Daniel Borkmann

Merge branch 'bpf-fix-bitfield-printing'

Yonghong Song says:

====================
The previous BTF kind_flag support patch set introduced a bug
for kernel bpffs pretty printing and another bug for bpftool
map pretty printing. If a bitfield struct member offset is
greater than 256 bits, printed value for that struct
member will be incorrect.

- Patch #1 fixed the bug in kernel bpffs pretty printing.
- Patch #2 enhanced the test_btf test case to cover the
           issue exposed by patch #1.
- Patch #3 fixed the bug in bpftool map pretty printing.
====================
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parents beaf3d19 298e59d3
...@@ -1219,8 +1219,6 @@ static void btf_bitfield_seq_show(void *data, u8 bits_offset, ...@@ -1219,8 +1219,6 @@ static void btf_bitfield_seq_show(void *data, u8 bits_offset,
u8 nr_copy_bits; u8 nr_copy_bits;
u64 print_num; u64 print_num;
data += BITS_ROUNDDOWN_BYTES(bits_offset);
bits_offset = BITS_PER_BYTE_MASKED(bits_offset);
nr_copy_bits = nr_bits + bits_offset; nr_copy_bits = nr_bits + bits_offset;
nr_copy_bytes = BITS_ROUNDUP_BYTES(nr_copy_bits); nr_copy_bytes = BITS_ROUNDUP_BYTES(nr_copy_bits);
...@@ -1255,7 +1253,9 @@ static void btf_int_bits_seq_show(const struct btf *btf, ...@@ -1255,7 +1253,9 @@ static void btf_int_bits_seq_show(const struct btf *btf,
* BTF_INT_OFFSET() cannot exceed 64 bits. * BTF_INT_OFFSET() cannot exceed 64 bits.
*/ */
total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data); total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data);
btf_bitfield_seq_show(data, total_bits_offset, nr_bits, m); data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
bits_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
btf_bitfield_seq_show(data, bits_offset, nr_bits, m);
} }
static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t, static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t,
...@@ -2001,12 +2001,12 @@ static void btf_struct_seq_show(const struct btf *btf, const struct btf_type *t, ...@@ -2001,12 +2001,12 @@ static void btf_struct_seq_show(const struct btf *btf, const struct btf_type *t,
member_offset = btf_member_bit_offset(t, member); member_offset = btf_member_bit_offset(t, member);
bitfield_size = btf_member_bitfield_size(t, member); bitfield_size = btf_member_bitfield_size(t, member);
bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
if (bitfield_size) { if (bitfield_size) {
btf_bitfield_seq_show(data, member_offset, btf_bitfield_seq_show(data + bytes_offset, bits8_offset,
bitfield_size, m); bitfield_size, m);
} else { } else {
bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
ops = btf_type_ops(member_type); ops = btf_type_ops(member_type);
ops->seq_show(btf, member_type, member->type, ops->seq_show(btf, member_type, member->type,
data + bytes_offset, bits8_offset, m); data + bytes_offset, bits8_offset, m);
......
...@@ -82,8 +82,6 @@ static void btf_dumper_bitfield(__u32 nr_bits, __u8 bit_offset, ...@@ -82,8 +82,6 @@ static void btf_dumper_bitfield(__u32 nr_bits, __u8 bit_offset,
int bits_to_copy; int bits_to_copy;
__u64 print_num; __u64 print_num;
data += BITS_ROUNDDOWN_BYTES(bit_offset);
bit_offset = BITS_PER_BYTE_MASKED(bit_offset);
bits_to_copy = bit_offset + nr_bits; bits_to_copy = bit_offset + nr_bits;
bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy); bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
...@@ -118,7 +116,9 @@ static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset, ...@@ -118,7 +116,9 @@ static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
* BTF_INT_OFFSET() cannot exceed 64 bits. * BTF_INT_OFFSET() cannot exceed 64 bits.
*/ */
total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type); total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
btf_dumper_bitfield(nr_bits, total_bits_offset, data, jw, data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
btf_dumper_bitfield(nr_bits, bit_offset, data, jw,
is_plain_text); is_plain_text);
} }
...@@ -216,11 +216,12 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id, ...@@ -216,11 +216,12 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
} }
jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off)); jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
if (bitfield_size) { if (bitfield_size) {
btf_dumper_bitfield(bitfield_size, bit_offset, btf_dumper_bitfield(bitfield_size,
data, d->jw, d->is_plain_text); BITS_PER_BYTE_MASKED(bit_offset),
data_off, d->jw, d->is_plain_text);
} else { } else {
data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
ret = btf_dumper_do_type(d, m[i].type, ret = btf_dumper_do_type(d, m[i].type,
BITS_PER_BYTE_MASKED(bit_offset), BITS_PER_BYTE_MASKED(bit_offset),
data_off); data_off);
......
...@@ -3526,6 +3526,8 @@ struct pprint_mapv { ...@@ -3526,6 +3526,8 @@ struct pprint_mapv {
ENUM_TWO, ENUM_TWO,
ENUM_THREE, ENUM_THREE,
} aenum; } aenum;
uint32_t ui32b;
uint32_t bits2c:2;
}; };
static struct btf_raw_test pprint_test_template[] = { static struct btf_raw_test pprint_test_template[] = {
...@@ -3568,7 +3570,7 @@ static struct btf_raw_test pprint_test_template[] = { ...@@ -3568,7 +3570,7 @@ static struct btf_raw_test pprint_test_template[] = {
BTF_ENUM_ENC(NAME_TBD, 2), BTF_ENUM_ENC(NAME_TBD, 2),
BTF_ENUM_ENC(NAME_TBD, 3), BTF_ENUM_ENC(NAME_TBD, 3),
/* struct pprint_mapv */ /* [16] */ /* struct pprint_mapv */ /* [16] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32), BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 10), 40),
BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */ BTF_MEMBER_ENC(NAME_TBD, 11, 0), /* uint32_t ui32 */
BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */ BTF_MEMBER_ENC(NAME_TBD, 10, 32), /* uint16_t ui16 */
BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */ BTF_MEMBER_ENC(NAME_TBD, 12, 64), /* int32_t si32 */
...@@ -3577,9 +3579,11 @@ static struct btf_raw_test pprint_test_template[] = { ...@@ -3577,9 +3579,11 @@ static struct btf_raw_test pprint_test_template[] = {
BTF_MEMBER_ENC(NAME_TBD, 6, 126), /* unused_bits2b */ BTF_MEMBER_ENC(NAME_TBD, 6, 126), /* unused_bits2b */
BTF_MEMBER_ENC(0, 14, 128), /* union (anon) */ BTF_MEMBER_ENC(0, 14, 128), /* union (anon) */
BTF_MEMBER_ENC(NAME_TBD, 15, 192), /* aenum */ BTF_MEMBER_ENC(NAME_TBD, 15, 192), /* aenum */
BTF_MEMBER_ENC(NAME_TBD, 11, 224), /* uint32_t ui32b */
BTF_MEMBER_ENC(NAME_TBD, 6, 256), /* bits2c */
BTF_END_RAW, BTF_END_RAW,
}, },
BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"), BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
.key_size = sizeof(unsigned int), .key_size = sizeof(unsigned int),
.value_size = sizeof(struct pprint_mapv), .value_size = sizeof(struct pprint_mapv),
.key_type_id = 3, /* unsigned int */ .key_type_id = 3, /* unsigned int */
...@@ -3628,7 +3632,7 @@ static struct btf_raw_test pprint_test_template[] = { ...@@ -3628,7 +3632,7 @@ static struct btf_raw_test pprint_test_template[] = {
BTF_ENUM_ENC(NAME_TBD, 2), BTF_ENUM_ENC(NAME_TBD, 2),
BTF_ENUM_ENC(NAME_TBD, 3), BTF_ENUM_ENC(NAME_TBD, 3),
/* struct pprint_mapv */ /* [16] */ /* struct pprint_mapv */ /* [16] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32), BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)), /* uint32_t ui32 */ BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)), /* uint32_t ui32 */
BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */ BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */ BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
...@@ -3637,9 +3641,11 @@ static struct btf_raw_test pprint_test_template[] = { ...@@ -3637,9 +3641,11 @@ static struct btf_raw_test pprint_test_template[] = {
BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 126)), /* unused_bits2b */ BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 126)), /* unused_bits2b */
BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)), /* union (anon) */ BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)), /* union (anon) */
BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)), /* aenum */ BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)), /* aenum */
BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)), /* uint32_t ui32b */
BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */
BTF_END_RAW, BTF_END_RAW,
}, },
BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"), BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
.key_size = sizeof(unsigned int), .key_size = sizeof(unsigned int),
.value_size = sizeof(struct pprint_mapv), .value_size = sizeof(struct pprint_mapv),
.key_type_id = 3, /* unsigned int */ .key_type_id = 3, /* unsigned int */
...@@ -3690,7 +3696,7 @@ static struct btf_raw_test pprint_test_template[] = { ...@@ -3690,7 +3696,7 @@ static struct btf_raw_test pprint_test_template[] = {
BTF_ENUM_ENC(NAME_TBD, 2), BTF_ENUM_ENC(NAME_TBD, 2),
BTF_ENUM_ENC(NAME_TBD, 3), BTF_ENUM_ENC(NAME_TBD, 3),
/* struct pprint_mapv */ /* [16] */ /* struct pprint_mapv */ /* [16] */
BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32), BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)), /* uint32_t ui32 */ BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)), /* uint32_t ui32 */
BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */ BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */ BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
...@@ -3699,13 +3705,15 @@ static struct btf_raw_test pprint_test_template[] = { ...@@ -3699,13 +3705,15 @@ static struct btf_raw_test pprint_test_template[] = {
BTF_MEMBER_ENC(NAME_TBD, 19, BTF_MEMBER_OFFSET(2, 126)),/* unused_bits2b */ BTF_MEMBER_ENC(NAME_TBD, 19, BTF_MEMBER_OFFSET(2, 126)),/* unused_bits2b */
BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)), /* union (anon) */ BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)), /* union (anon) */
BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)), /* aenum */ BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)), /* aenum */
BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)), /* uint32_t ui32b */
BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */
/* typedef unsigned int ___int */ /* [17] */ /* typedef unsigned int ___int */ /* [17] */
BTF_TYPEDEF_ENC(NAME_TBD, 18), BTF_TYPEDEF_ENC(NAME_TBD, 18),
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6), /* [18] */ BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6), /* [18] */
BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15), /* [19] */ BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15), /* [19] */
BTF_END_RAW, BTF_END_RAW,
}, },
BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0___int"), BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int"),
.key_size = sizeof(unsigned int), .key_size = sizeof(unsigned int),
.value_size = sizeof(struct pprint_mapv), .value_size = sizeof(struct pprint_mapv),
.key_type_id = 3, /* unsigned int */ .key_type_id = 3, /* unsigned int */
...@@ -3793,6 +3801,8 @@ static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i, ...@@ -3793,6 +3801,8 @@ static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
v->unused_bits2b = 3; v->unused_bits2b = 3;
v->ui64 = i; v->ui64 = i;
v->aenum = i & 0x03; v->aenum = i & 0x03;
v->ui32b = 4;
v->bits2c = 1;
v = (void *)v + rounded_value_size; v = (void *)v + rounded_value_size;
} }
} }
...@@ -3955,7 +3965,8 @@ static int do_test_pprint(int test_num) ...@@ -3955,7 +3965,8 @@ static int do_test_pprint(int test_num)
nexpected_line = snprintf(expected_line, sizeof(expected_line), nexpected_line = snprintf(expected_line, sizeof(expected_line),
"%s%u: {%u,0,%d,0x%x,0x%x,0x%x," "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
"{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n", "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s,"
"%u,0x%x}\n",
percpu_map ? "\tcpu" : "", percpu_map ? "\tcpu" : "",
percpu_map ? cpu : next_key, percpu_map ? cpu : next_key,
cmapv->ui32, cmapv->si32, cmapv->ui32, cmapv->si32,
...@@ -3967,7 +3978,9 @@ static int do_test_pprint(int test_num) ...@@ -3967,7 +3978,9 @@ static int do_test_pprint(int test_num)
cmapv->ui8a[2], cmapv->ui8a[3], cmapv->ui8a[2], cmapv->ui8a[3],
cmapv->ui8a[4], cmapv->ui8a[5], cmapv->ui8a[4], cmapv->ui8a[5],
cmapv->ui8a[6], cmapv->ui8a[7], cmapv->ui8a[6], cmapv->ui8a[7],
pprint_enum_str[cmapv->aenum]); pprint_enum_str[cmapv->aenum],
cmapv->ui32b,
cmapv->bits2c);
err = check_line(expected_line, nexpected_line, err = check_line(expected_line, nexpected_line,
sizeof(expected_line), line); sizeof(expected_line), line);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment