By design, a tracing_multi link does not support both kernel functions and bpf progs at the same time. In libbpf, the bpf_tracing_multi_opts options provides two new fields for tracing bpf progs: * 'fds': the fd array of the target bpf progs. One fd must be provided multiple times for multiple targets. * 'funcs': the function name array of the target bpf progs. The 'cnt' field indicates the size of both 'fds' and 'funcs' arrays. The 'funcs' will be translated to 'ids' by 'libbpf_find_prog_btf_id()'. At last, 'fds'+'ids' will be passed to kernel. Signed-off-by: Leon Hwang --- tools/lib/bpf/bpf.c | 1 + tools/lib/bpf/bpf.h | 2 ++ tools/lib/bpf/libbpf.c | 41 +++++++++++++++++++++++++++++++++++++---- tools/lib/bpf/libbpf.h | 4 +++- 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index b49822d212ae..4a78ccba9df2 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -852,6 +852,7 @@ int bpf_link_create(int prog_fd, int target_fd, attr.link_create.tracing_multi.ids = ptr_to_u64(OPTS_GET(opts, tracing_multi.ids, 0)); attr.link_create.tracing_multi.cookies = ptr_to_u64(OPTS_GET(opts, tracing_multi.cookies, 0)); attr.link_create.tracing_multi.cnt = OPTS_GET(opts, tracing_multi.cnt, 0); + attr.link_create.tracing_multi.fds = ptr_to_u64(OPTS_GET(opts, tracing_multi.fds, 0)); if (!OPTS_ZEROED(opts, tracing_multi)) return libbpf_err(-EINVAL); break; diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 826d9cc9ab65..cc37cf622dd8 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -474,6 +474,8 @@ struct bpf_link_create_opts { const __u32 *ids; const __u64 *cookies; __u32 cnt; + __u32 :32; + const int *fds; } tracing_multi; }; size_t :0; diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index cb09ded90773..edc5e8e813f3 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -13671,10 +13671,12 @@ bpf_program__attach_tracing_multi(const struct bpf_program *prog, const char *pa { LIBBPF_OPTS(bpf_link_create_opts, lopts); int prog_fd, link_fd, err, cnt; + struct bpf_link *link = NULL; __u32 *free_ids = NULL; - struct bpf_link *link; const __u64 *cookies; + const char **funcs; const __u32 *ids; + const int *fds; if (!OPTS_VALID(opts, bpf_tracing_multi_opts)) return libbpf_err_ptr(-EINVAL); @@ -13689,12 +13691,22 @@ bpf_program__attach_tracing_multi(const struct bpf_program *prog, const char *pa cnt = OPTS_GET(opts, cnt, 0); ids = OPTS_GET(opts, ids, NULL); cookies = OPTS_GET(opts, cookies, NULL); + fds = OPTS_GET(opts, fds, NULL); + funcs = OPTS_GET(opts, funcs, NULL); - if (!!ids != !!cnt) + if (ids && fds) + return libbpf_err_ptr(-EINVAL); + if (!!fds != !!funcs) + return libbpf_err_ptr(-EINVAL); + if (fds && !cnt) return libbpf_err_ptr(-EINVAL); - if (pattern && (ids || cookies)) + if (ids && !cnt) return libbpf_err_ptr(-EINVAL); - if (!pattern && !ids) + if (!fds && !ids && cnt) + return libbpf_err_ptr(-EINVAL); + if (pattern && (fds || ids || cookies)) + return libbpf_err_ptr(-EINVAL); + if (!pattern && !ids && !fds) return libbpf_err_ptr(-EINVAL); if (pattern) { @@ -13704,11 +13716,32 @@ bpf_program__attach_tracing_multi(const struct bpf_program *prog, const char *pa if (cnt == 0) return libbpf_err_ptr(-EINVAL); ids = (const __u32 *) free_ids; + } else if (fds) { + size_t cap = 0; + int i; + + err = libbpf_ensure_mem((void **) &free_ids, &cap, sizeof(*free_ids), cnt); + if (err) + return libbpf_err_ptr(err); + + for (i = 0; i < cnt; i++) { + if (!funcs[i]) { + err = -EINVAL; + goto error; + } + err = libbpf_find_prog_btf_id(funcs[i], fds[i], prog->obj->token_fd); + if (err < 0) + goto error; + + free_ids[i] = err; + } + ids = (const __u32 *) free_ids; } lopts.tracing_multi.ids = ids; lopts.tracing_multi.cookies = cookies; lopts.tracing_multi.cnt = cnt; + lopts.tracing_multi.fds = fds; link = calloc(1, sizeof(*link)); if (!link) { diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 03f794f4adb0..612f3e17ebc2 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -746,10 +746,12 @@ struct bpf_tracing_multi_opts { const __u32 *ids; const __u64 *cookies; size_t cnt; + const int *fds; + const char **funcs; size_t :0; }; -#define bpf_tracing_multi_opts__last_field cnt +#define bpf_tracing_multi_opts__last_field funcs LIBBPF_API struct bpf_link * bpf_program__attach_tracing_multi(const struct bpf_program *prog, const char *pattern, -- 2.55.0