Try to get the real kernel func addr from available_filter_functions_addr, in case of the function name is optimized by the compiler and a suffix such as ".isra.0" is added, which will be used in the next patch. Signed-off-by: Tao Chen <chen.dylane@xxxxxxxxx> --- tools/include/uapi/linux/bpf.h | 1 + tools/lib/bpf/bpf.c | 1 + tools/lib/bpf/bpf.h | 1 + tools/lib/bpf/gen_loader.c | 1 + tools/lib/bpf/libbpf.c | 53 ++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 07ee73cdf9..7016e47a70 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -1577,6 +1577,7 @@ union bpf_attr { * If provided, prog_flags should have BPF_F_TOKEN_FD flag set. */ __s32 prog_token_fd; + __aligned_u64 fentry_func; /* The fd_array_cnt can be used to pass the length of the * fd_array array. In this case all the [map] file descriptors * passed in this array will be bound to the program, even if diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index a9c3e33d0f..639a6b54e8 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -312,6 +312,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type, attr.fd_array = ptr_to_u64(OPTS_GET(opts, fd_array, NULL)); attr.fd_array_cnt = OPTS_GET(opts, fd_array_cnt, 0); + attr.fentry_func = OPTS_GET(opts, fentry_func, 0); if (log_level) { attr.log_buf = ptr_to_u64(log_buf); diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 777627d33d..b3340bcf7b 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -83,6 +83,7 @@ struct bpf_prog_load_opts { __u32 attach_btf_id; __u32 attach_prog_fd; __u32 attach_btf_obj_fd; + __u64 fentry_func; const int *fd_array; diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c index 113ae4abd3..d90874b746 100644 --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -1023,6 +1023,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen, attr.kern_version = 0; attr.insn_cnt = tgt_endian((__u32)insn_cnt); attr.prog_flags = tgt_endian(load_attr->prog_flags); + attr.fentry_func = tgt_endian(load_attr->fentry_func); attr.func_info_rec_size = tgt_endian(load_attr->func_info_rec_size); attr.func_info_cnt = tgt_endian(load_attr->func_info_cnt); diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 37d563e140..624e75cf2f 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -7456,6 +7456,50 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog, } static void fixup_verifier_log(struct bpf_program *prog, char *buf, size_t buf_sz); +static const char *tracefs_available_filter_functions_addrs(void); + +static void try_get_fentry_func_addr(const char *func_name, struct bpf_prog_load_opts *load_attr) +{ + const char *available_functions_file = tracefs_available_filter_functions_addrs(); + char sym_name[500]; + FILE *f; + char *suffix; + int ret; + unsigned long long sym_addr; + + f = fopen(available_functions_file, "re"); + if (!f) { + pr_warn("failed to open %s: %s\n", available_functions_file, errstr(errno)); + return; + } + + while (true) { + ret = fscanf(f, "%llx %499s%*[^\n]\n", &sym_addr, sym_name); + if (ret == EOF && feof(f)) + break; + + if (ret != 2) { + pr_warn("failed to parse available_filter_functions_addrs entry: %d\n", + ret); + goto cleanup; + } + + if (strcmp(func_name, sym_name) == 0) { + load_attr->fentry_func = sym_addr; + break; + } + /* find [func_name] optimized by compiler like [func_name].isra.0 */ + suffix = strstr(sym_name, "."); + if (suffix && strncmp(sym_name, func_name, + strlen(sym_name) - strlen(suffix)) == 0) { + load_attr->fentry_func = sym_addr; + break; + } + } + +cleanup: + fclose(f); +} static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, @@ -7504,6 +7548,15 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog load_attr.prog_ifindex = prog->prog_ifindex; load_attr.expected_attach_type = prog->expected_attach_type; + if (load_attr.expected_attach_type == BPF_TRACE_FENTRY || + load_attr.expected_attach_type == BPF_TRACE_FEXIT) { + const char *func_name; + + func_name = strchr(prog->sec_name, '/'); + if (func_name) + try_get_fentry_func_addr(++func_name, &load_attr); + } + /* specify func_info/line_info only if kernel supports them */ if (obj->btf && btf__fd(obj->btf) >= 0 && kernel_supports(obj, FEAT_BTF_FUNC)) { load_attr.prog_btf_fd = btf__fd(obj->btf); -- 2.43.0