Commit b0dc0373 authored by Jiri Olsa's avatar Jiri Olsa Committed by Alexei Starovoitov

bpftool: Display cookie for kprobe multi link

Displaying cookies for kprobe multi link, in plain mode:

  # bpftool link
  ...
  1397: kprobe_multi  prog 47532
          kretprobe.multi  func_cnt 3
          addr             cookie           func [module]
          ffffffff82b370c0 3                bpf_fentry_test1
          ffffffff82b39780 1                bpf_fentry_test2
          ffffffff82b397a0 2                bpf_fentry_test3

And in json mode:

  # bpftool link -j | jq
  ...
    {
      "id": 1397,
      "type": "kprobe_multi",
      "prog_id": 47532,
      "retprobe": true,
      "func_cnt": 3,
      "missed": 0,
      "funcs": [
        {
          "addr": 18446744071607382208,
          "func": "bpf_fentry_test1",
          "module": null,
          "cookie": 3
        },
        {
          "addr": 18446744071607392128,
          "func": "bpf_fentry_test2",
          "module": null,
          "cookie": 1
        },
        {
          "addr": 18446744071607392160,
          "func": "bpf_fentry_test3",
          "module": null,
          "cookie": 2
        }
      ]
    }

Cookie is attached to specific address, and because we sort addresses
before printing, we need to sort cookies the same way, hence adding
the struct addr_cookie to keep and sort them together.

