Re: [PATCH bpf-next 8/8] bpftool: Display cookie for kprobe multi link

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2024-01-18 09:55 UTC+0000 ~ Jiri Olsa <jolsa@xxxxxxxxxx>
> 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.
> 
> Signed-off-by: Jiri Olsa <jolsa@xxxxxxxxxx>
> ---
>  tools/bpf/bpftool/link.c | 71 ++++++++++++++++++++++++++++++++--------
>  1 file changed, 57 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/bpf/bpftool/link.c b/tools/bpf/bpftool/link.c
> index b66a1598b87c..fd862afe6c6f 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,17 @@ 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);
>  	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 +316,13 @@ 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);
> +	free(data);
>  }
>  
>  static __u64 *u64_to_arr(__u64 val)
> @@ -675,8 +706,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,8 +719,11 @@ 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)
> @@ -697,12 +731,12 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
>  	if (!dd.sym_count)
>  		return;

Don't we need to free(data) if we return here?

>  
> -	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 +745,7 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info)
>  		if (j++ == info->kprobe_multi.count)
>  			break;
>  	}
> +	free(data);
>  }
>  
>  static void show_uprobe_multi_plain(struct bpf_link_info *info)
> @@ -966,6 +1001,14 @@ static int do_show_link(int fd)
>  				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;
>  		}
>  	}





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux