Skip to content

Commit 37c7b1c

Browse files
committed
Merge branch 'bpf-btf-type-fixes'
Yonghong Song says: ==================== Commit 69b693f ("bpf: btf: Introduce BPF Type Format (BTF)") introduced BTF, a debug info format for BTF. The original design has a couple of issues though. First, the bitfield size is only encoded in int type. If the struct member bitfield type is enum, pahole ([1]) or llvm is forced to replace enum with int type. As a result, the original type information gets lost. Second, the original BTF design does not envision the possibility of BTF=>header_file conversion ([2]), hence does not encode "struct" or "union" info for a forward type. Such information is necessary to convert BTF to a header file. This patch set fixed the issue by introducing kind_flag, using one bit in type->info. When kind_flag, the struct/union btf_member->offset will encode both bitfield_size and bit_offset, covering both int and enum base types. The kind_flag is also used to indicate whether the forward type is a union (when set) or a struct. Patch #1 refactors function btf_int_bits_seq_show() so Patch #2 can reuse part of the function. Patch #2 implemented kind_flag support for struct/union/fwd types. Patch #3 added kind_flag support for cgroup local storage map pretty print. Patch #4 syncs kernel uapi btf.h to tools directory. Patch #5 added unit tests for kind_flag. Patch torvalds#6 added tests for kernel bpffs based pretty print with kind_flag. Patch torvalds#7 refactors function btf_dumper_int_bits() so Patch torvalds#8 can reuse part of the function. Patch torvalds#8 added bpftool support of pretty print with kind_flag set. [1] https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=b18354f64cc215368c3bc0df4a7e5341c55c378c [2] https://lwn.net/SubscriberLink/773198/fe3074838f5c3f26/ Change logs: v2 -> v3: . Relocated comments about bitfield_size/bit_offset interpretation of the "offset" field right before the "offset" struct member. . Added missing byte alignment checking for non-bitfield enum member of a struct with kind_flag set. . Added two test cases in unit tests for struct type, kind_flag set, non-bitfield int/enum member, not-byte aligned bit offsets. . Added comments to help understand there is no overflow for total_bits_offset in bpftool function btf_dumper_int_bits(). . Added explanation of typedef type dumping fix in Patch torvalds#8 commit message. v1 -> v2: . If kind_flag is set for a structure, ensure an int member, whether it is a bitfield or not, is a regular int type. . Added support so cgroup local storage map pretty print works with kind_flag. ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
2 parents 6c4fc20 + 8772c8b commit 37c7b1c

File tree

7 files changed

+1047
-92
lines changed

7 files changed

+1047
-92
lines changed

include/linux/btf.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/types.h>
88

99
struct btf;
10+
struct btf_member;
1011
struct btf_type;
1112
union bpf_attr;
1213

@@ -46,7 +47,9 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj,
4647
struct seq_file *m);
4748
int btf_get_fd_by_id(u32 id);
4849
u32 btf_id(const struct btf *btf);
49-
bool btf_type_is_reg_int(const struct btf_type *t, u32 expected_size);
50+
bool btf_member_is_reg_int(const struct btf *btf, const struct btf_type *s,
51+
const struct btf_member *m,
52+
u32 expected_offset, u32 expected_size);
5053

5154
#ifdef CONFIG_BPF_SYSCALL
5255
const struct btf_type *btf_type_by_id(const struct btf *btf, u32 type_id);

include/uapi/linux/btf.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ struct btf_type {
3434
* bits 0-15: vlen (e.g. # of struct's members)
3535
* bits 16-23: unused
3636
* bits 24-27: kind (e.g. int, ptr, array...etc)
37-
* bits 28-31: unused
37+
* bits 28-30: unused
38+
* bit 31: kind_flag, currently used by
39+
* struct, union and fwd
3840
*/
3941
__u32 info;
4042
/* "size" is used by INT, ENUM, STRUCT and UNION.
@@ -52,6 +54,7 @@ struct btf_type {
5254

5355
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
5456
#define BTF_INFO_VLEN(info) ((info) & 0xffff)
57+
#define BTF_INFO_KFLAG(info) ((info) >> 31)
5558

5659
#define BTF_KIND_UNKN 0 /* Unknown */
5760
#define BTF_KIND_INT 1 /* Integer */
@@ -110,9 +113,22 @@ struct btf_array {
110113
struct btf_member {
111114
__u32 name_off;
112115
__u32 type;
113-
__u32 offset; /* offset in bits */
116+
/* If the type info kind_flag is set, the btf_member offset
117+
* contains both member bitfield size and bit offset. The
118+
* bitfield size is set for bitfield members. If the type
119+
* info kind_flag is not set, the offset contains only bit
120+
* offset.
121+
*/
122+
__u32 offset;
114123
};
115124

125+
/* If the struct/union type info kind_flag is set, the
126+
* following two macros are used to access bitfield_size
127+
* and bit_offset from btf_member.offset.
128+
*/
129+
#define BTF_MEMBER_BITFIELD_SIZE(val) ((val) >> 24)
130+
#define BTF_MEMBER_BIT_OFFSET(val) ((val) & 0xffffff)
131+
116132
/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param".
117133
* The exact number of btf_param is stored in the vlen (of the
118134
* info in "struct btf_type").

0 commit comments

Comments
 (0)