Also adding missing dd.sym_count check to show_kprobe_multi_json.
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Acked-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20240119110505.400573-9-jolsa@kernel.orgSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 54258324
...@@ -249,18 +249,44 @@ static int get_prog_info(int prog_id, struct bpf_prog_info *info) ...@@ -249,18 +249,44 @@ static int get_prog_info(int prog_id, struct bpf_prog_info *info)
return err; return err;
} }
static int cmp_u64(const void *A, const void *B) struct addr_cookie {
__u64 addr;
__u64 cookie;
};
static int cmp_addr_cookie(const void *A, const void *B)
{
const struct addr_cookie *a = A, *b = B;
if (a->addr == b->addr)
return 0;
return a->addr < b->addr ? -1 : 1;
}
static struct addr_cookie *
get_addr_cookie_array(__u64 *addrs, __u64 *cookies, __u32 count)
{ {
const __u64 *a = A, *b = B; struct addr_cookie *data;
__u32 i;
return *a - *b; data = calloc(count, sizeof(data[0]));
if (!data) {
p_err("mem alloc failed");
return NULL;
}
for (i = 0; i < count; i++) {
data[i].addr = addrs[i];
data[i].cookie = cookies[i];
}
qsort(data, count, sizeof(data[0]), cmp_addr_cookie);
return data;
} }
static void static void
show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr) show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
{ {
struct addr_cookie *data;
__u32 i, j = 0; __u32 i, j = 0;
__u64 *addrs;
jsonw_bool_field(json_wtr, "retprobe", jsonw_bool_field(json_wtr, "retprobe",
info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN); info->kprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN);
...@@ -268,14 +294,20 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr) ...@@ -268,14 +294,20 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
jsonw_uint_field(json_wtr, "missed", info->kprobe_multi.missed); jsonw_uint_field(json_wtr, "missed", info->kprobe_multi.missed);
jsonw_name(json_wtr, "funcs"); jsonw_name(json_wtr, "funcs");
jsonw_start_array(json_wtr); jsonw_start_array(json_wtr);
addrs = u64_to_ptr(info->kprobe_multi.addrs); data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
qsort(addrs, info->kprobe_multi.count, sizeof(addrs[0]), cmp_u64); u64_to_ptr(info->kprobe_multi.cookies),
info->kprobe_multi.count);
if (!data)
return;
/* Load it once for all. */ /* Load it once for all. */
if (!dd.sym_count) if (!dd.sym_count)
kernel_syms_load(&dd); kernel_syms_load(&dd);
if (!dd.sym_count)
goto error;
for (i = 0; i < dd.sym_count; i++) { for (i = 0; i < dd.sym_count; i++) {
if (dd.sym_mapping[i].address != addrs[j]) if (dd.sym_mapping[i].address != data[j].addr)
continue; continue;
jsonw_start_object(json_wtr); jsonw_start_object(json_wtr);
jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address); jsonw_uint_field(json_wtr, "addr", dd.sym_mapping[i].address);
...@@ -287,11 +319,14 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr) ...@@ -287,11 +319,14 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)
} else { } else {
jsonw_string_field(json_wtr, "module", dd.sym_mapping[i].module); jsonw_string_field(json_wtr, "module", dd.sym_mapping[i].module);
} }
jsonw_uint_field(json_wtr, "cookie", data[j].cookie);
jsonw_end_object(json_wtr); jsonw_end_object(json_wtr);
if (j++ == info->kprobe_multi.count) if (j++ == info->kprobe_multi.count)
break; break;
} }
jsonw_end_array(json_wtr); jsonw_end_array(json_wtr);
error:
free(data);
} }
static __u64 *u64_to_arr(__u64 val) static __u64 *u64_to_arr(__u64 val)
...@@ -675,8 +710,8 @@ void netfilter_dump_plain(const struct bpf_link_info *info) ...@@ -675,8 +710,8 @@ void netfilter_dump_plain(const struct bpf_link_info *info)
static void show_kprobe_multi_plain(struct bpf_link_info *info) static void show_kprobe_multi_plain(struct bpf_link_info *info)
{ {
struct addr_cookie *data;
__u32 i, j = 0; __u32 i, j = 0;
__u64 *addrs;
if (!info->kprobe_multi.count) if (!info->kprobe_multi.count)
return; return;
...@@ -688,21 +723,24 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info) ...@@ -688,21 +723,24 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
printf("func_cnt %u ", info->kprobe_multi.count); printf("func_cnt %u ", info->kprobe_multi.count);
if (info->kprobe_multi.missed) if (info->kprobe_multi.missed)
printf("missed %llu ", info->kprobe_multi.missed); printf("missed %llu ", info->kprobe_multi.missed);
addrs = (__u64 *)u64_to_ptr(info->kprobe_multi.addrs); data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs),
qsort(addrs, info->kprobe_multi.count, sizeof(__u64), cmp_u64); u64_to_ptr(info->kprobe_multi.cookies),
info->kprobe_multi.count);
if (!data)
return;
/* Load it once for all. */ /* Load it once for all. */
if (!dd.sym_count) if (!dd.sym_count)
kernel_syms_load(&dd); kernel_syms_load(&dd);
if (!dd.sym_count) if (!dd.sym_count)
return; goto error;
printf("\n\t%-16s %s", "addr", "func [module]"); printf("\n\t%-16s %-16s %s", "addr", "cookie", "func [module]");
for (i = 0; i < dd.sym_count; i++) { for (i = 0; i < dd.sym_count; i++) {
if (dd.sym_mapping[i].address != addrs[j]) if (dd.sym_mapping[i].address != data[j].addr)
continue; continue;
printf("\n\t%016lx %s", printf("\n\t%016lx %-16llx %s",
dd.sym_mapping[i].address, dd.sym_mapping[i].name); dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name);
if (dd.sym_mapping[i].module[0] != '\0') if (dd.sym_mapping[i].module[0] != '\0')
printf(" [%s] ", dd.sym_mapping[i].module); printf(" [%s] ", dd.sym_mapping[i].module);
else else
...@@ -711,6 +749,8 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info) ...@@ -711,6 +749,8 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
if (j++ == info->kprobe_multi.count) if (j++ == info->kprobe_multi.count)
break; break;
} }
error:
free(data);
} }
static void show_uprobe_multi_plain(struct bpf_link_info *info) static void show_uprobe_multi_plain(struct bpf_link_info *info)
...@@ -966,6 +1006,14 @@ static int do_show_link(int fd) ...@@ -966,6 +1006,14 @@ static int do_show_link(int fd)
return -ENOMEM; return -ENOMEM;
} }
info.kprobe_multi.addrs = ptr_to_u64(addrs); info.kprobe_multi.addrs = ptr_to_u64(addrs);
cookies = calloc(count, sizeof(__u64));
if (!cookies) {
p_err("mem alloc failed");
free(addrs);
close(fd);
return -ENOMEM;
}
info.kprobe_multi.cookies = ptr_to_u64(cookies);
goto again; goto again;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment