bpf: Add btf func info support
Subsystems (8)
v5 cover bpf: Add btf func info support
The BTF support was added to kernel by Commit 69b693f0aefa ("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced .BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.
This patch added func info support to the kernel so we can get better ksym's for bpf function calls. Basically, function call types are passed to kernel and the kernel extract function names from these types in order to contruct ksym for these functions.
The llvm patch at https://urldefense.proofpoint.com/v2/url?u=https-3A__reviews.llvm.org_D53736&d=DwIBAg&c=5VD0RTtNlTh3ycd41b3MUw&r=VQnoQ7LvghIj0gVEaiQSUw&m=CGaBxxwoBOirzU2H_1txiXzzOWCa2Z8ihJYI3JUJhOI&s=kwigBzxoDmvGui52AFHvn7a3oTNYBUEWKdxyTaHKjpA&e=
will generate .BTF section and one more section .BTF.ext.
The .BTF.ext section encodes function type
information. The following is a sample output for selfteststest_btf with file test_btf_haskv.o for translated insns
and jited insns respectively.
$ bpftool prog dump xlated id 1
int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
0: (85) call pc+2#bpf_prog_2dcecc18072623fc_test_long_fname_1
1: (b7) r0 = 0
2: (95) exit
int test_long_fname_1(struct dummy_tracepoint_args * arg):
3: (85) call pc+1#bpf_prog_89d64e4abf0f0126_test_long_fname_2
4: (95) exit
int test_long_fname_2(struct dummy_tracepoint_args * arg):
5: (b7) r2 = 0
6: (63) *(u32 *)(r10 -4) = r2
7: (79) r1 = *(u64 *)(r1 +8)
...
22: (07) r1 += 1
23: (63) *(u32 *)(r0 +4) = r1
24: (95) exit $ bpftool prog dump jited id 1
int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
bpf_prog_b07ccb89267cf242__dummy_tracepoint:
0: push %rbp
1: mov %rsp,%rbp
......
3c: add $0x28,%rbp
40: leaveq
41: retq int test_long_fname_1(struct dummy_tracepoint_args * arg):
bpf_prog_2dcecc18072623fc_test_long_fname_1:
0: push %rbp
1: mov %rsp,%rbp
......
3a: add $0x28,%rbp
3e: leaveq
3f: retq int test_long_fname_2(struct dummy_tracepoint_args * arg):
bpf_prog_89d64e4abf0f0126_test_long_fname_2:
0: push %rbp
1: mov %rsp,%rbp
......
80: add $0x28,%rbp
84: leaveq
85: retqChangelogs:
v4 -> v5:
. Add back BTF_KIND_FUNC_PROTO as v1 did. The difference
is BTF_KIND_FUNC_PROTO cannot have t->name_off now. All param metadata is defined in BTF_KIND_FUNC_PROTO. BTF_KIND_FUNC must have t->name_off != 0 and t->type refers to a BTF_KIND_FUNC_PROTO.
The above is the conclusion after the discussion between Edward Cree, Alexei, Daniel, Yonghong and Martin.
v3 -> v4:
. Remove BTF_KIND_FUNC_PROTO. BTF_KIND_FUNC is used for
both function pointer and subprogram. The name_off field is used to distinguish both.
. The record size is added to the func_info subsection
in .BTF.ext to enable future extension.
. The bpf_prog_info interface change to make it similar
bpf_prog_load.
. Related kernel and libbpf changes to accommodate the
new .BTF.ext and kernel interface changes.
v2 -> v3:
. Removed kernel btf extern functions btf_type_id_func()
and btf_get_name_by_id(). Instead, exposing existing functions btf_type_by_id() and btf_name_by_offset().
. Added comments about ELF section .BTF.ext layout.
. Better codes in btftool as suggested by Edward Cree.
v1 -> v2:
. Added missing sign-off.
. Limited the func_name/struct_member_name length for validity test. . Removed/changed several verifier messages.
. Modified several commit messages to remove line_off reference.
Martin KaFai Lau (4):
bpf: btf: Break up btf_type_is_void()
bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO tools/bpf: Sync kernel btf.h header
tools/bpf: Add tests for BTF_KIND_FUNC_PROTO and BTF_KIND_FUNC
Yonghong Song (9):
bpf: Introduce bpf_func_info
tools/bpf: sync kernel uapi bpf.h header to tools directory tools/bpf: add new fields for program load in lib/bpf tools/bpf: extends test_btf to test load/retrieve func_type info tools/bpf: add support to read .BTF.ext sections tools/bpf: do not use pahole if clang/llvm can generate BTF sections tools/bpf: refactor to implement btf_get_from_id() in lib/bpf tools/bpf: enhance test_btf file testing to test func info tools/bpf: bpftool: add support for func types
include/linux/bpf.h | 5 +- include/linux/bpf_verifier.h | 1 + include/linux/btf.h | 2 + include/uapi/linux/bpf.h | 13 + include/uapi/linux/btf.h | 18 +- kernel/bpf/btf.c | 420 +++++++-- kernel/bpf/core.c | 13 + kernel/bpf/syscall.c | 59 +- kernel/bpf/verifier.c | 120 ++- samples/bpf/Makefile | 8 + tools/bpf/bpftool/btf_dumper.c | 136 +++ tools/bpf/bpftool/main.h | 2 + tools/bpf/bpftool/map.c | 68 +- tools/bpf/bpftool/prog.c | 56 ++ tools/bpf/bpftool/xlated_dumper.c | 33 + tools/bpf/bpftool/xlated_dumper.h | 3 + tools/include/uapi/linux/bpf.h | 13 + tools/include/uapi/linux/btf.h | 18 +- tools/lib/bpf/bpf.c | 50 +- tools/lib/bpf/bpf.h | 4 + tools/lib/bpf/btf.c | 347 +++++++ tools/lib/bpf/btf.h | 51 + tools/lib/bpf/libbpf.c | 87 +- tools/testing/selftests/bpf/Makefile | 8 + tools/testing/selftests/bpf/test_btf.c | 923 ++++++++++++++++++- tools/testing/selftests/bpf/test_btf_haskv.c | 16 +- tools/testing/selftests/bpf/test_btf_nokv.c | 16 +- 27 files changed, 2317 insertions(+), 173 deletions(-)
Signature · 1 line
2.17.1
PATCH v5 1/13 bpf: btf: Break up btf_type_is_void()
This patch breaks up btf_type_is_void() intobtf_type_is_void() and btf_type_is_fwd().
It also adds btf_type_nosize() to better describe it is testing a type has nosize info.
--- kernel/bpf/btf.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-)
kernel/bpf/btf.c +22 -15
@@ -306,15 +306,22 @@ static bool btf_type_is_modifier(const struct btf_type *t)static bool btf_type_is_void (const struct btf_type *t) { -/* void => no type and size info. -* Hence, FWD is also treated as void. -*/ -return t == &btf_void ||BTF_INFO_KIND (t->info) ==BTF_KIND_FWD ; +return t == &btf_void; +} + +static bool btf_type_is_fwd (const struct btf_type *t) +{ +return BTF_INFO_KIND (t->info) ==BTF_KIND_FWD ; +} + +static bool btf_type_nosize (const struct btf_type *t) +{ +return btf_type_is_void (t) ||btf_type_is_fwd (t); } -static bool btf_type_is_void_or_null (const struct btf_type *t) +static bool btf_type_nosize_or_null (const struct btf_type *t) { -return !t ||btf_type_is_void (t); +return !t ||btf_type_nosize (t); }/* union is only a special case of struct:
@@ -826,7 +833,7 @@ const struct btf_type *btf_type_id_size(const struct btf *btf,u32 size =0 ; size_type =btf_type_by_id (btf, size_type_id); -if (btf_type_is_void_or_null (size_type)) +if (btf_type_nosize_or_null (size_type))return NULL ;if (btf_type_has_size (size_type)) {
@@ -842,7 +849,7 @@ const struct btf_type *btf_type_id_size(const struct btf *btf, size = btf->resolved_sizes[size_type_id]; size_type_id = btf->resolved_ids[size_type_id]; size_type =btf_type_by_id (btf, size_type_id); -if (btf_type_is_void (size_type)) +if (btf_type_nosize_or_null (size_type))return NULL ; }
@@ -1164,7 +1171,7 @@ static int btf_modifier_resolve(struct btf_verifier_env *env, }/* "typedef void new_void", "const void"...etc */ -if (btf_type_is_void (next_type)) +if (btf_type_is_void (next_type) ||btf_type_is_fwd (next_type)) goto resolved; if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1178,7 +1185,7 @@ static int btf_modifier_resolve(struct btf_verifier_env *env,* pretty print). */ if (!btf_type_id_size (btf, &next_type_id, &next_type_size) && - !btf_type_is_void (btf_type_id_resolve (btf, &next_type_id))) { + !btf_type_nosize (btf_type_id_resolve (btf, &next_type_id))) {btf_verifier_log_type (env, v->t,"Invalid type_id" );return -EINVAL ; }
@@ -1205,7 +1212,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env, }/* "void *" */ -if (btf_type_is_void (next_type)) +if (btf_type_is_void (next_type) ||btf_type_is_fwd (next_type)) goto resolved; if (!env_type_is_resolve_sink(env, next_type) &&
@@ -1235,7 +1242,7 @@ static int btf_ptr_resolve(struct btf_verifier_env *env, }if (!btf_type_id_size (btf, &next_type_id, &next_type_size) && - !btf_type_is_void (btf_type_id_resolve (btf, &next_type_id))) { + !btf_type_nosize (btf_type_id_resolve (btf, &next_type_id))) {btf_verifier_log_type (env, v->t,"Invalid type_id" );return -EINVAL ; }
@@ -1396,7 +1403,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,/* Check array->index_type */ index_type_id = array->index_type; index_type =btf_type_by_id (btf, index_type_id); -if (btf_type_is_void_or_null (index_type)) { +if (btf_type_nosize_or_null (index_type)) {btf_verifier_log_type (env, v->t,"Invalid index" );return -EINVAL ; }
@@ -1415,7 +1422,7 @@ static int btf_array_resolve(struct btf_verifier_env *env,/* Check array->type */ elem_type_id = array->type; elem_type =btf_type_by_id (btf, elem_type_id); -if (btf_type_is_void_or_null (elem_type)) { +if (btf_type_nosize_or_null (elem_type)) {btf_verifier_log_type (env, v->t,"Invalid elem" );return -EINVAL ;
@@ -1615,7 +1622,7 @@ static int btf_struct_resolve(struct btf_verifier_env *env,const struct btf_type *member_type =btf_type_by_id (env->btf, member_type_id); -if (btf_type_is_void_or_null (member_type)) { +if (btf_type_nosize_or_null (member_type)) {btf_verifier_log_member (env, v->t, member,"Invalid member" );return -EINVAL ;
Signature · 1 line
2.17.1
PATCH v5 2/13 bpf: btf: Add BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO
In reply to Martin KaFai LauThis patch adds BTF_KIND_FUNC and BTF_KIND_FUNC_PROTO to support the function debug info.
BTF_KIND_FUNC_PROTO must not have a name (i.e. !t->name_off) and it is followed by >= 0 'struct bpf_param' objects to describe the function arguments.
The BTF_KIND_FUNC must have a valid name and it must refer back to a BTF_KIND_FUNC_PROTO.
The above is the conclusion after the discussion between Edward Cree, Alexei, Daniel, Yonghong and Martin.
By combining BTF_KIND_FUNC and BTF_LIND_FUNC_PROTO, a complete function signature can be obtained. It will be used in the later patches to learn the function signature of a running bpf program.
--- include/uapi/linux/btf.h | 18 +- kernel/bpf/btf.c | 389 ++++++++++++++++++++++++++++++++++----- 2 files changed, 354 insertions(+), 53 deletions(-)
include/uapi/linux/btf.h +15 -3
@@ -40,7 +40,8 @@ struct btf_type {/* "size" is used by INT, ENUM, STRUCT and UNION. * "size" tells the size of the type it is describing. * -* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT. +* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, +* FUNC and FUNC_PROTO. * "type" is a type_id referring to another type. */ union {
@@ -64,8 +65,10 @@ struct btf_type {#define BTF_KIND_VOLATILE 9/* Volatile */ #define BTF_KIND_CONST 10/* Const */ #define BTF_KIND_RESTRICT 11/* Restrict */ -#define BTF_KIND_MAX 11 -#define NR_BTF_KINDS 12 +#define BTF_KIND_FUNC 12/* Function */ +#define BTF_KIND_FUNC_PROTO 13/* Function Proto */ +#define BTF_KIND_MAX 13 +#define NR_BTF_KINDS 14/* For some specific BTF_KIND, "struct btf_type" is immediately * followed by extra data.
@@ -110,4 +113,13 @@ struct btf_member { __u32 offset; /* offset in bits */ }; +/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param". +* The exact number of btf_param is stored in the vlen (of the +* info in "struct btf_type"). +*/ +struct btf_param { +__u32 name_off; +__u32 type; +}; +#endif /* _UAPI__LINUX_BTF_H__ */
kernel/bpf/btf.c +339 -50
494 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v5 3/13 tools/bpf: Sync kernel btf.h header
In reply to Martin KaFai LauThe kernel uapi btf.h is synced to the tools directory.
--- tools/include/uapi/linux/btf.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
tools/include/uapi/linux/btf.h +15 -3
@@ -40,7 +40,8 @@ struct btf_type {/* "size" is used by INT, ENUM, STRUCT and UNION. * "size" tells the size of the type it is describing. * -* "type" is used by PTR, TYPEDEF, VOLATILE, CONST and RESTRICT. +* "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, +* FUNC and FUNC_PROTO. * "type" is a type_id referring to another type. */ union {
@@ -64,8 +65,10 @@ struct btf_type {#define BTF_KIND_VOLATILE 9/* Volatile */ #define BTF_KIND_CONST 10/* Const */ #define BTF_KIND_RESTRICT 11/* Restrict */ -#define BTF_KIND_MAX 11 -#define NR_BTF_KINDS 12 +#define BTF_KIND_FUNC 12/* Function */ +#define BTF_KIND_FUNC_PROTO 13/* Function Proto */ +#define BTF_KIND_MAX 13 +#define NR_BTF_KINDS 14/* For some specific BTF_KIND, "struct btf_type" is immediately * followed by extra data.
@@ -110,4 +113,13 @@ struct btf_member { __u32 offset; /* offset in bits */ }; +/* BTF_KIND_FUNC_PROTO is followed by multiple "struct btf_param". +* The exact number of btf_param is stored in the vlen (of the +* info in "struct btf_type"). +*/ +struct btf_param { +__u32 name_off; +__u32 type; +}; +#endif /* _UAPI__LINUX_BTF_H__ */
Signature · 1 line
2.17.1
PATCH v5 4/13 tools/bpf: Add tests for BTF_KIND_FUNC_PROTO and BTF_KIND_FUNC
In reply to Martin KaFai LauThis patch adds unit tests for BTF_KIND_FUNC_PROTO and BTF_KIND_FUNC to test_btf.
--- tools/lib/bpf/btf.c | 4 + tools/testing/selftests/bpf/test_btf.c | 474 ++++++++++++++++++++++++- 2 files changed, 476 insertions(+), 2 deletions(-)
tools/lib/bpf/btf.c +4 -0
@@ -165,6 +165,10 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)case BTF_KIND_ENUM : next_type += vlen *sizeof (struct btf_enum );break ; +case BTF_KIND_FUNC_PROTO : + next_type += vlen *sizeof (struct btf_param ); +break ; +case BTF_KIND_FUNC :case BTF_KIND_TYPEDEF :case BTF_KIND_PTR :case BTF_KIND_FWD :
tools/testing/selftests/bpf/test_btf.c +472 -2
486 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v5 5/13 bpf: Introduce bpf_func_info
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
This patch added interface to load a program with the following additional information:
. prog_btf_fd
. func_info, func_info_rec_size and func_info_cnt
where func_info will provide function range and type_id corresponding to each function.
The func_info_rec_size is introduced in the UAPI to specify struct bpf_func_info size passed from user space. This intends to make bpf_func_info structure growable in the future. If the kernel gets a different bpf_func_info size from userspace, it will try to handle user request with part of bpf_func_info it can understand. In this patch, kernel can understand
struct bpf_func_info {
__u32 insn_offset;
__u32 type_id; };
If user passed a bpf func_info record size of 16 bytes, the kernel can still handle part of records with the above definition.
If verifier agrees with function range provided by the user, the bpf_prog ksym for each function will use the func name provided in the type_id, which is supposed to provide better encoding as it is not limited by 16 bytes program name limitation and this is better for bpf program which contains multiple subprograms.
The bpf_prog_info interface is also extended to
return btf_id, func_info, func_info_rec_size and func_info_cnt to userspace, so userspace can print out the function prototype for each xlated function. The insn_offset in the returned func_info corresponds to the insn offset for xlated functions. With other jit related fields in bpf_prog_info, userspace can also print out function prototypes for each jited function.
--- include/linux/bpf.h | 5 +- include/linux/bpf_verifier.h | 1 + include/linux/btf.h | 2 + include/uapi/linux/bpf.h | 13 ++++ kernel/bpf/btf.c | 4 +- kernel/bpf/core.c | 13 ++++ kernel/bpf/syscall.c | 59 +++++++++++++++-- kernel/bpf/verifier.c | 120 ++++++++++++++++++++++++++++++++++- 8 files changed, 209 insertions(+), 8 deletions(-)
include/linux/bpf.h +4 -1
@@ -316,6 +316,8 @@ struct bpf_prog_aux {void *security;#endif struct bpf_prog_offload *offload; +struct btf *btf; +u32 type_id;/* type id for this prog/func */ union {struct work_struct work;struct rcu_head rcu;
@@ -527,7 +529,8 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size) }/* verify correctness of eBPF program */ -int bpf_check (struct bpf_prog **fp,union bpf_attr *attr); +int bpf_check (struct bpf_prog **fp,union bpf_attr *attr, +union bpf_attr __user *uattr);void bpf_patch_call_args (struct bpf_insn *insn,u32 stack_depth);/* Map specifics */
include/linux/bpf_verifier.h +1 -0
@@ -204,6 +204,7 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)struct bpf_subprog_info {u32 start;/* insn idx of function entry point */ u16 stack_depth;/* max. stack depth used by this function */ +u32 type_id;/* btf type_id for this subprog */ };/* single container for all structs
include/linux/btf.h +2 -0
@@ -46,5 +46,7 @@ void btf_type_seq_show(const struct btf *btf, u32 type_id, void *obj, struct seq_file *m);int btf_get_fd_by_id (u32 id);u32 btf_id (const struct btf *btf); +const struct btf_type *btf_type_by_id (const struct btf *btf,u32 type_id); +const char *btf_name_by_offset (const struct btf *btf,u32 offset);#endif
include/uapi/linux/bpf.h +13 -0
@@ -335,6 +335,10 @@ union bpf_attr {* (context accesses, allowed helpers, etc). */ __u32 expected_attach_type; +__u32 prog_btf_fd;/* fd pointing to BTF type data */ +__u32 func_info_rec_size;/* userspace bpf_func_info size */ +__aligned_u64 func_info;/* func info */ +__u32 func_info_cnt;/* number of bpf_func_info records */ };struct {/* anonymous struct used by BPF_OBJ_* commands */
@@ -2635,6 +2639,10 @@ struct bpf_prog_info {__u32 nr_jited_func_lens;__aligned_u64 jited_ksyms;__aligned_u64 jited_func_lens; +__u32 btf_id; +__u32 func_info_rec_size; +__aligned_u64 func_info; +__u32 func_info_cnt; } __attribute__((aligned(8)));struct bpf_map_info {
@@ -2946,4 +2954,9 @@ struct bpf_flow_keys { }; }; +struct bpf_func_info { +__u32 insn_offset; +__u32 type_id; +}; +#endif /* _UAPI__LINUX_BPF_H__ */
kernel/bpf/btf.c +2 -2
@@ -474,7 +474,7 @@ static bool btf_name_valid_identifier(const struct btf *btf, u32 offset)return !*src; } -static const char *btf_name_by_offset (const struct btf *btf,u32 offset) +const char *btf_name_by_offset (const struct btf *btf,u32 offset) {if (!offset)return "(anon)" ;
@@ -484,7 +484,7 @@ static const char *btf_name_by_offset(const struct btf *btf, u32 offset)return "(invalid-name-offset)" ; } -static const struct btf_type *btf_type_by_id (const struct btf *btf,u32 type_id) +const struct btf_type *btf_type_by_id (const struct btf *btf,u32 type_id) {if (type_id > btf->nr_types)return NULL ;
kernel/bpf/core.c +13 -0
@@ -21,12 +21,14 @@* Kris Katterjohn - Added many additional checks in bpf_check_classic() */ +#include <uapi/linux/btf.h> #include <linux/filter.h> #include <linux/skbuff.h> #include <linux/vmalloc.h> #include <linux/random.h> #include <linux/moduleloader.h> #include <linux/bpf.h> +#include <linux/btf.h> #include <linux/frame.h> #include <linux/rbtree_latch.h> #include <linux/kallsyms.h>
@@ -390,6 +392,8 @@ bpf_get_prog_addr_region(const struct bpf_prog *prog,static void bpf_get_prog_name (const struct bpf_prog *prog,char *sym) {const char *end = sym +KSYM_NAME_LEN ; +const struct btf_type *type; +const char *func_name; BUILD_BUG_ON(sizeof("bpf_prog_") + sizeof(prog->tag) * 2 +
@@ -404,6 +408,15 @@ static void bpf_get_prog_name(const struct bpf_prog *prog, char *sym) sym +=snprintf (sym,KSYM_NAME_LEN ,"bpf_prog_" ); sym =bin2hex (sym, prog->tag,sizeof (prog->tag)); + +/* prog->aux->name will be ignored if full btf name is available */ +if (prog->aux->btf) { + type =btf_type_by_id (prog->aux->btf, prog->aux->type_id); + func_name =btf_name_by_offset (prog->aux->btf, type->name_off); +snprintf (sym, (size_t )(end - sym),"_%s" , func_name); +return ; + } +if (prog->aux->name[0 ])snprintf (sym, (size_t )(end - sym),"_%s" , prog->aux->name);else
kernel/bpf/syscall.c +55 -4
96 lines not on this page · raw message
kernel/bpf/verifier.c +119 -1
154 lines not on this page · raw message
Signature · 1 line
2.17.1
kbuild test robot
build botRe: [PATCH v5 bpf-next 05/13] bpf: Introduce bpf_func_info
Thank you for the patch! Yet something to improve:
Hi Yonghong,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on bpf-next/master]
url: https://github.com/0day-ci/linux/commits/Martin-KaFai-Lau/bpf-Add-btf-func-info-support/20181120-181333 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master config: i386-randconfig-s0-11191736 (attached as .config) compiler: gcc-6 (Debian 6.4.0-9) 6.4.0 20171026 reproduce: # save the attached .config to linux build tree make ARCH=i386
All errors (new ones prefixed by >>):
kernel/bpf/core.o: In function `bpf_get_prog_name':
>> kernel/bpf/core.c:414: undefined reference to `btf_type_by_id' >> kernel/bpf/core.c:415: undefined reference to `btf_name_by_offset'
vim +414 kernel/bpf/core.c
391
392 static void bpf_get_prog_name(const struct bpf_prog *prog, char *sym)
393 {
394 const char *end = sym + KSYM_NAME_LEN;
395 const struct btf_type *type;
396 const char *func_name;
397
398 BUILD_BUG_ON(sizeof("bpf_prog_") +
399 sizeof(prog->tag) * 2 +
400 /* name has been null terminated.
401 * We should need +1 for the '_' preceding
402 * the name. However, the null character
403 * is double counted between the name and the
404 * sizeof("bpf_prog_") above, so we omit
405 * the +1 here.
406 */
407 sizeof(prog->aux->name) > KSYM_NAME_LEN);
408
409 sym += snprintf(sym, KSYM_NAME_LEN, "bpf_prog_");
410 sym = bin2hex(sym, prog->tag, sizeof(prog->tag));
411
412 /* prog->aux->name will be ignored if full btf name is available */
413 if (prog->aux->btf) {
> 414 type = btf_type_by_id(prog->aux->btf, prog->aux->type_id);
> 415 func_name = btf_name_by_offset(prog->aux->btf, type->name_off); 416 snprintf(sym, (size_t)(end - sym), "_%s", func_name);
417 return;
418 }
419
420 if (prog->aux->name[0])
421 snprintf(sym, (size_t)(end - sym), "_%s", prog->aux->name);
422 else
423 *sym = 0;
424 }
425
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
PATCH v5 6/13 tools/bpf: sync kernel uapi bpf.h header to tools directory
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
The kernel uapi bpf.h is synced to tools directory.
--- tools/include/uapi/linux/bpf.h | 13 +++++++++++++ 1 file changed, 13 insertions(+)
tools/include/uapi/linux/bpf.h +13 -0
@@ -335,6 +335,10 @@ union bpf_attr {* (context accesses, allowed helpers, etc). */ __u32 expected_attach_type; +__u32 prog_btf_fd;/* fd pointing to BTF type data */ +__u32 func_info_rec_size;/* userspace bpf_func_info size */ +__aligned_u64 func_info;/* func info */ +__u32 func_info_cnt;/* number of bpf_func_info records */ };struct {/* anonymous struct used by BPF_OBJ_* commands */
@@ -2631,6 +2635,10 @@ struct bpf_prog_info {__u32 nr_jited_func_lens;__aligned_u64 jited_ksyms;__aligned_u64 jited_func_lens; +__u32 btf_id; +__u32 func_info_rec_size; +__aligned_u64 func_info; +__u32 func_info_cnt; } __attribute__((aligned(8)));struct bpf_map_info {
@@ -2942,4 +2950,9 @@ struct bpf_flow_keys { }; }; +struct bpf_func_info { +__u32 insn_offset; +__u32 type_id; +}; +#endif /* _UAPI__LINUX_BPF_H__ */
Signature · 1 line
2.17.1
PATCH v5 7/13 tools/bpf: add new fields for program load in lib/bpf
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
The new fields are added for program load in lib/bpf so application uses api bpf_load_program_xattr() is able to load program with btf and func_info data.
This functionality will be used in next patch by bpf selftest test_btf.
--- tools/lib/bpf/bpf.c | 4 ++++ tools/lib/bpf/bpf.h | 4 ++++ 2 files changed, 8 insertions(+)
tools/lib/bpf/bpf.c +4 -0
@@ -196,6 +196,10 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, attr.log_level =0 ; attr.kern_version = load_attr->kern_version; attr.prog_ifindex = load_attr->prog_ifindex; + attr.prog_btf_fd = load_attr->prog_btf_fd; + attr.func_info_rec_size = load_attr->func_info_rec_size; + attr.func_info_cnt = load_attr->func_info_cnt; + attr.func_info =ptr_to_u64 (load_attr->func_info);memcpy (attr.prog_name, load_attr->name,min (name_len,BPF_OBJ_NAME_LEN -1 ));
tools/lib/bpf/bpf.h +4 -0
@@ -74,6 +74,10 @@ struct bpf_load_program_attr {const char *license;__u32 kern_version;__u32 prog_ifindex; +__u32 prog_btf_fd; +__u32 func_info_rec_size; +const void *func_info; +__u32 func_info_cnt; };/* Flags to direct loading requirements */
Signature · 1 line
2.17.1
PATCH v5 8/13 tools/bpf: extends test_btf to test load/retrieve func_type info
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
A two function bpf program is loaded with btf and func_info. After successful prog load, the bpf_get_info syscall is called to retrieve prog info to ensure the types returned from the kernel matches the types passed to the kernel from the user space.
Several negative tests are also added to test loading/retriving of func_type info.
--- tools/testing/selftests/bpf/test_btf.c | 332 ++++++++++++++++++++++++- 1 file changed, 329 insertions(+), 3 deletions(-)
tools/testing/selftests/bpf/test_btf.c +329 -3
@@ -5,6 +5,7 @@#include <linux/btf.h> #include <linux/err.h> #include <linux/kernel.h> +#include <linux/filter.h> #include <bpf/bpf.h> #include <sys/resource.h> #include <libelf.h>
@@ -22,9 +23,13 @@#include "bpf_rlimit.h" #include "bpf_util.h" +#define MAX_INSNS 512 +#define MAX_SUBPROGS 16 +static uint32_t pass_cnt;static uint32_t error_cnt;static uint32_t skip_cnt; +static bool jit_enabled; #define CHECK(condition, format...) ({ \ int __ret = !!(condition); \
@@ -60,6 +65,24 @@ static int __base_pr(const char *format, ...)return err; } +static bool is_jit_enabled (void ) +{ +const char *jit_sysctl ="/proc/sys/net/core/bpf_jit_enable" ; +bool enabled = false; +int sysctl_fd; + + sysctl_fd =open (jit_sysctl,0 ,O_RDONLY ); +if (sysctl_fd !=-1 ) { +char tmpc; + +if (read (sysctl_fd, &tmpc,sizeof (tmpc)) ==1 ) + enabled = (tmpc !='0' ); +close (sysctl_fd); + } + +return enabled; +} +#define BTF_INFO_ENC (kind, root, vlen) \ ((!!(root) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
@@ -115,6 +138,7 @@ static struct args {bool get_info_test;bool pprint_test;bool always_log; +bool func_type_test; } args;static char btf_log_buf[BTF_LOG_BUF_SIZE ];
@@ -2947,16 +2971,310 @@ static int test_pprint(void)return err; } +static struct btf_func_type_test { +const char *descr; +const char *str_sec; +__u32 raw_types[MAX_NR_RAW_TYPES ]; +__u32 str_sec_size; +struct bpf_insn insns[MAX_INSNS ]; +__u32 prog_type; +__u32 func_info[MAX_SUBPROGS ][2 ]; +__u32 func_info_rec_size; +__u32 func_info_cnt; +bool expected_prog_load_failure; +} func_type_test[] = { +{ + .descr ="func_type (main func + one sub)" , + .raw_types = { +BTF_TYPE_INT_ENC (NAME_TBD ,BTF_INT_SIGNED ,0 ,32 ,4 ),/* [1] */ +BTF_TYPE_INT_ENC (NAME_TBD ,0 ,0 ,32 ,4 ),/* [2] */ +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [3] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [4] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_ENC (NAME_TBD ,3 ),/* [5] */ +BTF_FUNC_ENC (NAME_TBD ,4 ),/* [6] */ +BTF_END_RAW , + }, + .str_sec ="\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" , + .str_sec_size =sizeof ("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" ), + .insns = { +BPF_RAW_INSN (BPF_JMP |BPF_CALL ,0 ,1 ,0 ,2 ), +BPF_MOV64_IMM (BPF_REG_0 ,1 ), +BPF_EXIT_INSN (), +BPF_MOV64_IMM (BPF_REG_0 ,2 ), +BPF_EXIT_INSN (), + }, + .prog_type =BPF_PROG_TYPE_TRACEPOINT , + .func_info = { {0 ,5 }, {3 ,6 } }, + .func_info_rec_size =8 , + .func_info_cnt =2 , +}, + +{ + .descr ="func_type (Incorrect func_info_rec_size)" , + .raw_types = { +BTF_TYPE_INT_ENC (NAME_TBD ,BTF_INT_SIGNED ,0 ,32 ,4 ),/* [1] */ +BTF_TYPE_INT_ENC (NAME_TBD ,0 ,0 ,32 ,4 ),/* [2] */ +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [3] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [4] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_ENC (NAME_TBD ,3 ),/* [5] */ +BTF_FUNC_ENC (NAME_TBD ,4 ),/* [6] */ +BTF_END_RAW , + }, + .str_sec ="\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" , + .str_sec_size =sizeof ("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" ), + .insns = { +BPF_RAW_INSN (BPF_JMP |BPF_CALL ,0 ,1 ,0 ,2 ), +BPF_MOV64_IMM (BPF_REG_0 ,1 ), +BPF_EXIT_INSN (), +BPF_MOV64_IMM (BPF_REG_0 ,2 ), +BPF_EXIT_INSN (), + }, + .prog_type =BPF_PROG_TYPE_TRACEPOINT , + .func_info = { {0 ,5 }, {3 ,6 } }, + .func_info_rec_size =4 , + .func_info_cnt =2 , + .expected_prog_load_failure = true, +}, + +{ + .descr ="func_type (Incorrect func_info_cnt)" , + .raw_types = { +BTF_TYPE_INT_ENC (NAME_TBD ,BTF_INT_SIGNED ,0 ,32 ,4 ),/* [1] */ +BTF_TYPE_INT_ENC (NAME_TBD ,0 ,0 ,32 ,4 ),/* [2] */ +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [3] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [4] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_ENC (NAME_TBD ,3 ),/* [5] */ +BTF_FUNC_ENC (NAME_TBD ,4 ),/* [6] */ +BTF_END_RAW , + }, + .str_sec ="\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" , + .str_sec_size =sizeof ("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" ), + .insns = { +BPF_RAW_INSN (BPF_JMP |BPF_CALL ,0 ,1 ,0 ,2 ), +BPF_MOV64_IMM (BPF_REG_0 ,1 ), +BPF_EXIT_INSN (), +BPF_MOV64_IMM (BPF_REG_0 ,2 ), +BPF_EXIT_INSN (), + }, + .prog_type =BPF_PROG_TYPE_TRACEPOINT , + .func_info = { {0 ,5 }, {3 ,6 } }, + .func_info_rec_size =8 , + .func_info_cnt =1 , + .expected_prog_load_failure = true, +}, + +{ + .descr ="func_type (Incorrect bpf_func_info.insn_offset)" , + .raw_types = { +BTF_TYPE_INT_ENC (NAME_TBD ,BTF_INT_SIGNED ,0 ,32 ,4 ),/* [1] */ +BTF_TYPE_INT_ENC (NAME_TBD ,0 ,0 ,32 ,4 ),/* [2] */ +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [3] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ENC (1 ,2 ),/* [4] */ +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,2 ), +BTF_FUNC_PROTO_ARG_ENC (NAME_TBD ,1 ), +BTF_FUNC_ENC (NAME_TBD ,3 ),/* [5] */ +BTF_FUNC_ENC (NAME_TBD ,4 ),/* [6] */ +BTF_END_RAW , + }, + .str_sec ="\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" , + .str_sec_size =sizeof ("\0int\0unsigned int\0a\0b\0c\0d\0funcA\0funcB" ), + .insns = { +BPF_RAW_INSN (BPF_JMP |BPF_CALL ,0 ,1 ,0 ,2 ), +BPF_MOV64_IMM (BPF_REG_0 ,1 ), +BPF_EXIT_INSN (), +BPF_MOV64_IMM (BPF_REG_0 ,2 ), +BPF_EXIT_INSN (), + }, + .prog_type =BPF_PROG_TYPE_TRACEPOINT , + .func_info = { {0 ,5 }, {2 ,6 } }, + .func_info_rec_size =8 , + .func_info_cnt =2 , + .expected_prog_load_failure = true, +}, + +}; + +static size_t probe_prog_length (const struct bpf_insn *fp) +{ +size_t len; + +for (len =MAX_INSNS -1 ; len >0 ; --len) +if (fp[len].code !=0 || fp[len].imm !=0 ) +break ; +return len +1 ; +} + +static int do_test_func_type (int test_num) +{ +const struct btf_func_type_test *test = &func_type_test[test_num]; +unsigned int raw_btf_size, info_len, rec_size; +int i, btf_fd =-1 , prog_fd =-1 , err =0 ; +struct bpf_load_program_attr attr = {}; +void *raw_btf, *func_info =NULL ; +struct bpf_prog_info info = {}; +struct bpf_func_info *finfo; + +fprintf (stderr,"%s......" , test->descr); + raw_btf =btf_raw_create (&hdr_tmpl, test->raw_types, + test->str_sec, test->str_sec_size, + &raw_btf_size); + +if (!raw_btf) +return -1 ; + + *btf_log_buf ='\0' ; + btf_fd =bpf_load_btf (raw_btf, raw_btf_size, + btf_log_buf,BTF_LOG_BUF_SIZE , + args.always_log); +free (raw_btf); + +if (CHECK (btf_fd ==-1 ,"invalid btf_fd errno:%d" , errno)) { + err =-1 ; + goto done; + } + +if (*btf_log_buf && args.always_log) +fprintf (stderr,"\n%s" , btf_log_buf); + + attr.prog_type = test->prog_type; + attr.insns = test->insns; + attr.insns_cnt =probe_prog_length (attr.insns); + attr.license ="GPL" ; + attr.prog_btf_fd = btf_fd; + attr.func_info_rec_size = test->func_info_rec_size; + attr.func_info_cnt = test->func_info_cnt; + attr.func_info = test->func_info; + + *btf_log_buf ='\0' ; + prog_fd =bpf_load_program_xattr (&attr, btf_log_buf, +BTF_LOG_BUF_SIZE ); +if (test->expected_prog_load_failure && prog_fd ==-1 ) { + err =0 ; + goto done; + } +if (CHECK (prog_fd ==-1 ,"invalid prog_id errno:%d" , errno)) { +fprintf (stderr,"%s\n" , btf_log_buf); + err =-1 ; + goto done; + } +if (!jit_enabled) { + skip_cnt++; +fprintf (stderr,"SKIPPED, please enable sysctl bpf_jit_enable\n" ); + err =0 ; + goto done; + } + +/* get necessary lens */ + info_len =sizeof (struct bpf_prog_info ); + err =bpf_obj_get_info_by_fd (prog_fd, &info, &info_len); +if (CHECK (err ==-1 ,"invalid get info (1st) errno:%d" , errno)) { +fprintf (stderr,"%s\n" , btf_log_buf); + err =-1 ; + goto done; + } +if (CHECK (info.func_info_cnt !=2 , +"incorrect info.func_info_cnt (1st) %d\n" , + info.func_info_cnt)) { + err =-1 ; + goto done; + } + rec_size = info.func_info_rec_size; +if (CHECK (rec_size <4 , +"incorrect info.func_info_rec_size (1st) %d\n" , rec_size)) { + err =-1 ; + goto done; + } + + func_info =malloc (info.func_info_cnt * rec_size); +if (CHECK (!func_info,"out of memeory" )) { + err =-1 ; + goto done; + } + +/* reset info to only retrieve func_info related data */ +memset (&info,0 ,sizeof (info)); + info.func_info_cnt =2 ; + info.func_info_rec_size = rec_size; + info.func_info =ptr_to_u64 (func_info); + err =bpf_obj_get_info_by_fd (prog_fd, &info, &info_len); +if (CHECK (err ==-1 ,"invalid get info (2nd) errno:%d" , errno)) { +fprintf (stderr,"%s\n" , btf_log_buf); + err =-1 ; + goto done; + } +if (CHECK (info.func_info_cnt !=2 , +"incorrect info.func_info_cnt (2nd) %d\n" , + info.func_info_cnt)) { + err =-1 ; + goto done; + } +if (CHECK (info.func_info_rec_size != rec_size, +"incorrect info.func_info_rec_size (2nd) %d\n" , + info.func_info_rec_size)) { + err =-1 ; + goto done; + } + + finfo = func_info; +for (i =0 ; i <2 ; i++) { +if (CHECK (finfo->type_id != test->func_info[i][1 ], +"incorrect func_type %u expected %u" , + finfo->type_id, test->func_info[i][1 ])) { + err =-1 ; + goto done; + } + finfo = (void *)finfo + rec_size; + } + +done: +if (*btf_log_buf && (err || args.always_log)) +fprintf (stderr,"\n%s" , btf_log_buf); + +if (btf_fd !=-1 ) +close (btf_fd); +if (prog_fd !=-1 ) +close (prog_fd); +free (func_info); +return err; +} + +static int test_func_type (void ) +{ +unsigned int i; +int err =0 ; + +for (i =0 ; i <ARRAY_SIZE (func_type_test); i++) + err |=count_result (do_test_func_type (i)); + +return err; +} +static void usage (const char *cmd) { -fprintf (stderr,"Usage: %s [-l] [[-r test_num (1 - %zu)] | [-g test_num (1 - %zu)] | [-f test_num (1 - %zu)] | [-p]]\n" , +fprintf (stderr,"Usage: %s [-l] [[-r test_num (1 - %zu)] |" +" [-g test_num (1 - %zu)] |" +" [-f test_num (1 - %zu)] | [-p] | [-k] ]\n" , cmd,ARRAY_SIZE (raw_tests),ARRAY_SIZE (get_info_tests),ARRAY_SIZE (file_tests)); }static int parse_args (int argc,char **argv) { -const char *optstr ="lpf:r:g:" ; +const char *optstr ="lpkf:r:g:" ;int opt;while ((opt =getopt (argc, argv, optstr)) !=-1 ) {
@@ -2979,6 +3297,9 @@ static int parse_args(int argc, char **argv)case 'p' : args.pprint_test = true;break ; +case 'k' : + args.func_type_test = true; +break ;case 'h' :usage (argv[0 ]);exit (0 );
@@ -3032,6 +3353,8 @@ int main(int argc, char **argv)if (args.always_log)libbpf_set_print (__base_pr, __base_pr, __base_pr); + jit_enabled =is_jit_enabled (); +if (args.raw_test) err |=test_raw ();
@@ -3044,8 +3367,11 @@ int main(int argc, char **argv)if (args.pprint_test) err |=test_pprint (); +if (args.func_type_test) + err |=test_func_type (); +if (args.raw_test || args.get_info_test || args.file_test || - args.pprint_test) + args.pprint_test || args.func_type_test) goto done; err |=test_raw ();
Signature · 1 line
2.17.1
PATCH v5 9/13 tools/bpf: add support to read .BTF.ext sections
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
The .BTF section is already available to encode types. These types can be used for map
pretty print. The whole .BTF will be passed to the kernel as well for which kernel can verify and return to the user space for pretty print etc.
The llvm patch at https://reviews.llvm.org/D53736
will generate .BTF section and one more section .BTF.ext. The .BTF.ext section encodes function type information and line information. Note that
this patch set only supports function type info. The functionality is implemented in libbpf.
The .BTF section can be directly loaded into the kernel, and the .BTF.ext section cannot. The loader may need to do some relocation and merging, similar to merging multiple code sections, before loading into the kernel.
--- tools/lib/bpf/bpf.c | 46 ++++++- tools/lib/bpf/btf.c | 274 +++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/btf.h | 50 ++++++++ tools/lib/bpf/libbpf.c | 87 ++++++++++--- 4 files changed, 442 insertions(+), 15 deletions(-)
tools/lib/bpf/bpf.c +45 -1
@@ -177,6 +177,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr, char *log_buf, size_t log_buf_sz) {union bpf_attr attr; +void *finfo =NULL ;__u32 name_len;int fd;
@@ -207,12 +208,55 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,if (fd >=0 || !log_buf || !log_buf_sz)return fd; +/* After bpf_prog_load, the kernel may modify certain attributes +* to give user space a hint how to deal with loading failure. +* Check to see whether we can make some changes and load again. +*/ +if (errno ==E2BIG && attr.func_info_cnt && + attr.func_info_rec_size < load_attr->func_info_rec_size) { +__u32 actual_rec_size = load_attr->func_info_rec_size; +__u32 expected_rec_size = attr.func_info_rec_size; +__u32 finfo_cnt = load_attr->func_info_cnt; +__u64 finfo_len = actual_rec_size * finfo_cnt; +const void *orecord; +void *nrecord; +int i; + + finfo =malloc (finfo_len); +if (!finfo) +/* further try with log buffer won't help */ +return fd; + +/* zero out bytes kernel does not understand */ + orecord = load_attr->func_info; + nrecord = finfo; +for (i =0 ; i < load_attr->func_info_cnt; i++) { +memcpy (nrecord, orecord, expected_rec_size); +memset (nrecord + expected_rec_size,0 , + actual_rec_size - expected_rec_size); + orecord += actual_rec_size; + nrecord += actual_rec_size; + } + +/* try with corrected func info records */ + attr.func_info =ptr_to_u64 (finfo); + attr.func_info_rec_size = load_attr->func_info_rec_size; + + fd =sys_bpf (BPF_PROG_LOAD , &attr,sizeof (attr)); + +if (fd >=0 || !log_buf || !log_buf_sz) + goto done; + } +/* Try again with log */ attr.log_buf =ptr_to_u64 (log_buf); attr.log_size = log_buf_sz; attr.log_level =1 ; log_buf[0 ] =0 ; -return sys_bpf (BPF_PROG_LOAD , &attr,sizeof (attr)); + fd =sys_bpf (BPF_PROG_LOAD , &attr,sizeof (attr)); +done: +free (finfo); +return fd; } int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
tools/lib/bpf/btf.c +274 -0
283 lines not on this page · raw message
tools/lib/bpf/btf.h +50 -0
64 lines not on this page · raw message
tools/lib/bpf/libbpf.c +73 -14
180 lines not on this page · raw message
Signature · 1 line
2.17.1
PATCH v5 10/13 tools/bpf: do not use pahole if clang/llvm can generate BTF sections
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
Add additional checks in tools/testing/selftests/bpf and samples/bpf such that if clang/llvm compiler can generate BTF sections, do not use pahole.
--- samples/bpf/Makefile | 8 ++++++++ tools/testing/selftests/bpf/Makefile | 8 ++++++++ 2 files changed, 16 insertions(+)
samples/bpf/Makefile +8 -0
@@ -208,12 +208,20 @@ endif BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') +BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \ + $(CLANG) -target bpf -O2 -g -c -x c - -o ./llvm_btf_verify.o; \ + readelf -S ./llvm_btf_verify.o | grep BTF; \ + /bin/rm -f ./llvm_btf_verify.o) +ifneq ($(BTF_LLVM_PROBE),) + EXTRA_CFLAGS += -g +else ifneq ($(and $(BTF_LLC_PROBE),$(BTF_PAHOLE_PROBE),$(BTF_OBJCOPY_PROBE)),) EXTRA_CFLAGS += -g LLC_FLAGS += -mattr=dwarfris DWARF2BTF = y endif +endif # Trick to allow make to be run from this directory all:
tools/testing/selftests/bpf/Makefile +8 -0
@@ -126,7 +126,14 @@ $(OUTPUT)/test_stack_map.o: test_queue_stack_map.h BTF_LLC_PROBE := $(shell $(LLC) -march=bpf -mattr=help 2>&1 | grep dwarfris) BTF_PAHOLE_PROBE := $(shell $(BTF_PAHOLE) --help 2>&1 | grep BTF) BTF_OBJCOPY_PROBE := $(shell $(LLVM_OBJCOPY) --help 2>&1 | grep -i 'usage.*llvm') +BTF_LLVM_PROBE := $(shell echo "int main() { return 0; }" | \ + $(CLANG) -target bpf -O2 -g -c -x c - -o ./llvm_btf_verify.o; \ + readelf -S ./llvm_btf_verify.o | grep BTF; \ + /bin/rm -f ./llvm_btf_verify.o) +ifneq ($(BTF_LLVM_PROBE),) + CLANG_FLAGS += -g +else ifneq ($(BTF_LLC_PROBE),) ifneq ($(BTF_PAHOLE_PROBE),) ifneq ($(BTF_OBJCOPY_PROBE),)
@@ -136,6 +143,7 @@ ifneq ($(BTF_OBJCOPY_PROBE),) endif endif endif +endif # Have one program compiled without "-target bpf" to test whether libbpf loads # it successfully
Signature · 1 line
2.17.1
PATCH v5 11/13 tools/bpf: refactor to implement btf_get_from_id() in lib/bpf
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
The function get_btf() is implemented in tools/bpf/bpftool/map.c to get a btf structure given a map_info. This patch refactored this function to be function btf_get_from_id() in tools/lib/bpf so that it can be used later.
--- tools/bpf/bpftool/map.c | 68 ++-------------------------------------- tools/lib/bpf/btf.c | 69 +++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/btf.h | 1 + 3 files changed, 72 insertions(+), 66 deletions(-)
tools/bpf/bpftool/map.c +2 -66
@@ -215,70 +215,6 @@ static int do_dump_btf(const struct btf_dumper *d,return ret; } -static int get_btf (struct bpf_map_info *map_info,struct btf **btf) -{ -struct bpf_btf_info btf_info = {0 }; -__u32 len =sizeof (btf_info); -__u32 last_size; -int btf_fd; -void *ptr; -int err; - - err =0 ; - *btf =NULL ; - btf_fd =bpf_btf_get_fd_by_id (map_info->btf_id); -if (btf_fd <0 ) -return 0 ; - -/* we won't know btf_size until we call bpf_obj_get_info_by_fd(). so -* let's start with a sane default - 4KiB here - and resize it only if -* bpf_obj_get_info_by_fd() needs a bigger buffer. -*/ - btf_info.btf_size =4096 ; - last_size = btf_info.btf_size; - ptr =malloc (last_size); -if (!ptr) { - err = -ENOMEM ; - goto exit_free; - } - -bzero (ptr, last_size); - btf_info.btf =ptr_to_u64 (ptr); - err =bpf_obj_get_info_by_fd (btf_fd, &btf_info, &len); - -if (!err && btf_info.btf_size > last_size) { -void *temp_ptr; - - last_size = btf_info.btf_size; - temp_ptr =realloc (ptr, last_size); -if (!temp_ptr) { - err = -ENOMEM ; - goto exit_free; - } - ptr = temp_ptr; -bzero (ptr, last_size); - btf_info.btf =ptr_to_u64 (ptr); - err =bpf_obj_get_info_by_fd (btf_fd, &btf_info, &len); - } - -if (err || btf_info.btf_size > last_size) { - err = errno; - goto exit_free; - } - - *btf =btf__new ((__u8 *)btf_info.btf, btf_info.btf_size,NULL ); -if (IS_ERR (*btf)) { - err =PTR_ERR (*btf); - *btf =NULL ; - } - -exit_free: -close (btf_fd); -free (ptr); - -return err; -} -static json_writer_t *get_btf_writer (void ) {json_writer_t *jw =jsonw_new (stdout);
@@ -775,7 +711,7 @@ static int do_dump(int argc, char **argv) prev_key =NULL ; - err =get_btf (&info, &btf); + err =btf_get_from_id (info.btf_id, &btf);if (err) {p_err ("failed to get btf" ); goto exit_free;
@@ -919,7 +855,7 @@ static int do_lookup(int argc, char **argv) }/* here means bpf_map_lookup_elem() succeeded */ - err =get_btf (&info, &btf); + err =btf_get_from_id (info.btf_id, &btf);if (err) {p_err ("failed to get btf" ); goto exit_free;
tools/lib/bpf/btf.c +69 -0
81 lines not on this page · raw message
tools/lib/bpf/btf.h +1 -0
@@ -69,6 +69,7 @@ LIBBPF_API __s64 btf__resolve_size(const struct btf *btf, __u32 type_id); LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id); LIBBPF_API int btf__fd(const struct btf *btf); LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset); +LIBBPF_API int btf_get_from_id(__u32 id, struct btf **btf);struct btf_ext *btf_ext__new (__u8 *data,__u32 size,btf_print_fn_t err_log);void btf_ext__free (struct btf_ext *btf_ext);
Signature · 1 line
2.17.1
PATCH v5 12/13 tools/bpf: enhance test_btf file testing to test func info
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
Change the bpf programs test_btf_haskv.c and test_btf_nokv.c to have two sections, and enhance test_btf.c test_file feature to test btf func_info returned by the kernel.
--- tools/testing/selftests/bpf/test_btf.c | 117 +++++++++++++++++-- tools/testing/selftests/bpf/test_btf_haskv.c | 16 ++- tools/testing/selftests/bpf/test_btf_nokv.c | 16 ++- 3 files changed, 136 insertions(+), 13 deletions(-)
tools/testing/selftests/bpf/test_btf.c +108 -9
@@ -2434,13 +2434,13 @@ static struct btf_file_test file_tests[] = { }, }; -static int file_has_btf_elf (const char *fn) +static int file_has_btf_elf (const char *fn,bool *has_btf_ext) {Elf_Scn *scn =NULL ;GElf_Ehdr ehdr; +int ret =0 ;int elf_fd;Elf *elf; -int ret;if (CHECK (elf_version (EV_CURRENT ) ==EV_NONE ,"elf_version(EV_CURRENT) == EV_NONE" ))
@@ -2472,14 +2472,12 @@ static int file_has_btf_elf(const char *fn) } sh_name =elf_strptr (elf, ehdr.e_shstrndx, sh.sh_name); -if (!strcmp (sh_name,BTF_ELF_SEC )) { +if (!strcmp (sh_name,BTF_ELF_SEC )) ret =1 ; - goto done; - } +if (!strcmp (sh_name,BTF_EXT_ELF_SEC )) + *has_btf_ext = true; } - ret =0 ; - done:close (elf_fd);elf_end (elf);
@@ -2489,15 +2487,24 @@ static int file_has_btf_elf(const char *fn)static int do_test_file (unsigned int test_num) {const struct btf_file_test *test = &file_tests[test_num -1 ]; +const char *expected_fnames[] = {"_dummy_tracepoint" , +"test_long_fname_1" , +"test_long_fname_2" }; +struct bpf_prog_info info = {};struct bpf_object *obj =NULL ; +struct bpf_func_info *finfo;struct bpf_program *prog; +__u32 info_len, rec_size; +bool has_btf_ext = false; +struct btf *btf =NULL ; +void *func_info =NULL ;struct bpf_map *map; -int err; +int i, err, prog_fd;fprintf (stderr,"BTF libbpf test[%u] (%s): " , test_num, test->file); - err =file_has_btf_elf (test->file); + err =file_has_btf_elf (test->file, &has_btf_ext);if (err ==-1 )return err;
@@ -2525,6 +2532,7 @@ static int do_test_file(unsigned int test_num) err =bpf_object__load (obj);if (CHECK (err <0 ,"bpf_object__load: %d" , err)) goto done; + prog_fd =bpf_program__fd (prog); map =bpf_object__find_map_by_name (obj,"btf_map" );if (CHECK (!map,"btf_map not found" )) {
@@ -2539,9 +2547,100 @@ static int do_test_file(unsigned int test_num) test->btf_kv_notfound)) goto done; +if (!jit_enabled || !has_btf_ext) + goto skip_jit; + +/* get necessary program info */ + info_len =sizeof (struct bpf_prog_info ); + err =bpf_obj_get_info_by_fd (prog_fd, &info, &info_len); + +if (CHECK (err ==-1 ,"invalid get info (1st) errno:%d" , errno)) { +fprintf (stderr,"%s\n" , btf_log_buf); + err =-1 ; + goto done; + } +if (CHECK (info.func_info_cnt !=3 , +"incorrect info.func_info_cnt (1st) %d" , + info.func_info_cnt)) { + err =-1 ; + goto done; + } + rec_size = info.func_info_rec_size; +if (CHECK (rec_size <4 , +"incorrect info.func_info_rec_size (1st) %d\n" , rec_size)) { + err =-1 ; + goto done; + } + + func_info =malloc (info.func_info_cnt * rec_size); +if (CHECK (!func_info,"out of memeory" )) { + err =-1 ; + goto done; + } + +/* reset info to only retrieve func_info related data */ +memset (&info,0 ,sizeof (info)); + info.func_info_cnt =3 ; + info.func_info_rec_size = rec_size; + info.func_info =ptr_to_u64 (func_info); + + err =bpf_obj_get_info_by_fd (prog_fd, &info, &info_len); + +if (CHECK (err ==-1 ,"invalid get info (2nd) errno:%d" , errno)) { +fprintf (stderr,"%s\n" , btf_log_buf); + err =-1 ; + goto done; + } +if (CHECK (info.func_info_cnt !=3 , +"incorrect info.func_info_cnt (2nd) %d" , + info.func_info_cnt)) { + err =-1 ; + goto done; + } +if (CHECK (info.func_info_rec_size != rec_size, +"incorrect info.func_info_rec_size (2nd) %d" , + info.func_info_rec_size)) { + err =-1 ; + goto done; + } + + err =btf_get_from_id (info.btf_id, &btf); +if (CHECK (err,"cannot get btf from kernel, err: %d" , err)) + goto done; + +/* check three functions */ + finfo = func_info; +for (i =0 ; i <3 ; i++) { +const struct btf_type *t; +const char *fname; + + t =btf__type_by_id (btf, finfo->type_id); +if (CHECK (!t,"btf__type_by_id failure: id %u" , + finfo->type_id)) { + err =-1 ; + goto done; + } + + fname =btf__name_by_offset (btf, t->name_off); + err =strcmp (fname, expected_fnames[i]); +/* for the second and third functions in .text section, +* the compiler may order them either way. +*/ +if (i && err) + err =strcmp (fname, expected_fnames[3 - i]); +if (CHECK (err,"incorrect fname %s" , fname ? :"" )) { + err =-1 ; + goto done; + } + + finfo = (void *)finfo + rec_size; + } + +skip_jit:fprintf (stderr,"OK" ); done: +free (func_info);bpf_object__close (obj);return err; }
tools/testing/selftests/bpf/test_btf_haskv.c +14 -2
@@ -24,8 +24,8 @@ struct dummy_tracepoint_args {struct sock *sock; }; -SEC("dummy_tracepoint") -int _dummy_tracepoint (struct dummy_tracepoint_args *arg) +__attribute__((noinline)) +static int test_long_fname_2 (struct dummy_tracepoint_args *arg) {struct ipv_counts *counts;int key =0 ;
@@ -42,4 +42,16 @@ int _dummy_tracepoint(struct dummy_tracepoint_args *arg)return 0 ; } +__attribute__((noinline)) +static int test_long_fname_1 (struct dummy_tracepoint_args *arg) +{ +return test_long_fname_2 (arg); +} + +SEC("dummy_tracepoint") +int _dummy_tracepoint (struct dummy_tracepoint_args *arg) +{ +return test_long_fname_1 (arg); +} + char _license[] SEC("license") = "GPL";
tools/testing/selftests/bpf/test_btf_nokv.c +14 -2
@@ -22,8 +22,8 @@ struct dummy_tracepoint_args {struct sock *sock; }; -SEC("dummy_tracepoint") -int _dummy_tracepoint (struct dummy_tracepoint_args *arg) +__attribute__((noinline)) +static int test_long_fname_2 (struct dummy_tracepoint_args *arg) {struct ipv_counts *counts;int key =0 ;
@@ -40,4 +40,16 @@ int _dummy_tracepoint(struct dummy_tracepoint_args *arg)return 0 ; } +__attribute__((noinline)) +static int test_long_fname_1 (struct dummy_tracepoint_args *arg) +{ +return test_long_fname_2 (arg); +} + +SEC("dummy_tracepoint") +int _dummy_tracepoint (struct dummy_tracepoint_args *arg) +{ +return test_long_fname_1 (arg); +} + char _license[] SEC("license") = "GPL";
Signature · 1 line
2.17.1
PATCH v5 13/13 tools/bpf: bpftool: add support for func types
In reply to Martin KaFai LauFrom: Yonghong Song <[email protected]>
This patch added support to print function signature if btf func_info is available. Note that ksym now uses function name instead of prog_name as prog_name has a limit of 16 bytes including ending '\0'.
The following is a sample output for selftests test_btf with file test_btf_haskv.o for translated insns and jited insns respectively.
$ bpftool prog dump xlated id 1
int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
0: (85) call pc+2#bpf_prog_2dcecc18072623fc_test_long_fname_1
1: (b7) r0 = 0
2: (95) exit
int test_long_fname_1(struct dummy_tracepoint_args * arg):
3: (85) call pc+1#bpf_prog_89d64e4abf0f0126_test_long_fname_2
4: (95) exit
int test_long_fname_2(struct dummy_tracepoint_args * arg):
5: (b7) r2 = 0
6: (63) *(u32 *)(r10 -4) = r2
7: (79) r1 = *(u64 *)(r1 +8)
...
22: (07) r1 += 1
23: (63) *(u32 *)(r0 +4) = r1
24: (95) exit $ bpftool prog dump jited id 1
int _dummy_tracepoint(struct dummy_tracepoint_args * arg):
bpf_prog_b07ccb89267cf242__dummy_tracepoint:
0: push %rbp
1: mov %rsp,%rbp
......
3c: add $0x28,%rbp
40: leaveq
41: retq int test_long_fname_1(struct dummy_tracepoint_args * arg):
bpf_prog_2dcecc18072623fc_test_long_fname_1:
0: push %rbp
1: mov %rsp,%rbp
......
3a: add $0x28,%rbp
3e: leaveq
3f: retq int test_long_fname_2(struct dummy_tracepoint_args * arg):
bpf_prog_89d64e4abf0f0126_test_long_fname_2:
0: push %rbp
1: mov %rsp,%rbp
......
80: add $0x28,%rbp
84: leaveq
85: retq--- tools/bpf/bpftool/btf_dumper.c | 136 ++++++++++++++++++++++++++++++ tools/bpf/bpftool/main.h | 2 + tools/bpf/bpftool/prog.c | 56 ++++++++++++ tools/bpf/bpftool/xlated_dumper.c | 33 ++++++++ tools/bpf/bpftool/xlated_dumper.h | 3 + 5 files changed, 230 insertions(+)
tools/bpf/bpftool/btf_dumper.c +136 -0
@@ -249,3 +249,139 @@ int btf_dumper_type(const struct btf_dumper *d, __u32 type_id, {return btf_dumper_do_type (d, type_id,0 , data); } + +#define BTF_PRINT_ARG (...) \ + do { \ + pos += snprintf(func_sig + pos, size - pos, \ + __VA_ARGS__); \ + if (pos >= size) \ + return -1; \ + } while (0) +#define BTF_PRINT_TYPE (type) \ + do { \ + pos = __btf_dumper_type_only(btf, type, func_sig, \ + pos, size); \ + if (pos == -1) \ + return -1; \ + } while (0) + +static int btf_dump_func (const struct btf *btf,char *func_sig, +const struct btf_type *func_proto, +const struct btf_type *func,int pos,int size); + +static int __btf_dumper_type_only (const struct btf *btf,__u32 type_id, +char *func_sig,int pos,int size) +{ +const struct btf_type *proto_type; +const struct btf_array *array; +const struct btf_type *t; + +if (!type_id) { +BTF_PRINT_ARG ("void " ); +return pos; + } + + t =btf__type_by_id (btf, type_id); + +switch (BTF_INFO_KIND (t->info)) { +case BTF_KIND_INT : +BTF_PRINT_ARG ("%s " ,btf__name_by_offset (btf, t->name_off)); +break ; +case BTF_KIND_STRUCT : +BTF_PRINT_ARG ("struct %s " , +btf__name_by_offset (btf, t->name_off)); +break ; +case BTF_KIND_UNION : +BTF_PRINT_ARG ("union %s " , +btf__name_by_offset (btf, t->name_off)); +break ; +case BTF_KIND_ENUM : +BTF_PRINT_ARG ("enum %s " , +btf__name_by_offset (btf, t->name_off)); +break ; +case BTF_KIND_ARRAY : + array = (struct btf_array *)(t +1 ); +BTF_PRINT_TYPE (array->type); +BTF_PRINT_ARG ("[%d]" , array->nelems); +break ; +case BTF_KIND_PTR : +BTF_PRINT_TYPE (t->type); +BTF_PRINT_ARG ("* " ); +break ; +case BTF_KIND_UNKN : +case BTF_KIND_FWD : +case BTF_KIND_TYPEDEF : +return -1 ; +case BTF_KIND_VOLATILE : +BTF_PRINT_ARG ("volatile " ); +BTF_PRINT_TYPE (t->type); +break ; +case BTF_KIND_CONST : +BTF_PRINT_ARG ("const " ); +BTF_PRINT_TYPE (t->type); +break ; +case BTF_KIND_RESTRICT : +BTF_PRINT_ARG ("restrict " ); +BTF_PRINT_TYPE (t->type); +break ; +case BTF_KIND_FUNC_PROTO : + pos =btf_dump_func (btf, func_sig, t,NULL , pos, size); +if (pos ==-1 ) +return -1 ; +break ; +case BTF_KIND_FUNC : + proto_type =btf__type_by_id (btf, t->type); + pos =btf_dump_func (btf, func_sig, proto_type, t, pos, size); +if (pos ==-1 ) +return -1 ; +break ; +default : +return -1 ; + } + +return pos; +} + +static int btf_dump_func (const struct btf *btf,char *func_sig, +const struct btf_type *func_proto, +const struct btf_type *func,int pos,int size) +{ +int i, vlen; + +BTF_PRINT_TYPE (func_proto->type); +if (func) +BTF_PRINT_ARG ("%s(" ,btf__name_by_offset (btf, func->name_off)); +else +BTF_PRINT_ARG ("(" ); + vlen =BTF_INFO_VLEN (func_proto->info); +for (i =0 ; i < vlen; i++) { +struct btf_param *arg = &((struct btf_param *)(func_proto +1 ))[i]; + +if (i) +BTF_PRINT_ARG (", " ); +if (arg->type) { +BTF_PRINT_TYPE (arg->type); +BTF_PRINT_ARG ("%s" , +btf__name_by_offset (btf, arg->name_off)); + }else { +BTF_PRINT_ARG ("..." ); + } + } +BTF_PRINT_ARG (")" ); + +return pos; +} + +void btf_dumper_type_only (const struct btf *btf,__u32 type_id,char *func_sig, +int size) +{ +int err; + + func_sig[0 ] ='\0' ; +if (!btf) +return ; + + err =__btf_dumper_type_only (btf, type_id, func_sig,0 , size); +if (err <0 ) + func_sig[0 ] ='\0' ; +}
tools/bpf/bpftool/main.h +2 -0
@@ -173,6 +173,8 @@ struct btf_dumper {*/ int btf_dumper_type (const struct btf_dumper *d,__u32 type_id,const void *data); +void btf_dumper_type_only (const struct btf *btf,__u32 func_type_id, +char *func_only,int size);struct nlattr ;struct ifinfomsg ;
tools/bpf/bpftool/prog.c +56 -0
136 lines not on this page · raw message
tools/bpf/bpftool/xlated_dumper.c +33 -0
@@ -242,11 +242,15 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, .cb_imm = print_imm, .private_data = dd, }; +struct bpf_func_info *record;struct bpf_insn *insn = buf; +struct btf *btf = dd->btf;bool double_insn = false; +char func_sig[1024 ];unsigned int i;jsonw_start_array (json_wtr); + record = dd->func_info;for (i =0 ; i < len /sizeof (*insn); i++) {if (double_insn) { double_insn = false;
@@ -255,6 +259,20 @@ void dump_xlated_json(struct dump_data *dd, void *buf, unsigned int len, double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );jsonw_start_object (json_wtr); + +if (btf && record) { +if (record->insn_offset == i) { +btf_dumper_type_only (btf, record->type_id, + func_sig, +sizeof (func_sig)); +if (func_sig[0 ] !='\0' ) { +jsonw_name (json_wtr,"proto" ); +jsonw_string (json_wtr, func_sig); + } + record = (void *)record + dd->finfo_rec_size; + } + } +jsonw_name (json_wtr,"disasm" );print_bpf_insn (&cbs, insn + i, true);
@@ -297,16 +315,31 @@ void dump_xlated_plain(struct dump_data *dd, void *buf, unsigned int len, .cb_imm = print_imm, .private_data = dd, }; +struct bpf_func_info *record;struct bpf_insn *insn = buf; +struct btf *btf = dd->btf;bool double_insn = false; +char func_sig[1024 ];unsigned int i; + record = dd->func_info;for (i =0 ; i < len /sizeof (*insn); i++) {if (double_insn) { double_insn = false;continue ; } +if (btf && record) { +if (record->insn_offset == i) { +btf_dumper_type_only (btf, record->type_id, + func_sig, +sizeof (func_sig)); +if (func_sig[0 ] !='\0' ) +printf ("%s:\n" , func_sig); + record = (void *)record + dd->finfo_rec_size; + } + } + double_insn = insn[i].code == (BPF_LD |BPF_IMM |BPF_DW );printf ("% 4d: " , i);
tools/bpf/bpftool/xlated_dumper.h +3 -0
@@ -51,6 +51,9 @@ struct dump_data {__u32 sym_count;__u64 *jited_ksyms;__u32 nr_jited_ksyms; +struct btf *btf; +void *func_info; +__u32 finfo_rec_size;char scratch_buff[SYM_MAX_NAME +8 ]; };
Signature · 1 line
2.17.1
Quoted 6 lines · Martin KaFai Lau
The BTF support was added to kernel by Commit
69b693f0aefa("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced .BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.
Quoted 7 lines
This patch added func info support to the kernel so we can get better ksym's for bpf function calls. Basically, function call types are passed to kernel and the kernel extract function names from these types in order to contruct ksym for these functions.
[...]
Alexei Starovoitov
AppliedQuoted 13 lines · Edward Cree
Quoted 12 lines · Martin KaFai Lau
The BTF support was added to kernel by Commit
69b693f0aefa("bpf: btf: Introduce BPF Type Format (BTF)"), which introduced .BTF section into ELF file and is primarily
used for map pretty print.
pahole is used to convert dwarf to BTF for ELF files.This patch added func info support to the kernel so we can get better ksym's for bpf function calls. Basically, function call types are passed to kernel and the kernel extract function names from these types in order to contruct ksym for these functions.
Quoted 3 lines
Quoted 1 line
[...]
Acked-by Edward Cree <[email protected]>
Applied to bpf-next. Thank you everyone.