From 2adb2e0fcdf3c6d8e28a5a9c33e458e1037ae5ad Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 19 Jan 2024 12:05:00 +0100 Subject: bpftool: Fix wrong free call in do_show_link The error path frees wrong array, it should be ref_ctr_offsets. Acked-by: Yafang Shao Reviewed-by: Quentin Monnet Fixes: a7795698f8b6 ("bpftool: Add support to display uprobe_multi links") Signed-off-by: Jiri Olsa Acked-by: Song Liu Link: https://lore.kernel.org/r/20240119110505.400573-4-jolsa@kernel.org Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/bpf/bpftool/link.c') diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c index cb46667a6b2e..35b6859dd7c3 100644 --- a/tools/bpf/bpftool/link.c +++ b/tools/bpf/bpftool/link.c @@ -977,7 +977,7 @@ again: cookies = calloc(count, sizeof(__u64)); if (!cookies) { p_err("mem alloc failed"); - free(cookies); + free(ref_ctr_offsets); free(offsets); close(fd); return -ENOMEM; -- cgit v1.2.3 From 54258324b934aa8552c239c443272ec7aea55285 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 19 Jan 2024 12:05:04 +0100 Subject: bpftool: Display cookie for perf event link probes Displaying cookie for perf event link probes, in plain mode: # bpftool link 17: perf_event prog 90 kprobe ffffffff82b1c2b0 bpf_fentry_test1 cookie 3735928559 18: perf_event prog 90 kretprobe ffffffff82b1c2b0 bpf_fentry_test1 cookie 3735928559 20: perf_event prog 92 tracepoint sched_switch cookie 3735928559 21: perf_event prog 93 event software:page-faults cookie 3735928559 22: perf_event prog 91 uprobe /proc/self/exe+0xd703c cookie 3735928559 And in json mode: # bpftool link -j | jq { "id": 30, "type": "perf_event", "prog_id": 160, "retprobe": false, "addr": 18446744071607272112, "func": "bpf_fentry_test1", "offset": 0, "missed": 0, "cookie": 3735928559 } { "id": 33, "type": "perf_event", "prog_id": 162, "tracepoint": "sched_switch", "cookie": 3735928559 } { "id": 34, "type": "perf_event", "prog_id": 163, "event_type": "software", "event_config": "page-faults", "cookie": 3735928559 } { "id": 35, "type": "perf_event", "prog_id": 161, "retprobe": false, "file": "/proc/self/exe", "offset": 880700, "cookie": 3735928559 } Reviewed-by: Quentin Monnet Signed-off-by: Jiri Olsa Acked-by: Song Liu Link: https://lore.kernel.org/r/20240119110505.400573-8-jolsa@kernel.org Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/link.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'tools/bpf/bpftool/link.c') diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c index 35b6859dd7c3..b66a1598b87c 100644 --- a/tools/bpf/bpftool/link.c +++ b/tools/bpf/bpftool/link.c @@ -334,6 +334,7 @@ show_perf_event_kprobe_json(struct bpf_link_info *info, json_writer_t *wtr) u64_to_ptr(info->perf_event.kprobe.func_name)); jsonw_uint_field(wtr, "offset", info->perf_event.kprobe.offset); jsonw_uint_field(wtr, "missed", info->perf_event.kprobe.missed); + jsonw_uint_field(wtr, "cookie", info->perf_event.kprobe.cookie); } static void @@ -343,6 +344,7 @@ show_perf_event_uprobe_json(struct bpf_link_info *info, json_writer_t *wtr) jsonw_string_field(wtr, "file", u64_to_ptr(info->perf_event.uprobe.file_name)); jsonw_uint_field(wtr, "offset", info->perf_event.uprobe.offset); + jsonw_uint_field(wtr, "cookie", info->perf_event.uprobe.cookie); } static void @@ -350,6 +352,7 @@ show_perf_event_tracepoint_json(struct bpf_link_info *info, json_writer_t *wtr) { jsonw_string_field(wtr, "tracepoint", u64_to_ptr(info->perf_event.tracepoint.tp_name)); + jsonw_uint_field(wtr, "cookie", info->perf_event.tracepoint.cookie); } static char *perf_config_hw_cache_str(__u64 config) @@ -426,6 +429,8 @@ show_perf_event_event_json(struct bpf_link_info *info, json_writer_t *wtr) else jsonw_uint_field(wtr, "event_config", config); + jsonw_uint_field(wtr, "cookie", info->perf_event.event.cookie); + if (type == PERF_TYPE_HW_CACHE && perf_config) free((void *)perf_config); } @@ -754,6 +759,8 @@ static void show_perf_event_kprobe_plain(struct bpf_link_info *info) printf("+%#x", info->perf_event.kprobe.offset); if (info->perf_event.kprobe.missed) printf(" missed %llu", info->perf_event.kprobe.missed); + if (info->perf_event.kprobe.cookie) + printf(" cookie %llu", info->perf_event.kprobe.cookie); printf(" "); } @@ -770,6 +777,8 @@ static void show_perf_event_uprobe_plain(struct bpf_link_info *info) else printf("\n\tuprobe "); printf("%s+%#x ", buf, info->perf_event.uprobe.offset); + if (info->perf_event.uprobe.cookie) + printf("cookie %llu ", info->perf_event.uprobe.cookie); } static void show_perf_event_tracepoint_plain(struct bpf_link_info *info) @@ -781,6 +790,8 @@ static void show_perf_event_tracepoint_plain(struct bpf_link_info *info) return; printf("\n\ttracepoint %s ", buf); + if (info->perf_event.tracepoint.cookie) + printf("cookie %llu ", info->perf_event.tracepoint.cookie); } static void show_perf_event_event_plain(struct bpf_link_info *info) @@ -802,6 +813,9 @@ static void show_perf_event_event_plain(struct bpf_link_info *info) else printf("%llu ", config); + if (info->perf_event.event.cookie) + printf("cookie %llu ", info->perf_event.event.cookie); + if (type == PERF_TYPE_HW_CACHE && perf_config) free((void *)perf_config); } -- cgit v1.2.3 From b0dc037399b19a777d569dbd9e2e9bbd62f3b3b1 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 19 Jan 2024 12:05:05 +0100 Subject: 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: Jiri Olsa Acked-by: Song Liu Link: https://lore.kernel.org/r/20240119110505.400573-9-jolsa@kernel.org Signed-off-by: Alexei Starovoitov --- tools/bpf/bpftool/link.c | 78 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 15 deletions(-) (limited to 'tools/bpf/bpftool/link.c') diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c index b66a1598b87c..afde9d0c2ea1 100644 --- a/tools/bpf/bpftool/link.c +++ b/tools/bpf/bpftool/link.c @@ -249,18 +249,44 @@ static int get_prog_info(int prog_id, struct bpf_prog_info *info) 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 show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr) { + struct addr_cookie *data; __u32 i, j = 0; - __u64 *addrs; jsonw_bool_field(json_wtr, "retprobe", 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) jsonw_uint_field(json_wtr, "missed", info->kprobe_multi.missed); jsonw_name(json_wtr, "funcs"); jsonw_start_array(json_wtr); - addrs = u64_to_ptr(info->kprobe_multi.addrs); - qsort(addrs, info->kprobe_multi.count, sizeof(addrs[0]), cmp_u64); + data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs), + u64_to_ptr(info->kprobe_multi.cookies), + info->kprobe_multi.count); + if (!data) + return; /* Load it once for all. */ if (!dd.sym_count) kernel_syms_load(&dd); + if (!dd.sym_count) + goto error; + 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; jsonw_start_object(json_wtr); 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) } else { 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); if (j++ == info->kprobe_multi.count) break; } jsonw_end_array(json_wtr); +error: + free(data); } static __u64 *u64_to_arr(__u64 val) @@ -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) { + struct addr_cookie *data; __u32 i, j = 0; - __u64 *addrs; if (!info->kprobe_multi.count) return; @@ -688,21 +723,24 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info) printf("func_cnt %u ", info->kprobe_multi.count); if (info->kprobe_multi.missed) printf("missed %llu ", info->kprobe_multi.missed); - addrs = (__u64 *)u64_to_ptr(info->kprobe_multi.addrs); - qsort(addrs, info->kprobe_multi.count, sizeof(__u64), cmp_u64); + data = get_addr_cookie_array(u64_to_ptr(info->kprobe_multi.addrs), + u64_to_ptr(info->kprobe_multi.cookies), + info->kprobe_multi.count); + if (!data) + return; /* Load it once for all. */ if (!dd.sym_count) kernel_syms_load(&dd); 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++) { - if (dd.sym_mapping[i].address != addrs[j]) + if (dd.sym_mapping[i].address != data[j].addr) continue; - printf("\n\t%016lx %s", - dd.sym_mapping[i].address, dd.sym_mapping[i].name); + printf("\n\t%016lx %-16llx %s", + dd.sym_mapping[i].address, data[j].cookie, dd.sym_mapping[i].name); if (dd.sym_mapping[i].module[0] != '\0') printf(" [%s] ", dd.sym_mapping[i].module); else @@ -711,6 +749,8 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info) if (j++ == info->kprobe_multi.count) break; } +error: + free(data); } static void show_uprobe_multi_plain(struct bpf_link_info *info) @@ -966,6 +1006,14 @@ again: return -ENOMEM; } 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; } } -- cgit v1.2.3