From: Jiri Olsa <jolsa@kernel.org>
To: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org, Martin KaFai Lau <kafai@fb.com>,
Song Liu <songliubraving@fb.com>, Yonghong Song <yhs@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@chromium.org>,
Stanislav Fomichev <sdf@google.com>, Hao Luo <haoluo@google.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>
Subject: [RFC/PATCH bpf-next 12/20] libbpf: Add uprobe multi link support to bpf_program__attach_usdt
Date: Mon, 24 Apr 2023 18:04:39 +0200 [thread overview]
Message-ID: <20230424160447.2005755-13-jolsa@kernel.org> (raw)
In-Reply-To: <20230424160447.2005755-1-jolsa@kernel.org>
Adding uprobe_multi bool to struct bpf_usdt_opts. If it's true
the usdt_manager_attach_usdt will use uprobe_multi link to attach
to usdt probes.
The bpf program for usdt probe needs to have BPF_TRACE_UPROBE_MULTI
set as expected_attach_type.
Because current uprobe is implemented through perf event interface,
it allows the pid filter for uprobes. This is not the case for
uprobe_multi link, so the pid filter is not allowed for that.
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
tools/lib/bpf/libbpf.c | 9 ++-
tools/lib/bpf/libbpf.h | 2 +
tools/lib/bpf/libbpf_internal.h | 2 +-
tools/lib/bpf/usdt.c | 127 ++++++++++++++++++++++++--------
4 files changed, 105 insertions(+), 35 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 70353aaac86e..25d32aa605e8 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -6817,7 +6817,6 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
if (!insns || !insns_cnt)
return -EINVAL;
- load_attr.expected_attach_type = prog->expected_attach_type;
if (kernel_supports(obj, FEAT_PROG_NAME))
prog_name = prog->name;
load_attr.attach_prog_fd = prog->attach_prog_fd;
@@ -6853,6 +6852,9 @@ static int bpf_object_load_prog(struct bpf_object *obj, struct bpf_program *prog
insns_cnt = prog->insns_cnt;
}
+ /* allow prog_prepare_load_fn to change expected_attach_type */
+ load_attr.expected_attach_type = prog->expected_attach_type;
+
if (obj->gen_loader) {
bpf_gen__prog_load(obj->gen_loader, prog->type, prog->name,
license, insns, insns_cnt, &load_attr,
@@ -11730,6 +11732,7 @@ struct bpf_link *bpf_program__attach_usdt(const struct bpf_program *prog,
struct bpf_object *obj = prog->obj;
struct bpf_link *link;
__u64 usdt_cookie;
+ bool uprobe_multi;
int err;
if (!OPTS_VALID(opts, bpf_uprobe_opts))
@@ -11766,8 +11769,10 @@ struct bpf_link *bpf_program__attach_usdt(const struct bpf_program *prog,
}
usdt_cookie = OPTS_GET(opts, usdt_cookie, 0);
+ uprobe_multi = OPTS_GET(opts, uprobe_multi, 0);
link = usdt_manager_attach_usdt(obj->usdt_man, prog, pid, binary_path,
- usdt_provider, usdt_name, usdt_cookie);
+ usdt_provider, usdt_name, usdt_cookie,
+ uprobe_multi);
err = libbpf_get_error(link);
if (err)
return libbpf_err_ptr(err);
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 921ab2a94cec..025feb21c2ec 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -673,6 +673,8 @@ struct bpf_usdt_opts {
size_t sz;
/* custom user-provided value accessible through usdt_cookie() */
__u64 usdt_cookie;
+ /* use uprobe_multi link */
+ bool uprobe_multi;
size_t :0;
};
#define bpf_usdt_opts__last_field usdt_cookie
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index e4d05662a96c..5d5f61d0bcfb 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -567,7 +567,7 @@ struct bpf_link * usdt_manager_attach_usdt(struct usdt_manager *man,
const struct bpf_program *prog,
pid_t pid, const char *path,
const char *usdt_provider, const char *usdt_name,
- __u64 usdt_cookie);
+ __u64 usdt_cookie, bool uprobe_multi);
static inline bool is_pow_of_2(size_t x)
{
diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c
index b8402e3f9eb2..f55dbd47d29e 100644
--- a/tools/lib/bpf/usdt.c
+++ b/tools/lib/bpf/usdt.c
@@ -803,11 +803,20 @@ struct bpf_link_usdt {
size_t spec_cnt;
int *spec_ids;
+ bool has_uprobe_multi;
+
size_t uprobe_cnt;
struct {
long abs_ip;
struct bpf_link *link;
} *uprobes;
+ struct {
+ char **paths;
+ unsigned long *offsets;
+ unsigned long *ref_ctr_offsets;
+ __u64 *cookies;
+ struct bpf_link *link;
+ } uprobe_multi;
};
static int bpf_link_usdt_detach(struct bpf_link *link)
@@ -816,19 +825,23 @@ static int bpf_link_usdt_detach(struct bpf_link *link)
struct usdt_manager *man = usdt_link->usdt_man;
int i;
- for (i = 0; i < usdt_link->uprobe_cnt; i++) {
- /* detach underlying uprobe link */
- bpf_link__destroy(usdt_link->uprobes[i].link);
- /* there is no need to update specs map because it will be
- * unconditionally overwritten on subsequent USDT attaches,
- * but if BPF cookies are not used we need to remove entry
- * from ip_to_spec_id map, otherwise we'll run into false
- * conflicting IP errors
- */
- if (!man->has_bpf_cookie) {
- /* not much we can do about errors here */
- (void)bpf_map_delete_elem(bpf_map__fd(man->ip_to_spec_id_map),
- &usdt_link->uprobes[i].abs_ip);
+ if (usdt_link->has_uprobe_multi) {
+ bpf_link__destroy(usdt_link->uprobe_multi.link);
+ } else {
+ for (i = 0; i < usdt_link->uprobe_cnt; i++) {
+ /* detach underlying uprobe link */
+ bpf_link__destroy(usdt_link->uprobes[i].link);
+ /* there is no need to update specs map because it will be
+ * unconditionally overwritten on subsequent USDT attaches,
+ * but if BPF cookies are not used we need to remove entry
+ * from ip_to_spec_id map, otherwise we'll run into false
+ * conflicting IP errors
+ */
+ if (!man->has_bpf_cookie) {
+ /* not much we can do about errors here */
+ (void)bpf_map_delete_elem(bpf_map__fd(man->ip_to_spec_id_map),
+ &usdt_link->uprobes[i].abs_ip);
+ }
}
}
@@ -868,9 +881,16 @@ static void bpf_link_usdt_dealloc(struct bpf_link *link)
{
struct bpf_link_usdt *usdt_link = container_of(link, struct bpf_link_usdt, link);
- free(usdt_link->spec_ids);
- free(usdt_link->uprobes);
- free(usdt_link);
+ if (usdt_link->has_uprobe_multi) {
+ free(usdt_link->uprobe_multi.paths);
+ free(usdt_link->uprobe_multi.offsets);
+ free(usdt_link->uprobe_multi.ref_ctr_offsets);
+ free(usdt_link->uprobe_multi.cookies);
+ } else {
+ free(usdt_link->spec_ids);
+ free(usdt_link->uprobes);
+ free(usdt_link);
+ }
}
static size_t specs_hash_fn(long key, void *ctx)
@@ -941,16 +961,22 @@ static int allocate_spec_id(struct usdt_manager *man, struct hashmap *specs_hash
struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct bpf_program *prog,
pid_t pid, const char *path,
const char *usdt_provider, const char *usdt_name,
- __u64 usdt_cookie)
+ __u64 usdt_cookie, bool uprobe_multi)
{
+ LIBBPF_OPTS(bpf_uprobe_multi_opts, opts_multi);
int i, fd, err, spec_map_fd, ip_map_fd;
LIBBPF_OPTS(bpf_uprobe_opts, opts);
struct hashmap *specs_hash = NULL;
struct bpf_link_usdt *link = NULL;
struct usdt_target *targets = NULL;
+ struct bpf_link *uprobe_link;
size_t target_cnt;
Elf *elf;
+ /* The uprobe_multi link does not have pid filter. */
+ if (uprobe_multi && pid >= 0)
+ return libbpf_err_ptr(-EINVAL);
+
spec_map_fd = bpf_map__fd(man->specs_map);
ip_map_fd = bpf_map__fd(man->ip_to_spec_id_map);
@@ -1001,19 +1027,32 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
goto err_out;
}
+ link->has_uprobe_multi = uprobe_multi;
link->usdt_man = man;
link->link.detach = &bpf_link_usdt_detach;
link->link.dealloc = &bpf_link_usdt_dealloc;
- link->uprobes = calloc(target_cnt, sizeof(*link->uprobes));
- if (!link->uprobes) {
- err = -ENOMEM;
- goto err_out;
+ if (uprobe_multi) {
+ link->uprobe_multi.paths = calloc(target_cnt, sizeof(*link->uprobe_multi.paths));
+ link->uprobe_multi.offsets = calloc(target_cnt, sizeof(*link->uprobe_multi.offsets));
+ link->uprobe_multi.ref_ctr_offsets = calloc(target_cnt, sizeof(*link->uprobe_multi.ref_ctr_offsets));
+ link->uprobe_multi.cookies = calloc(target_cnt, sizeof(*link->uprobe_multi.cookies));
+
+ if (!link->uprobe_multi.paths || !link->uprobe_multi.offsets ||
+ !link->uprobe_multi.ref_ctr_offsets || !link->uprobe_multi.cookies) {
+ err = -ENOMEM;
+ goto err_out;
+ }
+ } else {
+ link->uprobes = calloc(target_cnt, sizeof(*link->uprobes));
+ if (!link->uprobes) {
+ err = -ENOMEM;
+ goto err_out;
+ }
}
for (i = 0; i < target_cnt; i++) {
struct usdt_target *target = &targets[i];
- struct bpf_link *uprobe_link;
bool is_new;
int spec_id;
@@ -1049,20 +1088,44 @@ struct bpf_link *usdt_manager_attach_usdt(struct usdt_manager *man, const struct
goto err_out;
}
- opts.ref_ctr_offset = target->sema_off;
- opts.bpf_cookie = man->has_bpf_cookie ? spec_id : 0;
- uprobe_link = bpf_program__attach_uprobe_opts(prog, pid, path,
- target->rel_ip, &opts);
+ if (uprobe_multi) {
+ link->uprobe_multi.paths[i] = (char *) path;
+ link->uprobe_multi.offsets[i] = target->rel_ip;
+ link->uprobe_multi.ref_ctr_offsets[i] = target->sema_off;
+ link->uprobe_multi.cookies[i] = spec_id;
+ } else {
+ opts.ref_ctr_offset = target->sema_off;
+ opts.bpf_cookie = man->has_bpf_cookie ? spec_id : 0;
+ uprobe_link = bpf_program__attach_uprobe_opts(prog, pid, path,
+ target->rel_ip, &opts);
+ err = libbpf_get_error(uprobe_link);
+ if (err) {
+ pr_warn("usdt: failed to attach uprobe #%d for '%s:%s' in '%s': %d\n",
+ i, usdt_provider, usdt_name, path, err);
+ goto err_out;
+ }
+
+ link->uprobes[i].link = uprobe_link;
+ link->uprobes[i].abs_ip = target->abs_ip;
+ link->uprobe_cnt++;
+ }
+ }
+
+ if (uprobe_multi) {
+ opts_multi.cnt = target_cnt;
+ opts_multi.paths = (const char **) link->uprobe_multi.paths;
+ opts_multi.offsets = link->uprobe_multi.offsets;
+ opts_multi.ref_ctr_offsets = link->uprobe_multi.ref_ctr_offsets;
+ opts_multi.cookies = link->uprobe_multi.cookies;
+
+ uprobe_link = bpf_program__attach_uprobe_multi_opts(prog, NULL, NULL, &opts_multi);
err = libbpf_get_error(uprobe_link);
if (err) {
- pr_warn("usdt: failed to attach uprobe #%d for '%s:%s' in '%s': %d\n",
- i, usdt_provider, usdt_name, path, err);
+ pr_warn("usdt: failed to attach uprobe multi for '%s:%s' in '%s': %d\n",
+ usdt_provider, usdt_name, path, err);
goto err_out;
}
-
- link->uprobes[i].link = uprobe_link;
- link->uprobes[i].abs_ip = target->abs_ip;
- link->uprobe_cnt++;
+ link->uprobe_multi.link = uprobe_link;
}
free(targets);
--
2.40.0
next prev parent reply other threads:[~2023-04-24 16:07 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-24 16:04 [RFC/PATCH bpf-next 00/20] bpf: Add multi uprobe link Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 01/20] " Jiri Olsa
2023-04-24 22:11 ` Alexei Starovoitov
2023-04-25 9:54 ` Jiri Olsa
2023-04-26 19:01 ` Andrii Nakryiko
2023-04-27 13:15 ` Jiri Olsa
2023-04-25 23:56 ` Yonghong Song
2023-04-26 7:37 ` Jiri Olsa
2023-04-26 19:00 ` Andrii Nakryiko
2023-04-27 13:14 ` Jiri Olsa
2023-04-26 19:17 ` Andrii Nakryiko
2023-04-27 13:15 ` Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 02/20] bpf: Add cookies support for uprobe_multi link Jiri Olsa
2023-04-26 0:03 ` Yonghong Song
2023-04-26 19:13 ` Andrii Nakryiko
2023-04-27 12:58 ` Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 03/20] bpf: Add bpf_get_func_ip helper support for uprobe link Jiri Olsa
2023-04-26 19:11 ` Andrii Nakryiko
2023-04-27 12:45 ` Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 04/20] libbpf: Update uapi bpf.h tools header Jiri Olsa
2023-04-26 19:14 ` Andrii Nakryiko
2023-04-27 12:58 ` Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 05/20] libbpf: Add uprobe_multi attach type and link names Jiri Olsa
2023-04-26 19:14 ` Andrii Nakryiko
2023-04-24 16:04 ` [RFC/PATCH bpf-next 06/20] libbpf: Factor elf_for_each_symbol function Jiri Olsa
2023-04-26 19:27 ` Andrii Nakryiko
2023-04-27 13:23 ` Jiri Olsa
2023-04-27 22:28 ` Andrii Nakryiko
2023-04-24 16:04 ` [RFC/PATCH bpf-next 07/20] libbpf: Add elf_find_multi_func_offset function Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 08/20] libbpf: Add elf_find_patern_func_offset function Jiri Olsa
2023-04-26 19:24 ` Andrii Nakryiko
2023-04-27 13:21 ` Jiri Olsa
2023-04-27 22:29 ` Andrii Nakryiko
2023-04-24 16:04 ` [RFC/PATCH bpf-next 09/20] libbpf: Add bpf_link_create support for multi uprobes Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 10/20] libbpf: Add bpf_program__attach_uprobe_multi_opts function Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 11/20] libbpf: Add support for uprobe.multi/uprobe.multi program sections Jiri Olsa
2023-04-26 19:31 ` Andrii Nakryiko
2023-04-24 16:04 ` Jiri Olsa [this message]
2023-04-26 19:32 ` [RFC/PATCH bpf-next 12/20] libbpf: Add uprobe multi link support to bpf_program__attach_usdt Andrii Nakryiko
2023-04-24 16:04 ` [RFC/PATCH bpf-next 13/20] selftests/bpf: Add uprobe_multi skel test Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 14/20] selftests/bpf: Add uprobe_multi api test Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 15/20] selftests/bpf: Add uprobe_multi link test Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 16/20] selftests/bpf: Add uprobe_multi test program Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 17/20] selftests/bpf: Add uprobe_multi bench test Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 18/20] selftests/bpf: Add usdt_multi test program Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 19/20] selftests/bpf: Add usdt_multi bench test Jiri Olsa
2023-04-24 16:04 ` [RFC/PATCH bpf-next 20/20] selftests/bpf: Add uprobe_multi cookie test Jiri Olsa
2023-04-26 19:09 ` [RFC/PATCH bpf-next 00/20] bpf: Add multi uprobe link Andrii Nakryiko
2023-04-27 12:44 ` Jiri Olsa
2023-04-27 22:24 ` Andrii Nakryiko
2023-04-28 10:55 ` Jiri Olsa
2023-04-28 21:19 ` Andrii Nakryiko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230424160447.2005755-13-jolsa@kernel.org \
--to=jolsa@kernel.org \
--cc=acme@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=haoluo@google.com \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@chromium.org \
--cc=sdf@google.com \
--cc=songliubraving@fb.com \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox