From: Jiri Olsa <olsajiri@gmail.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
bpf@vger.kernel.org, Martin KaFai Lau <martin.lau@linux.dev>,
Eduard Zingerman <eddyz87@gmail.com>,
Song Liu <songliubraving@fb.com>, Yonghong Song <yhs@fb.com>,
Quentin Monnet <qmo@kernel.org>
Subject: Re: [PATCHv2 bpf-next 3/3] bpftool: Add tracing_multi link info output
Date: Wed, 24 Jun 2026 13:32:01 +0200 [thread overview]
Message-ID: <ajvAMSeIxsHGBXOw@krava> (raw)
In-Reply-To: <CAEf4BzaCnTNo5dmYGRVWGWn+tUCP279Owbg54MuVqQrZTx=rQQ@mail.gmail.com>
On Tue, Jun 23, 2026 at 02:11:34PM -0700, Andrii Nakryiko wrote:
> On Tue, Jun 23, 2026 at 7:24 AM Jiri Olsa <jolsa@kernel.org> wrote:
> >
> > Adding bpftool support to show tracing_multi link details,
> > the new output looks like:
> >
> > # bpftool link
> > ...
> > 27: tracing_multi prog 93
> > attach_type trace_fentry_multi obj_id 1 count 3
> > btf_id addr cookie func [module]
> > 91984 ffffffff824f4a24 a bpf_fentry_test1
> > 91986 ffffffff824f6a84 1e bpf_fentry_test2
> > 91987 ffffffff824f6a94 14 bpf_fentry_test3
> > pids test_progs(1462)
> >
> > Assisted-by: Codex:GPT-5
> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> > ---
> > tools/bpf/bpftool/link.c | 137 +++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 137 insertions(+)
> >
> > diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
> > index bdcd717b0348..db780ee39820 100644
> > --- a/tools/bpf/bpftool/link.c
> > +++ b/tools/bpf/bpftool/link.c
> > @@ -377,6 +377,25 @@ static __u64 *u64_to_arr(__u64 val)
> > return (__u64 *) u64_to_ptr(val);
> > }
> >
> > +static __u32 *u64_to_u32_arr(__u64 val)
> > +{
> > + return (__u32 *)u64_to_ptr(val);
> > +}
> > +
> > +static struct kernel_sym *find_kernel_sym_by_addr(__u64 addr, bool is_ibt_enabled)
> > +{
> > + struct kernel_sym *sym;
> > +
> > + if (!addr)
> > + return NULL;
> > +
> > + sym = kernel_syms_search(&dd, addr);
> > + if (!sym && is_ibt_enabled && addr >= 4)
> > + sym = kernel_syms_search(&dd, addr - 4);
>
> if is_ibt_enabled, can we match addr with kernel_syms_search at all?
> I.e., can addr sometimes be resolvable without - 4 adjustment? If not,
> why is this not if/else and instead "try this, if not, try that"?
I followed the symbol_matches_target logic and assumed we could have functions
with and without endbr instruction at the entry.. but I can't find any example
of such traceable function
>
> > +
> > + return sym;
> > +}
> > +
> > static void
> > show_uprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
> > {
> > @@ -403,6 +422,47 @@ show_uprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
> > jsonw_end_array(json_wtr);
> > }
> >
> > +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;
> > + __u32 i;
> > +
> > + if (!dd.sym_count)
> > + kernel_syms_load(&dd);
> > + show_symbol = !!dd.sym_count;
> > +
> > + show_link_attach_type_json(info->tracing_multi.attach_type, wtr);
> > + jsonw_uint_field(wtr, "func_cnt", info->tracing_multi.count);
> > + jsonw_uint_field(wtr, "obj_id", info->tracing_multi.obj_id);
> > + jsonw_name(wtr, "funcs");
> > +
> > + jsonw_start_array(wtr);
> > +
> > + for (i = 0; i < info->tracing_multi.count; i++) {
> > + __u64 addr = u64_to_arr(info->tracing_multi.addrs)[i];
> > + struct kernel_sym *sym;
> > +
> > + sym = show_symbol ? find_kernel_sym_by_addr(addr, is_ibt_enabled) : NULL;
> > +
> > + jsonw_start_object(wtr);
> > + jsonw_uint_field(wtr, "id", u64_to_u32_arr(info->tracing_multi.ids)[i]);
>
> nit, here and for cookies, do the cast outside of the loop into local
> variable? seems cleaner as an approach
ok
>
> > + jsonw_uint_field(wtr, "addr", addr);
> > + if (sym) {
> > + jsonw_string_field(wtr, "func", sym->name);
> > + if (sym->module[0] == '\0') {
> > + jsonw_name(wtr, "module");
> > + jsonw_null(wtr);
>
> just curious, is it cleaner to have "module: null" instead of just not
> emitting "module:" field at all?
I followed what we do for kprobe_multi, not sure what's preffered,
but I think it's better to be consistent.. at least somewhere ;-)
>
> > + } else {
> > + jsonw_string_field(wtr, "module", sym->module);
> > + }
> > + }
> > + jsonw_uint_field(wtr, "cookie", u64_to_arr(info->tracing_multi.cookies)[i]);
> > + jsonw_end_object(wtr);
> > + }
> > + jsonw_end_array(wtr);
> > +}
> > +
> > static void
> > show_perf_event_kprobe_json(struct bpf_link_info *info, json_writer_t *wtr)
> > {
> > @@ -589,6 +649,9 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)
> > case BPF_LINK_TYPE_UPROBE_MULTI:
> > show_uprobe_multi_json(info, json_wtr);
> > break;
> > + case BPF_LINK_TYPE_TRACING_MULTI:
> > + show_tracing_multi_json(info, json_wtr);
> > + break;
> > case BPF_LINK_TYPE_PERF_EVENT:
> > switch (info->perf_event.type) {
> > case BPF_PERF_EVENT_EVENT:
> > @@ -833,6 +896,42 @@ 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;
> > + __u32 i;
> > +
> > + if (!info->tracing_multi.count)
> > + return;
> > +
> > + if (!dd.sym_count)
> > + kernel_syms_load(&dd);
> > + show_symbol = !!dd.sym_count;
> > +
> > + printf("\n\t");
> > + show_link_attach_type_plain(info->tracing_multi.attach_type);
> > + printf("obj_id %u ", info->tracing_multi.obj_id);
> > + printf("count %u ", info->tracing_multi.count);
> > +
> > + printf("\n\t%-16s %-16s %-16s %s",
> > + "btf_id", "addr", "cookie", "func [module]");
> > + for (i = 0; i < info->tracing_multi.count; i++) {
> > + __u64 addr = u64_to_arr(info->tracing_multi.addrs)[i];
> > + struct kernel_sym *sym;
> > +
> > + sym = show_symbol ? find_kernel_sym_by_addr(addr, is_ibt_enabled) : NULL;
> > +
> > + printf("\n\t%-16u %016llx %-16llx",
> > + u64_to_u32_arr(info->tracing_multi.ids)[i],
> > + addr, u64_to_arr(info->tracing_multi.cookies)[i]);
>
> As I mentioned, it surprised me that we emit cookie as hex. Kernel
> doesn't in fdinfo output. And at least in my experience cookie is some
> small compact index into some additional lookup array, so decimal
> makes most sense. I see now that we have hex for uprobe_multi, but
> decimal for perf link, so ugh, goodbye consistency. But still, decimal
> will be much more useful in practice, IMO.
agreed
>
> > + if (sym) {
> > + printf(" %s", sym->name);
> > + if (sym->module[0] != '\0')
> > + printf(" [%s]", sym->module);
> > + }
> > + }
> > +}
> > +
> > static void show_perf_event_kprobe_plain(struct bpf_link_info *info)
> > {
> > const char *buf;
> > @@ -989,6 +1088,9 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)
> > case BPF_LINK_TYPE_UPROBE_MULTI:
> > show_uprobe_multi_plain(info);
> > break;
> > + case BPF_LINK_TYPE_TRACING_MULTI:
> > + show_tracing_multi_plain(info);
> > + break;
> > case BPF_LINK_TYPE_PERF_EVENT:
> > switch (info->perf_event.type) {
> > case BPF_PERF_EVENT_EVENT:
> > @@ -1029,6 +1131,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;
> > struct bpf_link_info info;
> > __u32 len = sizeof(info);
> > char path_buf[PATH_MAX];
> > @@ -1114,6 +1217,39 @@ static int do_show_link(int fd)
> > goto again;
> > }
> > }
> > + if (info.type == BPF_LINK_TYPE_TRACING_MULTI &&
> > + !info.tracing_multi.ids) {
>
> why wrap?
I followed the previous code style
>
> > + count = info.tracing_multi.count;
> > + if (count) {
> > + ids = calloc(count, sizeof(__u32));
> > + if (!ids) {
> > + p_err("mem alloc failed");
> > + close(fd);
> > + return -ENOMEM;
> > + }
> > + info.tracing_multi.ids = ptr_to_u64(ids);
> > +
> > + addrs = calloc(count, sizeof(__u64));
> > + if (!addrs) {
> > + p_err("mem alloc failed");
> > + free(ids);
> > + close(fd);
> > + return -ENOMEM;
> > + }
> > + info.tracing_multi.addrs = ptr_to_u64(addrs);
> > +
> > + cookies = calloc(count, sizeof(__u64));
> > + if (!cookies) {
> > + p_err("mem alloc failed");
> > + free(addrs);
> > + free(ids);
> > + close(fd);
> > + return -ENOMEM;
> > + }
>
> ugh... do three calloc()s in a row, check that all succeeded, if not -
> free and close(fd)? shorter and just as good
ah right.. I guess I followed the previous kprobe/uprobe code style,
but as you said, we can simplify the error path, will change
thanks,
jirka
next prev parent reply other threads:[~2026-06-24 11:32 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-23 14:24 [PATCHv2 bpf-next 0/3] bpf: tracing_multi link info support Jiri Olsa
2026-06-23 14:24 ` [PATCHv2 bpf-next 1/3] bpf: Add " Jiri Olsa
2026-06-23 15:32 ` Leon Hwang
2026-06-23 21:01 ` Andrii Nakryiko
2026-06-24 9:36 ` Jiri Olsa
2026-06-23 14:24 ` [PATCHv2 bpf-next 2/3] selftests/bpf: Add tracing_multi link info tests Jiri Olsa
2026-06-23 14:39 ` sashiko-bot
2026-06-23 14:24 ` [PATCHv2 bpf-next 3/3] bpftool: Add tracing_multi link info output Jiri Olsa
2026-06-23 14:38 ` sashiko-bot
2026-06-23 21:11 ` Andrii Nakryiko
2026-06-24 11:32 ` Jiri Olsa [this message]
2026-06-23 20:51 ` [PATCHv2 bpf-next 0/3] bpf: tracing_multi link info support Andrii Nakryiko
2026-06-24 9:29 ` Jiri Olsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ajvAMSeIxsHGBXOw@krava \
--to=olsajiri@gmail.com \
--cc=andrii.nakryiko@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=martin.lau@linux.dev \
--cc=qmo@kernel.org \
--cc=songliubraving@fb.com \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.