[PATCH bpf-next 07/13] bpf: Add tracing_multi link info support for bpf progs
Leon Hwang <[email protected]>
| Newsgroups | org.kernel.vger.linux-kselftest,org.kernel.vger.bpf,org.kernel.vger.linux-kernel,org.kernel.vger.linux-trace-kernel |
|---|---|
| Message-ID | <[email protected]> |
Show bpf prog info in the link info. $ bpftool link 9: tracing_multi prog 25 attach_type trace_fsession_multi btf_obj_id 1 count 2 prog_id func_btf_id addr cookie func [module] 21 4 ffffffffc080064c 16706819 target_1 [bpf] 22 5 ffffffffc08006d4 16706819 target_2 [bpf] pids test_progs(98) Signed-off-by: Leon Hwang <[email protected]> --- include/uapi/linux/bpf.h | 4 ++- kernel/trace/bpf_trace.c | 25 ++++++++++---- tools/bpf/bpftool/link.c | 59 +++++++++++++++++++++++++++------- tools/include/uapi/linux/bpf.h | 4 ++- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 6fa93a6ff54f..e0c8ea5ed2c8 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -6890,10 +6890,12 @@ struct bpf_link_info { __u32 attach_type; __u32 count; /* in/out: tracing_multi target count */ __u32 btf_obj_id; - __u32 :32; + __u32 tgt_progs:1; + __u32 :31; __aligned_u64 ids; __aligned_u64 addrs; __aligned_u64 cookies; + __aligned_u64 func_btf_ids; } tracing_multi; struct { __u32 type; /* enum bpf_perf_event_type */ diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 80928401830c..d998e7ea563d 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -3707,15 +3707,16 @@ static void bpf_tracing_multi_link_dealloc(struct bpf_link *link) static int bpf_tracing_multi_link_fill_link_info(const struct bpf_link *link, struct bpf_link_info *info) { + u32 __user *fids = u64_to_user_ptr(info->tracing_multi.func_btf_ids); u64 __user *ucookies = u64_to_user_ptr(info->tracing_multi.cookies); u64 __user *uaddrs = u64_to_user_ptr(info->tracing_multi.addrs); u32 __user *uids = u64_to_user_ptr(info->tracing_multi.ids); struct bpf_tracing_multi_link *tr_link; u32 ucount = info->tracing_multi.count; - bool has_cookies, show_addrs; + bool has_cookies, show_addrs, has_progs; int err = 0; - if ((uids || ucookies || uaddrs) && !ucount) + if ((uids || ucookies || uaddrs || fids) && !ucount) return -EINVAL; tr_link = container_of(link, struct bpf_tracing_multi_link, link); @@ -3723,9 +3724,12 @@ static int bpf_tracing_multi_link_fill_link_info(const struct bpf_link *link, info->tracing_multi.attach_type = tr_link->link.attach_type; info->tracing_multi.count = tr_link->nodes_cnt; info->tracing_multi.btf_obj_id = btf_obj_id(tr_link->link.prog->aux->attach_btf); + info->tracing_multi.tgt_progs = has_progs = !!tr_link->progs; - if (!uids && !ucookies && !uaddrs) + if (!uids && !ucookies && !uaddrs && !fids) return 0; + if (has_progs != !!fids) + return -EINVAL; if (ucount < tr_link->nodes_cnt) err = -ENOSPC; @@ -3737,20 +3741,27 @@ static int bpf_tracing_multi_link_fill_link_info(const struct bpf_link *link, for (int i = 0; i < ucount; i++) { struct bpf_tracing_multi_node *mnode = &tr_link->nodes[i]; + u32 prog_id, btf_id; u64 addr, cookie; - u32 id; - bpf_trampoline_unpack_key(mnode->trampoline->key, NULL, &id); + bpf_trampoline_unpack_key(mnode->trampoline->key, &prog_id, &btf_id); - addr = show_addrs ? mnode->trampoline->ip : 0; + if (!show_addrs) + addr = 0; + else if (has_progs) + addr = (u64) mnode->trampoline->func.addr; + else + addr = mnode->trampoline->ip; cookie = has_cookies ? tr_link->cookies[i] : 0; - if (uids && put_user(id, uids + i)) + if (uids && put_user(has_progs ? prog_id : btf_id, uids + i)) return -EFAULT; if (uaddrs && put_user(addr, uaddrs + i)) return -EFAULT; if (ucookies && put_user(cookie, ucookies + i)) return -EFAULT; + if (has_progs && put_user((u32) mnode->trampoline->key, fids + i)) + return -EFAULT; cond_resched(); } diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c index 088d1d206065..d5c5ec433350 100644 --- a/tools/bpf/bpftool/link.c +++ b/tools/bpf/bpftool/link.c @@ -422,12 +422,30 @@ show_uprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr) jsonw_end_array(json_wtr); } +#define BPF_PROG_PREFIX "bpf_prog_" +#define BPF_PROG_PREFIX_LEN (sizeof(BPF_PROG_PREFIX) - 1) + +static const char * +sym_name_trim_prefix(struct kernel_sym *sym, bool is_prog) +{ + int prefix_len; + + if (!is_prog) + return sym->name; + + /* Ref kernel/bpf/core.c::bpf_prog_ksym_set_name() */ + prefix_len = BPF_PROG_PREFIX_LEN; + prefix_len += BPF_TAG_SIZE * 2; + prefix_len += 1; /* skip the '_' */ + return sym->name + prefix_len; +} + static void show_tracing_multi_json(struct bpf_link_info *info, json_writer_t *wtr) { - bool is_ibt_enabled = is_x86_ibt_enabled(), show_symbol; + bool is_ibt_enabled = is_x86_ibt_enabled(), show_symbol, tgt_progs; __u64 *addrs, *cookies; - __u32 i, *ids; + __u32 i, *ids, *fids; if (!dd.sym_count) kernel_syms_load(&dd); @@ -443,6 +461,8 @@ show_tracing_multi_json(struct bpf_link_info *info, json_writer_t *wtr) ids = u64_to_u32_arr(info->tracing_multi.ids); addrs = u64_to_arr(info->tracing_multi.addrs); cookies = u64_to_arr(info->tracing_multi.cookies); + fids = u64_to_u32_arr(info->tracing_multi.func_btf_ids); + tgt_progs = info->tracing_multi.tgt_progs; for (i = 0; i < info->tracing_multi.count; i++) { struct kernel_sym *sym; @@ -451,10 +471,12 @@ show_tracing_multi_json(struct bpf_link_info *info, json_writer_t *wtr) sym = show_symbol ? find_kernel_sym_by_addr(addr, is_ibt_enabled) : NULL; jsonw_start_object(wtr); - jsonw_uint_field(wtr, "id", ids[i]); + jsonw_uint_field(wtr, tgt_progs ? "prog_id" : "id", ids[i]); + if (tgt_progs) + jsonw_uint_field(wtr, "func_btf_id", fids[i]); jsonw_uint_field(wtr, "addr", addr); if (sym) { - jsonw_string_field(wtr, "func", sym->name); + jsonw_string_field(wtr, "func", sym_name_trim_prefix(sym, tgt_progs)); if (sym->module[0] == '\0') { jsonw_name(wtr, "module"); jsonw_null(wtr); @@ -903,9 +925,9 @@ static void show_uprobe_multi_plain(struct bpf_link_info *info) static void show_tracing_multi_plain(struct bpf_link_info *info) { - bool is_ibt_enabled = is_x86_ibt_enabled(), show_symbol; + bool is_ibt_enabled = is_x86_ibt_enabled(), show_symbol, tgt_progs; __u64 *addrs, *cookies; - __u32 i, *ids; + __u32 i, *ids, *fids; if (!info->tracing_multi.count) return; @@ -919,12 +941,18 @@ static void show_tracing_multi_plain(struct bpf_link_info *info) printf("btf_obj_id %u ", info->tracing_multi.btf_obj_id); printf("count %u ", info->tracing_multi.count); - printf("\n\t%-16s %-16s %-16s %s", - "btf_id", "addr", "cookie", "func [module]"); + tgt_progs = info->tracing_multi.tgt_progs; + if (tgt_progs) + printf("\n\t%-16s %-16s %-16s %-16s %s", + "prog_id", "func_btf_id", "addr", "cookie", "func [module]"); + else + printf("\n\t%-16s %-16s %-16s %s", + "btf_id", "addr", "cookie", "func [module]"); ids = u64_to_u32_arr(info->tracing_multi.ids); addrs = u64_to_arr(info->tracing_multi.addrs); cookies = u64_to_arr(info->tracing_multi.cookies); + fids = u64_to_u32_arr(info->tracing_multi.func_btf_ids); for (i = 0; i < info->tracing_multi.count; i++) { __u64 addr = addrs[i]; @@ -932,9 +960,12 @@ static void show_tracing_multi_plain(struct bpf_link_info *info) sym = show_symbol ? find_kernel_sym_by_addr(addr, is_ibt_enabled) : NULL; - printf("\n\t%-16u %016llx %-16llu", ids[i], addr, cookies[i]); + if (tgt_progs) + printf("\n\t%-16u %-16u %016llx %-16llu", ids[i], fids[i], addr, cookies[i]); + else + printf("\n\t%-16u %016llx %-16llu", ids[i], addr, cookies[i]); if (sym) { - printf(" %s", sym->name); + printf(" %s", sym_name_trim_prefix(sym, tgt_progs)); if (sym->module[0] != '\0') printf(" [%s]", sym->module); } @@ -1140,7 +1171,7 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info) static int do_show_link(int fd) { __u64 *ref_ctr_offsets = NULL, *offsets = NULL, *cookies = NULL; - __u32 *ids = NULL; + __u32 *ids = NULL, *func_btf_ids = NULL; struct bpf_link_info info; __u32 len = sizeof(info); char path_buf[PATH_MAX]; @@ -1232,9 +1263,11 @@ static int do_show_link(int fd) ids = calloc(count, sizeof(__u32)); addrs = calloc(count, sizeof(__u64)); cookies = calloc(count, sizeof(__u64)); - if (!ids || !addrs || !cookies) { + func_btf_ids = info.tracing_multi.tgt_progs ? calloc(count, sizeof(__u32)) : NULL; + if (!ids || !addrs || !cookies || (info.tracing_multi.tgt_progs && !func_btf_ids)) { p_err("mem alloc failed"); close(fd); + free(func_btf_ids); free(cookies); free(addrs); free(ids); @@ -1243,6 +1276,7 @@ static int do_show_link(int fd) info.tracing_multi.ids = ptr_to_u64(ids); info.tracing_multi.addrs = ptr_to_u64(addrs); info.tracing_multi.cookies = ptr_to_u64(cookies); + info.tracing_multi.func_btf_ids = ptr_to_u64(func_btf_ids); goto again; } } @@ -1282,6 +1316,7 @@ static int do_show_link(int fd) show_link_close_plain(fd, &info); free(ref_ctr_offsets); + free(func_btf_ids); free(cookies); free(offsets); free(addrs); diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 6fa93a6ff54f..e0c8ea5ed2c8 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -6890,10 +6890,12 @@ struct bpf_link_info { __u32 attach_type; __u32 count; /* in/out: tracing_multi target count */ __u32 btf_obj_id; - __u32 :32; + __u32 tgt_progs:1; + __u32 :31; __aligned_u64 ids; __aligned_u64 addrs; __aligned_u64 cookies; + __aligned_u64 func_btf_ids; } tracing_multi; struct { __u32 type; /* enum bpf_perf_event_type */ -- 2.55.0