libbpf: Add bpf_program__attach_uprobe_multi function
Adding bpf_program__attach_uprobe_multi function that allows to attach multiple uprobes with uprobe_multi link. The user can specify uprobes with direct arguments: binary_path/func_pattern/pid or with struct bpf_uprobe_multi_opts opts argument fields: const char **syms; const unsigned long *offsets; const unsigned long *ref_ctr_offsets; const __u64 *cookies; User can specify 2 mutually exclusive set of inputs: 1) use only path/func_pattern/pid arguments 2) use path/pid with allowed combinations of: syms/offsets/ref_ctr_offsets/cookies/cnt - syms and offsets are mutually exclusive - ref_ctr_offsets and cookies are optional Any other usage results in error. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/r/20230809083440.3209381-15-jolsa@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
5054a303f8
commit
3140cf121c
|
@ -11146,6 +11146,120 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
struct bpf_link *
|
||||
bpf_program__attach_uprobe_multi(const struct bpf_program *prog,
|
||||
pid_t pid,
|
||||
const char *path,
|
||||
const char *func_pattern,
|
||||
const struct bpf_uprobe_multi_opts *opts)
|
||||
{
|
||||
const unsigned long *ref_ctr_offsets = NULL, *offsets = NULL;
|
||||
LIBBPF_OPTS(bpf_link_create_opts, lopts);
|
||||
unsigned long *resolved_offsets = NULL;
|
||||
int err = 0, link_fd, prog_fd;
|
||||
struct bpf_link *link = NULL;
|
||||
char errmsg[STRERR_BUFSIZE];
|
||||
char full_path[PATH_MAX];
|
||||
const __u64 *cookies;
|
||||
const char **syms;
|
||||
size_t cnt;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_uprobe_multi_opts))
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
syms = OPTS_GET(opts, syms, NULL);
|
||||
offsets = OPTS_GET(opts, offsets, NULL);
|
||||
ref_ctr_offsets = OPTS_GET(opts, ref_ctr_offsets, NULL);
|
||||
cookies = OPTS_GET(opts, cookies, NULL);
|
||||
cnt = OPTS_GET(opts, cnt, 0);
|
||||
|
||||
/*
|
||||
* User can specify 2 mutually exclusive set of inputs:
|
||||
*
|
||||
* 1) use only path/func_pattern/pid arguments
|
||||
*
|
||||
* 2) use path/pid with allowed combinations of:
|
||||
* syms/offsets/ref_ctr_offsets/cookies/cnt
|
||||
*
|
||||
* - syms and offsets are mutually exclusive
|
||||
* - ref_ctr_offsets and cookies are optional
|
||||
*
|
||||
* Any other usage results in error.
|
||||
*/
|
||||
|
||||
if (!path)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
if (!func_pattern && cnt == 0)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
if (func_pattern) {
|
||||
if (syms || offsets || ref_ctr_offsets || cookies || cnt)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
} else {
|
||||
if (!!syms == !!offsets)
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
}
|
||||
|
||||
if (func_pattern) {
|
||||
if (!strchr(path, '/')) {
|
||||
err = resolve_full_path(path, full_path, sizeof(full_path));
|
||||
if (err) {
|
||||
pr_warn("prog '%s': failed to resolve full path for '%s': %d\n",
|
||||
prog->name, path, err);
|
||||
return libbpf_err_ptr(err);
|
||||
}
|
||||
path = full_path;
|
||||
}
|
||||
|
||||
err = elf_resolve_pattern_offsets(path, func_pattern,
|
||||
&resolved_offsets, &cnt);
|
||||
if (err < 0)
|
||||
return libbpf_err_ptr(err);
|
||||
offsets = resolved_offsets;
|
||||
} else if (syms) {
|
||||
err = elf_resolve_syms_offsets(path, cnt, syms, &resolved_offsets);
|
||||
if (err < 0)
|
||||
return libbpf_err_ptr(err);
|
||||
offsets = resolved_offsets;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (pid == 0)
|
||||
pid = getpid();
|
||||
if (pid > 0)
|
||||
lopts.uprobe_multi.pid = pid;
|
||||
|
||||
link = calloc(1, sizeof(*link));
|
||||
if (!link) {
|
||||
err = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
link->detach = &bpf_link__detach_fd;
|
||||
|
||||
prog_fd = bpf_program__fd(prog);
|
||||
link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &lopts);
|
||||
if (link_fd < 0) {
|
||||
err = -errno;
|
||||
pr_warn("prog '%s': failed to attach multi-uprobe: %s\n",
|
||||
prog->name, libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
|
||||
goto error;
|
||||
}
|
||||
link->fd = link_fd;
|
||||
free(resolved_offsets);
|
||||
return link;
|
||||
|
||||
error:
|
||||
free(resolved_offsets);
|
||||
free(link);
|
||||
return libbpf_err_ptr(err);
|
||||
}
|
||||
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
|
||||
const char *binary_path, size_t func_offset,
|
||||
|
|
|
@ -529,6 +529,57 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
|
|||
const char *pattern,
|
||||
const struct bpf_kprobe_multi_opts *opts);
|
||||
|
||||
struct bpf_uprobe_multi_opts {
|
||||
/* size of this struct, for forward/backward compatibility */
|
||||
size_t sz;
|
||||
/* array of function symbols to attach to */
|
||||
const char **syms;
|
||||
/* array of function addresses to attach to */
|
||||
const unsigned long *offsets;
|
||||
/* optional, array of associated ref counter offsets */
|
||||
const unsigned long *ref_ctr_offsets;
|
||||
/* optional, array of associated BPF cookies */
|
||||
const __u64 *cookies;
|
||||
/* number of elements in syms/addrs/cookies arrays */
|
||||
size_t cnt;
|
||||
/* create return uprobes */
|
||||
bool retprobe;
|
||||
size_t :0;
|
||||
};
|
||||
|
||||
#define bpf_uprobe_multi_opts__last_field retprobe
|
||||
|
||||
/**
|
||||
* @brief **bpf_program__attach_uprobe_multi()** attaches a BPF program
|
||||
* to multiple uprobes with uprobe_multi link.
|
||||
*
|
||||
* User can specify 2 mutually exclusive set of inputs:
|
||||
*
|
||||
* 1) use only path/func_pattern/pid arguments
|
||||
*
|
||||
* 2) use path/pid with allowed combinations of
|
||||
* syms/offsets/ref_ctr_offsets/cookies/cnt
|
||||
*
|
||||
* - syms and offsets are mutually exclusive
|
||||
* - ref_ctr_offsets and cookies are optional
|
||||
*
|
||||
*
|
||||
* @param prog BPF program to attach
|
||||
* @param pid Process ID to attach the uprobe to, 0 for self (own process),
|
||||
* -1 for all processes
|
||||
* @param binary_path Path to binary
|
||||
* @param func_pattern Regular expression to specify functions to attach
|
||||
* BPF program to
|
||||
* @param opts Additional options (see **struct bpf_uprobe_multi_opts**)
|
||||
* @return 0, on success; negative error code, otherwise
|
||||
*/
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_uprobe_multi(const struct bpf_program *prog,
|
||||
pid_t pid,
|
||||
const char *binary_path,
|
||||
const char *func_pattern,
|
||||
const struct bpf_uprobe_multi_opts *opts);
|
||||
|
||||
struct bpf_ksyscall_opts {
|
||||
/* size of this struct, for forward/backward compatibility */
|
||||
size_t sz;
|
||||
|
|
|
@ -398,4 +398,5 @@ LIBBPF_1.3.0 {
|
|||
bpf_prog_detach_opts;
|
||||
bpf_program__attach_netfilter;
|
||||
bpf_program__attach_tcx;
|
||||
bpf_program__attach_uprobe_multi;
|
||||
} LIBBPF_1.2.0;
|
||||
|
|
Loading…
Reference in New Issue