Adding support to attach program in uprobe session mode
with bpf_program__attach_uprobe_multi function.

Adding session bool to bpf_uprobe_multi_opts struct that allows
to load and attach the bpf program via uprobe session.
the attachment to create uprobe multi session.

Also adding new program loader section that allows:
SEC("uprobe.session/bpf_fentry_test*")

and loads/attaches uprobe program as uprobe session.

Signed-off-by: Jiri Olsa <jo...@kernel.org>
---
 tools/lib/bpf/bpf.c    |  1 +
 tools/lib/bpf/libbpf.c | 50 ++++++++++++++++++++++++++++++++++++++++--
 tools/lib/bpf/libbpf.h |  4 +++-
 3 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 2a4c71501a17..becdfa701c75 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -776,6 +776,7 @@ int bpf_link_create(int prog_fd, int target_fd,
                        return libbpf_err(-EINVAL);
                break;
        case BPF_TRACE_UPROBE_MULTI:
+       case BPF_TRACE_UPROBE_SESSION:
                attr.link_create.uprobe_multi.flags = OPTS_GET(opts, 
uprobe_multi.flags, 0);
                attr.link_create.uprobe_multi.cnt = OPTS_GET(opts, 
uprobe_multi.cnt, 0);
                attr.link_create.uprobe_multi.path = ptr_to_u64(OPTS_GET(opts, 
uprobe_multi.path, 0));
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index d1627a2ca30b..a0044448a708 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9328,6 +9328,7 @@ static int attach_trace(const struct bpf_program *prog, 
long cookie, struct bpf_
 static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, 
struct bpf_link **link);
 static int attach_kprobe_session(const struct bpf_program *prog, long cookie, 
struct bpf_link **link);
 static int attach_uprobe_multi(const struct bpf_program *prog, long cookie, 
struct bpf_link **link);
+static int attach_uprobe_session(const struct bpf_program *prog, long cookie, 
struct bpf_link **link);
 static int attach_lsm(const struct bpf_program *prog, long cookie, struct 
bpf_link **link);
 static int attach_iter(const struct bpf_program *prog, long cookie, struct 
bpf_link **link);
 
@@ -9346,6 +9347,7 @@ static const struct bpf_sec_def section_defs[] = {
        SEC_DEF("kprobe.session+",      KPROBE, BPF_TRACE_KPROBE_SESSION, 
SEC_NONE, attach_kprobe_session),
        SEC_DEF("uprobe.multi+",        KPROBE, BPF_TRACE_UPROBE_MULTI, 
SEC_NONE, attach_uprobe_multi),
        SEC_DEF("uretprobe.multi+",     KPROBE, BPF_TRACE_UPROBE_MULTI, 
SEC_NONE, attach_uprobe_multi),
+       SEC_DEF("uprobe.session+",      KPROBE, BPF_TRACE_UPROBE_SESSION, 
SEC_NONE, attach_uprobe_session),
        SEC_DEF("uprobe.multi.s+",      KPROBE, BPF_TRACE_UPROBE_MULTI, 
SEC_SLEEPABLE, attach_uprobe_multi),
        SEC_DEF("uretprobe.multi.s+",   KPROBE, BPF_TRACE_UPROBE_MULTI, 
SEC_SLEEPABLE, attach_uprobe_multi),
        SEC_DEF("ksyscall+",            KPROBE, 0, SEC_NONE, attach_ksyscall),
@@ -11682,6 +11684,40 @@ static int attach_uprobe_multi(const struct 
bpf_program *prog, long cookie, stru
        return ret;
 }
 
+static int attach_uprobe_session(const struct bpf_program *prog, long cookie, 
struct bpf_link **link)
+{
+       char *binary_path = NULL, *func_name = NULL;
+       LIBBPF_OPTS(bpf_uprobe_multi_opts, opts,
+               .session = true,
+       );
+       int n, ret = -EINVAL;
+       const char *spec;
+
+       *link = NULL;
+
+       spec = prog->sec_name + sizeof("uprobe.session/") - 1;
+       n = sscanf(spec, "%m[^:]:%m[^\n]",
+                  &binary_path, &func_name);
+
+       switch (n) {
+       case 1:
+               /* but auto-attach is impossible. */
+               ret = 0;
+               break;
+       case 2:
+               *link = bpf_program__attach_uprobe_multi(prog, -1, binary_path, 
func_name, &opts);
+               ret = *link ? 0 : -errno;
+               break;
+       default:
+               pr_warn("prog '%s': invalid format of section definition 
'%s'\n", prog->name,
+                       prog->sec_name);
+               break;
+       }
+       free(binary_path);
+       free(func_name);
+       return ret;
+}
+
 static void gen_uprobe_legacy_event_name(char *buf, size_t buf_sz,
                                         const char *binary_path, uint64_t 
offset)
 {
@@ -11916,10 +11952,12 @@ bpf_program__attach_uprobe_multi(const struct 
bpf_program *prog,
        const unsigned long *ref_ctr_offsets = NULL, *offsets = NULL;
        LIBBPF_OPTS(bpf_link_create_opts, lopts);
        unsigned long *resolved_offsets = NULL;
+       enum bpf_attach_type attach_type;
        int err = 0, link_fd, prog_fd;
        struct bpf_link *link = NULL;
        char errmsg[STRERR_BUFSIZE];
        char full_path[PATH_MAX];
+       bool retprobe, session;
        const __u64 *cookies;
        const char **syms;
        size_t cnt;
@@ -11990,12 +12028,20 @@ bpf_program__attach_uprobe_multi(const struct 
bpf_program *prog,
                offsets = resolved_offsets;
        }
 
+       retprobe = OPTS_GET(opts, retprobe, false);
+       session  = OPTS_GET(opts, session, false);
+
+       if (retprobe && session)
+               return libbpf_err_ptr(-EINVAL);
+
+       attach_type = session ? BPF_TRACE_UPROBE_SESSION : 
BPF_TRACE_UPROBE_MULTI;
+
        lopts.uprobe_multi.path = path;
        lopts.uprobe_multi.offsets = offsets;
        lopts.uprobe_multi.ref_ctr_offsets = ref_ctr_offsets;
        lopts.uprobe_multi.cookies = cookies;
        lopts.uprobe_multi.cnt = cnt;
-       lopts.uprobe_multi.flags = OPTS_GET(opts, retprobe, false) ? 
BPF_F_UPROBE_MULTI_RETURN : 0;
+       lopts.uprobe_multi.flags = retprobe ? BPF_F_UPROBE_MULTI_RETURN : 0;
 
        if (pid == 0)
                pid = getpid();
@@ -12009,7 +12055,7 @@ bpf_program__attach_uprobe_multi(const struct 
bpf_program *prog,
        }
        link->detach = &bpf_link__detach_fd;
 
-       link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &lopts);
+       link_fd = bpf_link_create(prog_fd, 0, attach_type, &lopts);
        if (link_fd < 0) {
                err = -errno;
                pr_warn("prog '%s': failed to attach multi-uprobe: %s\n",
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 26e4e35528c5..04cdb38f527f 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -569,10 +569,12 @@ struct bpf_uprobe_multi_opts {
        size_t cnt;
        /* create return uprobes */
        bool retprobe;
+       /* create session kprobes */
+       bool session;
        size_t :0;
 };
 
-#define bpf_uprobe_multi_opts__last_field retprobe
+#define bpf_uprobe_multi_opts__last_field session
 
 /**
  * @brief **bpf_program__attach_uprobe_multi()** attaches a BPF program
-- 
2.45.1


Reply via email to