Adding support to attach unique generic uprobe by adding the 'unique' bool flag to struct bpf_uprobe_opts.
Signed-off-by: Jiri Olsa <jo...@kernel.org> --- tools/lib/bpf/libbpf.c | 29 ++++++++++++++++++++++++----- tools/lib/bpf/libbpf.h | 4 +++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 1f613a5f95b6..aac2bd4fb95e 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -11045,11 +11045,19 @@ static int determine_uprobe_retprobe_bit(void) return parse_uint_from_file(file, "config:%d\n"); } +static int determine_uprobe_unique_bit(void) +{ + const char *file = "/sys/bus/event_source/devices/uprobe/format/unique"; + + return parse_uint_from_file(file, "config:%d\n"); +} + #define PERF_UPROBE_REF_CTR_OFFSET_BITS 32 #define PERF_UPROBE_REF_CTR_OFFSET_SHIFT 32 static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, - uint64_t offset, int pid, size_t ref_ctr_off) + uint64_t offset, int pid, size_t ref_ctr_off, + bool unique) { const size_t attr_sz = sizeof(struct perf_event_attr); struct perf_event_attr attr; @@ -11080,6 +11088,16 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, } attr.config |= 1 << bit; } + if (uprobe && unique) { + int bit = determine_uprobe_unique_bit(); + + if (bit < 0) { + pr_warn("failed to determine uprobe unique bit: %s\n", + errstr(bit)); + return bit; + } + attr.config |= 1 << bit; + } attr.size = attr_sz; attr.type = type; attr.config |= (__u64)ref_ctr_off << PERF_UPROBE_REF_CTR_OFFSET_SHIFT; @@ -11286,7 +11304,7 @@ int probe_kern_syscall_wrapper(int token_fd) if (determine_kprobe_perf_type() >= 0) { int pfd; - pfd = perf_event_open_probe(false, false, syscall_name, 0, getpid(), 0); + pfd = perf_event_open_probe(false, false, syscall_name, 0, getpid(), 0, false); if (pfd >= 0) close(pfd); @@ -11348,7 +11366,7 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog, if (!legacy) { pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name, offset, - -1 /* pid */, 0 /* ref_ctr_off */); + -1 /* pid */, 0 /* ref_ctr_off */, false /* unique */); } else { char probe_name[MAX_EVENT_NAME_LEN]; @@ -12251,7 +12269,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid, struct bpf_link *link; size_t ref_ctr_off; int pfd, err; - bool retprobe, legacy; + bool retprobe, legacy, unique; const char *func_name; if (!OPTS_VALID(opts, bpf_uprobe_opts)) @@ -12261,6 +12279,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid, retprobe = OPTS_GET(opts, retprobe, false); ref_ctr_off = OPTS_GET(opts, ref_ctr_offset, 0); pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); + unique = OPTS_GET(opts, unique, false); if (!binary_path) return libbpf_err_ptr(-EINVAL); @@ -12321,7 +12340,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid, if (!legacy) { pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path, - func_offset, pid, ref_ctr_off); + func_offset, pid, ref_ctr_off, unique); } else { char probe_name[MAX_EVENT_NAME_LEN]; diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 13a10299331b..0a38dee1d9c1 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -701,9 +701,11 @@ struct bpf_uprobe_opts { const char *func_name; /* uprobe attach mode */ enum probe_attach_mode attach_mode; + /* create unique uprobe */ + bool unique; size_t :0; }; -#define bpf_uprobe_opts__last_field attach_mode +#define bpf_uprobe_opts__last_field unique /** * @brief **bpf_program__attach_uprobe()** attaches a BPF program -- 2.51.0