bpf: Add link_info support for uprobe multi link
Subsystems (8)
Jiri Olsa
reviewerv4 cover bpf: Add link_info support for uprobe multi link
hi,
this patchset adds support to get bpf_link_info details for uprobe_multi links and adding support for bpftool link to display them.
v4 changes:
- move flags field up in bpf_uprobe_multi_link [Andrii]
- include zero terminating byte in path_size [Andrii]
- return d_path error directly [Yonghong]
- use SEC(".probes") for semaphores [Yonghong]
- fix ref_ctr_offsets leak in test [Yonghong]
- other smaller fixes [Yonghong]
thanks,
jirka
---
Jiri Olsa (6):
libbpf: Add st_type argument to elf_resolve_syms_offsets function
bpf: Store ref_ctr_offsets values in bpf_uprobe array
bpf: Add link_info support for uprobe multi link selftests/bpf: Use bpf_link__destroy in fill_link_info tests selftests/bpf: Add link_info test for uprobe_multi link
bpftool: Add support to display uprobe_multi links
include/uapi/linux/bpf.h | 10 ++++ kernel/trace/bpf_trace.c | 86 ++++++++++++++++++++++++++++----- tools/bpf/bpftool/link.c | 105 +++++++++++++++++++++++++++++++++++++++- tools/include/uapi/linux/bpf.h | 10 ++++ tools/lib/bpf/elf.c | 5 +- tools/lib/bpf/libbpf.c | 2 +- tools/lib/bpf/libbpf_internal.h | 3 +- tools/testing/selftests/bpf/prog_tests/fill_link_info.c | 242 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c | 2 +- tools/testing/selftests/bpf/progs/test_fill_link_info.c | 6 +++ 10 files changed, 432 insertions(+), 39 deletions(-)
Jiri Olsa
reviewerPATCH v4 1/6 libbpf: Add st_type argument to elf_resolve_syms_offsets function
We need to get offsets for static variables in following changes, so making elf_resolve_syms_offsets to take st_type value as argument and passing it to elf_sym_iter_new.
--- tools/lib/bpf/elf.c | 5 +++-- tools/lib/bpf/libbpf.c | 2 +- tools/lib/bpf/libbpf_internal.h | 3 ++- tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-)
tools/lib/bpf/elf.c +3 -2
@@ -407,7 +407,8 @@ static int symbol_cmp(const void *a, const void *b)* size, that needs to be released by the caller. */ int elf_resolve_syms_offsets (const char *binary_path,int cnt, -const char **syms,unsigned long **poffsets) +const char **syms,unsigned long **poffsets, +int st_type) {int sh_types[2 ] = {SHT_DYNSYM ,SHT_SYMTAB };int err =0 , i, cnt_done =0 ;
@@ -438,7 +439,7 @@ int elf_resolve_syms_offsets(const char *binary_path, int cnt,struct elf_sym_iter iter;struct elf_sym *sym; - err =elf_sym_iter_new (&iter, elf_fd.elf, binary_path, sh_types[i],STT_FUNC ); + err =elf_sym_iter_new (&iter, elf_fd.elf, binary_path, sh_types[i], st_type);if (err == -ENOENT )continue ;if (err)
tools/lib/bpf/libbpf.c +1 -1
@@ -11447,7 +11447,7 @@ bpf_program__attach_uprobe_multi(const struct bpf_program *prog,return libbpf_err_ptr (err); offsets = resolved_offsets; }else if (syms) { - err =elf_resolve_syms_offsets (path, cnt, syms, &resolved_offsets); + err =elf_resolve_syms_offsets (path, cnt, syms, &resolved_offsets,STT_FUNC );if (err <0 )return libbpf_err_ptr (err); offsets = resolved_offsets;
tools/lib/bpf/libbpf_internal.h +2 -1
@@ -594,7 +594,8 @@ int elf_open(const char *binary_path, struct elf_fd *elf_fd);void elf_close (struct elf_fd *elf_fd);int elf_resolve_syms_offsets (const char *binary_path,int cnt, -const char **syms,unsigned long **poffsets); +const char **syms,unsigned long **poffsets, +int st_type);int elf_resolve_pattern_offsets (const char *binary_path,const char *pattern,unsigned long **poffsets,size_t *pcnt);
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +1 -1
@@ -249,7 +249,7 @@ static void __test_link_api(struct child *child)int link_extra_fd =-1 ;int err; - err =elf_resolve_syms_offsets (path,3 , syms, (unsigned long **) &offsets); + err =elf_resolve_syms_offsets (path,3 , syms, (unsigned long **) &offsets,STT_FUNC );if (!ASSERT_OK (err,"elf_resolve_syms_offsets" ))return ;
Signature · 1 line
2.42.0
Jiri Olsa
reviewerPATCH v4 2/6 bpf: Store ref_ctr_offsets values in bpf_uprobe array
In reply to Jiri OlsaWe will need to return ref_ctr_offsets values through link_info interface in following change, so we need to keep them around.
Storing ref_ctr_offsets values directly into bpf_uprobe array.
--- kernel/trace/bpf_trace.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-)
kernel/trace/bpf_trace.c +3 -11
@@ -3033,6 +3033,7 @@ struct bpf_uprobe_multi_link;struct bpf_uprobe {struct bpf_uprobe_multi_link *link;loff_t offset; +unsigned long ref_ctr_offset;u64 cookie;struct uprobe_consumer consumer; };
@@ -3172,7 +3173,6 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr {struct bpf_uprobe_multi_link *link =NULL ;unsigned long __user *uref_ctr_offsets; -unsigned long *ref_ctr_offsets =NULL ;struct bpf_link_primer link_primer;struct bpf_uprobe *uprobes =NULL ;struct task_struct *task =NULL ;
@@ -3245,18 +3245,12 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prif (!uprobes || !link) goto error_free; -if (uref_ctr_offsets) { - ref_ctr_offsets =kvcalloc (cnt,sizeof (*ref_ctr_offsets),GFP_KERNEL ); -if (!ref_ctr_offsets) - goto error_free; - } -for (i =0 ; i < cnt; i++) {if (ucookies &&__get_user (uprobes[i].cookie, ucookies + i)) { err = -EFAULT ; goto error_free; } -if (uref_ctr_offsets &&__get_user (ref_ctr_offsets[i], uref_ctr_offsets + i)) { +if (uref_ctr_offsets &&__get_user (uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) { err = -EFAULT ; goto error_free; }
@@ -3287,7 +3281,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prfor (i =0 ; i < cnt; i++) { err =uprobe_register_refctr (d_real_inode (link->path.dentry), uprobes[i].offset, - ref_ctr_offsets ? ref_ctr_offsets[i] :0 , + uprobes[i].ref_ctr_offset, &uprobes[i].consumer);if (err) {bpf_uprobe_unregister (&path, uprobes, i);
@@ -3299,11 +3293,9 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prif (err) goto error_free; -kvfree (ref_ctr_offsets);return bpf_link_settle (&link_primer); error_free: -kvfree (ref_ctr_offsets);kvfree (uprobes);kfree (link);if (task)
Signature · 1 line
2.42.0
Jiri Olsa
reviewerPATCH v4 3/6 bpf: Add link_info support for uprobe multi link
In reply to Jiri OlsaAdding support to get uprobe_link details through bpf_link_info interface.
Adding new struct uprobe_multi to struct bpf_link_info to carry the uprobe_multi link details.
The uprobe_multi.count is passed from user space to denote size of array fields (offsets/ref_ctr_offsets/cookies). The actual array size is stored back to uprobe_multi.count (allowing user to find out the actual array size) and array fields are populated up to the user passed size.
All the non-array fields (path/count/flags/pid) are always set.
--- include/uapi/linux/bpf.h | 10 +++++ kernel/trace/bpf_trace.c | 72 ++++++++++++++++++++++++++++++++++ tools/include/uapi/linux/bpf.h | 10 +++++ 3 files changed, 92 insertions(+)
include/uapi/linux/bpf.h +10 -0
@@ -6562,6 +6562,16 @@ struct bpf_link_info {__u32 flags;__u64 missed; } kprobe_multi; +struct { +__aligned_u64 path; +__aligned_u64 offsets; +__aligned_u64 ref_ctr_offsets; +__aligned_u64 cookies; +__u32 path_size;/* in/out: real path size on success, including zero byte */ +__u32 count;/* in/out: uprobe_multi offsets/ref_ctr_offsets/cookies count */ +__u32 flags; +__u32 pid; + } uprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */ __u32 :32;
kernel/trace/bpf_trace.c +72 -0
93 lines not on this page · raw message
tools/include/uapi/linux/bpf.h +10 -0
@@ -6562,6 +6562,16 @@ struct bpf_link_info {__u32 flags;__u64 missed; } kprobe_multi; +struct { +__aligned_u64 path; +__aligned_u64 offsets; +__aligned_u64 ref_ctr_offsets; +__aligned_u64 cookies; +__u32 path_size;/* in/out: real path size on success, including zero byte */ +__u32 count;/* in/out: uprobe_multi offsets/ref_ctr_offsets/cookies count */ +__u32 flags; +__u32 pid; + } uprobe_multi;struct {__u32 type;/* enum bpf_perf_event_type */ __u32 :32;
Signature · 1 line
2.42.0
Quoted 12 lines · Jiri Olsa
Adding support to get
uprobe_linkdetails throughbpf_link_infointerface.Adding new struct
uprobe_multito structbpf_link_infoto carry theuprobe_multilink details.The uprobe_multi.count is passed from user space to denote size of array fields (offsets/ref_ctr_offsets/cookies). The actual array size is stored back to uprobe_multi.count (allowing user to find out the actual array size) and array fields are populated up to the user passed size.
Quoted 3 lines
All the non-array fields (path/count/flags/pid) are always set.
Signed-off-by Jiri Olsa <[email protected]>
Jiri Olsa
reviewerPATCH v4 4/6 selftests/bpf: Use bpf_link__destroy in fill_link_info tests
In reply to Jiri OlsaThe fill_link_info test keeps skeleton open and just creates various links. We are wrongly calling bpf_link__detach after each test to close them, we need to call bpf_link__destroy.
--- .../selftests/bpf/prog_tests/fill_link_info.c | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-)
tools/testing/selftests/bpf/prog_tests/fill_link_info.c +23 -21
@@ -140,14 +140,14 @@ static void test_kprobe_fill_link_info(struct test_fill_link_info *skel, .retprobe = type == BPF_PERF_EVENT_KRETPROBE, );ssize_t entry_offset =0 ; +struct bpf_link *link;int link_fd, err; - skel->links.kprobe_run =bpf_program__attach_kprobe_opts (skel->progs.kprobe_run, -KPROBE_FUNC , &opts); -if (!ASSERT_OK_PTR (skel->links.kprobe_run,"attach_kprobe" )) + link =bpf_program__attach_kprobe_opts (skel->progs.kprobe_run,KPROBE_FUNC , &opts); +if (!ASSERT_OK_PTR (link,"attach_kprobe" ))return ; - link_fd =bpf_link__fd (skel->links.kprobe_run); + link_fd =bpf_link__fd (link);if (!invalid) {/* See also arch_adjust_kprobe_addr(). */ if (skel->kconfig->CONFIG_X86_KERNEL_IBT)
@@ -157,39 +157,41 @@ static void test_kprobe_fill_link_info(struct test_fill_link_info *skel, }else {kprobe_fill_invalid_user_buffer (link_fd); } -bpf_link__detach (skel->links.kprobe_run); +bpf_link__destroy (link); }static void test_tp_fill_link_info (struct test_fill_link_info *skel) { +struct bpf_link *link;int link_fd, err; - skel->links.tp_run =bpf_program__attach_tracepoint (skel->progs.tp_run,TP_CAT ,TP_NAME ); -if (!ASSERT_OK_PTR (skel->links.tp_run,"attach_tp" )) + link =bpf_program__attach_tracepoint (skel->progs.tp_run,TP_CAT ,TP_NAME ); +if (!ASSERT_OK_PTR (link,"attach_tp" ))return ; - link_fd =bpf_link__fd (skel->links.tp_run); + link_fd =bpf_link__fd (link); err =verify_perf_link_info (link_fd,BPF_PERF_EVENT_TRACEPOINT ,0 ,0 ,0 );ASSERT_OK (err,"verify_perf_link_info" ); -bpf_link__detach (skel->links.tp_run); +bpf_link__destroy (link); }static void test_uprobe_fill_link_info (struct test_fill_link_info *skel,enum bpf_perf_event_type type) { +struct bpf_link *link;int link_fd, err; - skel->links.uprobe_run =bpf_program__attach_uprobe (skel->progs.uprobe_run, - type ==BPF_PERF_EVENT_URETPROBE , -0 ,/* self pid */ -UPROBE_FILE , uprobe_offset); -if (!ASSERT_OK_PTR (skel->links.uprobe_run,"attach_uprobe" )) + link =bpf_program__attach_uprobe (skel->progs.uprobe_run, + type ==BPF_PERF_EVENT_URETPROBE , +0 ,/* self pid */ +UPROBE_FILE , uprobe_offset); +if (!ASSERT_OK_PTR (link,"attach_uprobe" ))return ; - link_fd =bpf_link__fd (skel->links.uprobe_run); + link_fd =bpf_link__fd (link); err =verify_perf_link_info (link_fd, type,0 , uprobe_offset,0 );ASSERT_OK (err,"verify_perf_link_info" ); -bpf_link__detach (skel->links.uprobe_run); +bpf_link__destroy (link); }static int verify_kmulti_link_info (int fd,bool retprobe)
@@ -278,24 +280,24 @@ static void test_kprobe_multi_fill_link_info(struct test_fill_link_info *skel, bool retprobe, bool invalid) {LIBBPF_OPTS (bpf_kprobe_multi_opts ,opts ); +struct bpf_link *link;int link_fd, err; opts.syms = kmulti_syms; opts.cnt =KMULTI_CNT ; opts.retprobe = retprobe; - skel->links.kmulti_run =bpf_program__attach_kprobe_multi_opts (skel->progs.kmulti_run, -NULL , &opts); -if (!ASSERT_OK_PTR (skel->links.kmulti_run,"attach_kprobe_multi" )) + link =bpf_program__attach_kprobe_multi_opts (skel->progs.kmulti_run,NULL , &opts); +if (!ASSERT_OK_PTR (link,"attach_kprobe_multi" ))return ; - link_fd =bpf_link__fd (skel->links.kmulti_run); + link_fd =bpf_link__fd (link);if (!invalid) { err =verify_kmulti_link_info (link_fd, retprobe);ASSERT_OK (err,"verify_kmulti_link_info" ); }else {verify_kmulti_invalid_user_buffer (link_fd); } -bpf_link__detach (skel->links.kmulti_run); +bpf_link__destroy (link); }void test_fill_link_info (void )
Signature · 1 line
2.42.0
Jiri Olsa
reviewerPATCH v4 5/6 selftests/bpf: Add link_info test for uprobe_multi link
In reply to Jiri OlsaAdding fill_link_info test for uprobe_multi link.
Setting up uprobes with bogus ref_ctr_offsets and cookie values to test all the bpf_link_info::uprobe_multi fields.
--- .../selftests/bpf/prog_tests/fill_link_info.c | 198 ++++++++++++++++++ .../selftests/bpf/progs/test_fill_link_info.c | 6 + 2 files changed, 204 insertions(+)
tools/testing/selftests/bpf/prog_tests/fill_link_info.c +198 -0
@@ -7,6 +7,7 @@#include <test_progs.h> #include "trace_helpers.h" #include "test_fill_link_info.skel.h" +#include "bpf/libbpf_internal.h" #define TP_CAT "sched"#define TP_NAME "sched_switch"
@@ -300,6 +301,196 @@ static void test_kprobe_multi_fill_link_info(struct test_fill_link_info *skel,bpf_link__destroy (link); } +#define SEC (name) __attribute__((section(name), used)) + +static short uprobe_link_info_sema_1 SEC(".probes"); +static short uprobe_link_info_sema_2 SEC(".probes"); +static short uprobe_link_info_sema_3 SEC(".probes"); + +noinline void uprobe_link_info_func_1(void) +{ + asmvolatile ("" ); + uprobe_link_info_sema_1++; +} + +noinline void uprobe_link_info_func_2(void) +{ + asmvolatile ("" ); + uprobe_link_info_sema_2++; +} + +noinline void uprobe_link_info_func_3(void) +{ + asmvolatile ("" ); + uprobe_link_info_sema_3++; +} + +static int +verify_umulti_link_info (int fd,bool retprobe,__u64 *offsets, +__u64 *cookies,__u64 *ref_ctr_offsets) +{ +char path[PATH_MAX ], path_buf[PATH_MAX ]; +struct bpf_link_info info; +__u32 len =sizeof (info); +__u64 ref_ctr_offsets_buf[3 ]; +__u64 offsets_buf[3 ]; +__u64 cookies_buf[3 ]; +int i, err, bit; +__u32 count =0 ; + +memset (path,0 ,sizeof (path)); + err =readlink ("/proc/self/exe" , path,sizeof (path)); +if (!ASSERT_NEQ (err,-1 ,"readlink" )) +return -1 ; + +for (bit =0 ; bit <8 ; bit++) { +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.path =ptr_to_u64 (path_buf); + info.uprobe_multi.path_size =sizeof (path_buf); + info.uprobe_multi.count = count; + +if (bit &0x1 ) + info.uprobe_multi.offsets =ptr_to_u64 (offsets_buf); +if (bit &0x2 ) + info.uprobe_multi.cookies =ptr_to_u64 (cookies_buf); +if (bit &0x4 ) + info.uprobe_multi.ref_ctr_offsets =ptr_to_u64 (ref_ctr_offsets_buf); + + err =bpf_link_get_info_by_fd (fd, &info, &len); +if (!ASSERT_OK (err,"bpf_link_get_info_by_fd" )) +return -1 ; + +if (!ASSERT_EQ (info.type,BPF_LINK_TYPE_UPROBE_MULTI ,"info.type" )) +return -1 ; + +ASSERT_EQ (info.uprobe_multi.pid,getpid (),"info.uprobe_multi.pid" ); +ASSERT_EQ (info.uprobe_multi.count,3 ,"info.uprobe_multi.count" ); +ASSERT_EQ (info.uprobe_multi.flags &BPF_F_KPROBE_MULTI_RETURN , + retprobe,"info.uprobe_multi.flags.retprobe" ); +ASSERT_EQ (info.uprobe_multi.path_size,strlen (path) +1 ,"info.uprobe_multi.path_size" ); +ASSERT_STREQ (path_buf, path,"info.uprobe_multi.path" ); + +for (i =0 ; i < info.uprobe_multi.count; i++) { +if (info.uprobe_multi.offsets) +ASSERT_EQ (offsets_buf[i], offsets[i],"info.uprobe_multi.offsets" ); +if (info.uprobe_multi.cookies) +ASSERT_EQ (cookies_buf[i], cookies[i],"info.uprobe_multi.cookies" ); +if (info.uprobe_multi.ref_ctr_offsets) { +ASSERT_EQ (ref_ctr_offsets_buf[i], ref_ctr_offsets[i], +"info.uprobe_multi.ref_ctr_offsets" ); + } + } + count = count ?: info.uprobe_multi.count; + } + +return 0 ; +} + +static void verify_umulti_invalid_user_buffer (int fd) +{ +struct bpf_link_info info; +__u32 len =sizeof (info); +__u64 buf[3 ]; +int err; + +/* upath_size defined, not path */ +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.path_size =3 ; + err =bpf_link_get_info_by_fd (fd, &info, &len); +ASSERT_EQ (err, -EINVAL ,"failed_upath_size" ); + +/* path defined, but small */ +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.path =ptr_to_u64 (buf); + info.uprobe_multi.path_size =3 ; + err =bpf_link_get_info_by_fd (fd, &info, &len); +ASSERT_LT (err,0 ,"failed_upath_small" ); + +/* path has wrong pointer */ +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.path_size =PATH_MAX ; + info.uprobe_multi.path =123 ; + err =bpf_link_get_info_by_fd (fd, &info, &len); +ASSERT_EQ (err, -EFAULT ,"failed_bad_path_ptr" ); + +/* count zero, with offsets */ +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.offsets =ptr_to_u64 (buf); + err =bpf_link_get_info_by_fd (fd, &info, &len); +ASSERT_EQ (err, -EINVAL ,"failed_count" ); + +/* offsets not big enough */ +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.offsets =ptr_to_u64 (buf); + info.uprobe_multi.count =2 ; + err =bpf_link_get_info_by_fd (fd, &info, &len); +ASSERT_EQ (err, -ENOSPC ,"failed_small_count" ); + +/* offsets has wrong pointer */ +memset (&info,0 ,sizeof (info)); + info.uprobe_multi.offsets =123 ; + info.uprobe_multi.count =3 ; + err =bpf_link_get_info_by_fd (fd, &info, &len); +ASSERT_EQ (err, -EFAULT ,"failed_wrong_offsets" ); +} + +static void test_uprobe_multi_fill_link_info (struct test_fill_link_info *skel, +bool retprobe,bool invalid) +{ +LIBBPF_OPTS (bpf_uprobe_multi_opts, opts, + .retprobe = retprobe, + ); +const char *syms[3 ] = { +"uprobe_link_info_func_1" , +"uprobe_link_info_func_2" , +"uprobe_link_info_func_3" , + }; +__u64 cookies[3 ] = { +0xdead , +0xbeef , +0xcafe , + }; +const char *sema[3 ] = { +"uprobe_link_info_sema_1" , +"uprobe_link_info_sema_2" , +"uprobe_link_info_sema_3" , + }; +__u64 *offsets =NULL , *ref_ctr_offsets; +struct bpf_link *link; +int link_fd, err; + + err =elf_resolve_syms_offsets ("/proc/self/exe" ,3 , sema, + (unsigned long **) &ref_ctr_offsets,STT_OBJECT ); +if (!ASSERT_OK (err,"elf_resolve_syms_offsets_object" )) +return ; + + err =elf_resolve_syms_offsets ("/proc/self/exe" ,3 , syms, + (unsigned long **) &offsets,STT_FUNC ); +if (!ASSERT_OK (err,"elf_resolve_syms_offsets_func" )) + goto out; + + opts.syms = syms; + opts.cookies = &cookies[0 ]; + opts.ref_ctr_offsets = (unsigned long *) &ref_ctr_offsets[0 ]; + opts.cnt =ARRAY_SIZE (syms); + + link =bpf_program__attach_uprobe_multi (skel->progs.umulti_run,0 , +"/proc/self/exe" ,NULL , &opts); +if (!ASSERT_OK_PTR (link,"bpf_program__attach_uprobe_multi" )) + goto out; + + link_fd =bpf_link__fd (link); +if (invalid) +verify_umulti_invalid_user_buffer (link_fd); +else +verify_umulti_link_info (link_fd, retprobe, offsets, cookies, ref_ctr_offsets); + +bpf_link__destroy (link); +out: +free (ref_ctr_offsets); +free (offsets); +} +void test_fill_link_info (void ) {struct test_fill_link_info *skel;
@@ -339,6 +530,13 @@ void test_fill_link_info(void)if (test__start_subtest ("kprobe_multi_invalid_ubuff" ))test_kprobe_multi_fill_link_info (skel, true, true); +if (test__start_subtest ("uprobe_multi_link_info" )) +test_uprobe_multi_fill_link_info (skel, false, false); +if (test__start_subtest ("uretprobe_multi_link_info" )) +test_uprobe_multi_fill_link_info (skel, true, false); +if (test__start_subtest ("uprobe_multi_invalid" )) +test_uprobe_multi_fill_link_info (skel, false, true); + cleanup:test_fill_link_info__destroy (skel); }
tools/testing/selftests/bpf/progs/test_fill_link_info.c +6 -0
@@ -39,4 +39,10 @@ int BPF_PROG(kmulti_run)return 0 ; } +SEC("uprobe.multi") +int BPF_PROG (umulti_run ) +{ +return 0 ; +} + char _license[] SEC("license") = "GPL";
Signature · 1 line
2.42.0
Re: [PATCHv4 bpf-next 5/6] selftests/bpf: Add link_info test for uprobe_multi link
Quoted 7 lines · Jiri Olsa
Adding
fill_link_infotest foruprobe_multilink.Setting up uprobes with bogus
ref_ctr_offsetsand cookie values to test all thebpf_link_info::uprobe_multifields.Acked-by Song Liu <[email protected]>Signed-off-by Jiri Olsa <[email protected]>
Jiri Olsa
reviewerPATCH v4 6/6 bpftool: Add support to display uprobe_multi links
In reply to Jiri OlsaAdding support to display details for uprobe_multi links, both plain:
# bpftool link -p
...
24: uprobe_multi prog 126
uprobe.multi path /home/jolsa/bpf/test_progs func_cnt 3 pid 4143
offset ref_ctr_offset cookies
0xd1f88 0xf5d5a8 0xdead
0xd1f8f 0xf5d5aa 0xbeef
0xd1f96 0xf5d5ac 0xcafeand json:
# bpftool link -p
[{
...
},{
"id": 24,
"type": "uprobe_multi",
"prog_id": 126,
"retprobe": false,
"path": "/home/jolsa/bpf/test_progs",
"func_cnt": 3,
"pid": 4143,
"funcs": [{
"offset": 860040,
"ref_ctr_offset": 16111016,
"cookie": 57005
},{
"offset": 860047,
"ref_ctr_offset": 16111018,
"cookie": 48879
},{
"offset": 860054,
"ref_ctr_offset": 16111020,
"cookie": 51966
}
]
}
]--- tools/bpf/bpftool/link.c | 105 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-)
tools/bpf/bpftool/link.c +103 -2
@@ -294,6 +294,37 @@ show_kprobe_multi_json(struct bpf_link_info *info, json_writer_t *wtr)jsonw_end_array (json_wtr); } +static __u64 *u64_to_arr (__u64 val) +{ +return (__u64 *)u64_to_ptr (val); +} + +static void +show_uprobe_multi_json (struct bpf_link_info *info,json_writer_t *wtr) +{ +__u32 i; + +jsonw_bool_field (json_wtr,"retprobe" , + info->uprobe_multi.flags &BPF_F_UPROBE_MULTI_RETURN ); +jsonw_string_field (json_wtr,"path" , (char *)u64_to_ptr (info->uprobe_multi.path)); +jsonw_uint_field (json_wtr,"func_cnt" , info->uprobe_multi.count); +jsonw_int_field (json_wtr,"pid" , (int ) info->uprobe_multi.pid); +jsonw_name (json_wtr,"funcs" ); +jsonw_start_array (json_wtr); + +for (i =0 ; i < info->uprobe_multi.count; i++) { +jsonw_start_object (json_wtr); +jsonw_uint_field (json_wtr,"offset" , +u64_to_arr (info->uprobe_multi.offsets)[i]); +jsonw_uint_field (json_wtr,"ref_ctr_offset" , +u64_to_arr (info->uprobe_multi.ref_ctr_offsets)[i]); +jsonw_uint_field (json_wtr,"cookie" , +u64_to_arr (info->uprobe_multi.cookies)[i]); +jsonw_end_object (json_wtr); + } +jsonw_end_array (json_wtr); +} +static void show_perf_event_kprobe_json (struct bpf_link_info *info,json_writer_t *wtr) {
@@ -465,6 +496,9 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)case BPF_LINK_TYPE_KPROBE_MULTI :show_kprobe_multi_json (info, json_wtr);break ; +case BPF_LINK_TYPE_UPROBE_MULTI : +show_uprobe_multi_json (info, json_wtr); +break ;case BPF_LINK_TYPE_PERF_EVENT :switch (info->perf_event.type) {case BPF_PERF_EVENT_EVENT :
@@ -674,6 +708,33 @@ static void show_kprobe_multi_plain(struct bpf_link_info *info) } } +static void show_uprobe_multi_plain (struct bpf_link_info *info) +{ +__u32 i; + +if (!info->uprobe_multi.count) +return ; + +if (info->uprobe_multi.flags &BPF_F_UPROBE_MULTI_RETURN ) +printf ("\n\turetprobe.multi " ); +else +printf ("\n\tuprobe.multi " ); + +printf ("path %s " , (char *)u64_to_ptr (info->uprobe_multi.path)); +printf ("func_cnt %u " , info->uprobe_multi.count); + +if (info->uprobe_multi.pid) +printf ("pid %d " , info->uprobe_multi.pid); + +printf ("\n\t%-16s %-16s %-16s" ,"offset" ,"ref_ctr_offset" ,"cookies" ); +for (i =0 ; i < info->uprobe_multi.count; i++) { +printf ("\n\t0x%-16llx 0x%-16llx 0x%-16llx" , +u64_to_arr (info->uprobe_multi.offsets)[i], +u64_to_arr (info->uprobe_multi.ref_ctr_offsets)[i], +u64_to_arr (info->uprobe_multi.cookies)[i]); + } +} +static void show_perf_event_kprobe_plain (struct bpf_link_info *info) {const char *buf;
@@ -807,6 +868,9 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)case BPF_LINK_TYPE_KPROBE_MULTI :show_kprobe_multi_plain (info);break ; +case BPF_LINK_TYPE_UPROBE_MULTI : +show_uprobe_multi_plain (info); +break ;case BPF_LINK_TYPE_PERF_EVENT :switch (info->perf_event.type) {case BPF_PERF_EVENT_EVENT :
@@ -846,8 +910,10 @@ 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 ;struct bpf_link_info info;__u32 len =sizeof (info); +char path_buf[PATH_MAX ];__u64 *addrs =NULL ;char buf[PATH_MAX ];int count;
@@ -889,6 +955,39 @@ static int do_show_link(int fd) goto again; } } +if (info.type ==BPF_LINK_TYPE_UPROBE_MULTI && + !info.uprobe_multi.offsets) { + count = info.uprobe_multi.count; +if (count) { + offsets =calloc (count,sizeof (__u64)); +if (!offsets) { +p_err ("mem alloc failed" ); +close (fd); +return -ENOMEM ; + } + info.uprobe_multi.offsets =ptr_to_u64 (offsets); + ref_ctr_offsets =calloc (count,sizeof (__u64)); +if (!ref_ctr_offsets) { +p_err ("mem alloc failed" ); +free (offsets); +close (fd); +return -ENOMEM ; + } + info.uprobe_multi.ref_ctr_offsets =ptr_to_u64 (ref_ctr_offsets); + cookies =calloc (count,sizeof (__u64)); +if (!cookies) { +p_err ("mem alloc failed" ); +free (cookies); +free (offsets); +close (fd); +return -ENOMEM ; + } + info.uprobe_multi.cookies =ptr_to_u64 (cookies); + info.uprobe_multi.path =ptr_to_u64 (path_buf); + info.uprobe_multi.path_size =sizeof (path_buf); + goto again; + } + }if (info.type ==BPF_LINK_TYPE_PERF_EVENT ) {switch (info.perf_event.type) {case BPF_PERF_EVENT_TRACEPOINT :
@@ -924,8 +1023,10 @@ static int do_show_link(int fd)else show_link_close_plain (fd, &info); -if (addrs) -free (addrs); +free (ref_ctr_offsets); +free (cookies); +free (offsets); +free (addrs);close (fd);return 0 ; }
Signature · 1 line
2.42.0
This series was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <[email protected]>:
Hello:
This series was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <[email protected]>:
Quoted 13 lines · On Sat, 25 Nov 2023 20:31:24 +0100 you wrote:
hi,
this patchset adds support to getbpf_link_infodetails foruprobe_multilinks and adding support for bpftool link to display them.v4 changes:
- move flags field up inbpf_uprobe_multi_link[Andrii]
- include zero terminating byte inpath_size[Andrii]
- returnd_patherror directly [Yonghong]
- useSEC(".probes")for semaphores [Yonghong]
- fixref_ctr_offsetsleak in test [Yonghong]
- other smaller fixes [Yonghong]
Quoted 1 line
[...]
Here is the summary with links:
- [PATCHv4,bpf-next,1/6] libbpf: Add st_type argument to elf_resolve_syms_offsets function
https://git.kernel.org/bpf/bpf-next/c/48f0dfd8d3e2 - [PATCHv4,bpf-next,2/6] bpf: Store ref_ctr_offsets values in bpf_uprobe array https://git.kernel.org/bpf/bpf-next/c/4930b7f53a29 - [PATCHv4,bpf-next,3/6] bpf: Add link_info support for uprobe multi link https://git.kernel.org/bpf/bpf-next/c/e56fdbfb06e2 - [PATCHv4,bpf-next,4/6] selftests/bpf: Use bpf_link__destroy in fill_link_info tests https://git.kernel.org/bpf/bpf-next/c/170361288572 - [PATCHv4,bpf-next,5/6] selftests/bpf: Add link_info test for uprobe_multi link https://git.kernel.org/bpf/bpf-next/c/147c69307bcf - [PATCHv4,bpf-next,6/6] bpftool: Add support to display uprobe_multi links https://git.kernel.org/bpf/bpf-next/c/a7795698f8b6
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html