mirror of
https://github.com/netdata/libbpf.git
synced 2026-04-01 22:29:06 +08:00
libbpf: Add bpf_cookie to perf_event, kprobe, uprobe, and tp attach APIs
Wire through bpf_cookie for all attach APIs that use perf_event_open under the
hood:
- for kprobes, extend existing bpf_kprobe_opts with bpf_cookie field;
- for perf_event, uprobe, and tracepoint APIs, add their _opts variants and
pass bpf_cookie through opts.
For kernel that don't support BPF_LINK_CREATE for perf_events, and thus
bpf_cookie is not supported either, return error and log warning for user.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20210815070609.987780-12-andrii@kernel.org
This commit is contained in:
committed by
Andrii Nakryiko
parent
a3f8c5a306
commit
91259bc676
78
src/libbpf.c
78
src/libbpf.c
@@ -9014,12 +9014,16 @@ static void bpf_link_perf_dealloc(struct bpf_link *link)
|
||||
free(perf_link);
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pfd)
|
||||
struct bpf_link *bpf_program__attach_perf_event_opts(struct bpf_program *prog, int pfd,
|
||||
const struct bpf_perf_event_opts *opts)
|
||||
{
|
||||
char errmsg[STRERR_BUFSIZE];
|
||||
struct bpf_link_perf *link;
|
||||
int prog_fd, link_fd = -1, err;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_perf_event_opts))
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
if (pfd < 0) {
|
||||
pr_warn("prog '%s': invalid perf event FD %d\n",
|
||||
prog->name, pfd);
|
||||
@@ -9040,7 +9044,10 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pf
|
||||
link->perf_event_fd = pfd;
|
||||
|
||||
if (kernel_supports(prog->obj, FEAT_PERF_LINK)) {
|
||||
link_fd = bpf_link_create(prog_fd, pfd, BPF_PERF_EVENT, NULL);
|
||||
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts,
|
||||
.perf_event.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0));
|
||||
|
||||
link_fd = bpf_link_create(prog_fd, pfd, BPF_PERF_EVENT, &link_opts);
|
||||
if (link_fd < 0) {
|
||||
err = -errno;
|
||||
pr_warn("prog '%s': failed to create BPF link for perf_event FD %d: %d (%s)\n",
|
||||
@@ -9050,6 +9057,12 @@ struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pf
|
||||
}
|
||||
link->link.fd = link_fd;
|
||||
} else {
|
||||
if (OPTS_GET(opts, bpf_cookie, 0)) {
|
||||
pr_warn("prog '%s': user context value is not supported\n", prog->name);
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (ioctl(pfd, PERF_EVENT_IOC_SET_BPF, prog_fd) < 0) {
|
||||
err = -errno;
|
||||
pr_warn("prog '%s': failed to attach to perf_event FD %d: %s\n",
|
||||
@@ -9076,6 +9089,11 @@ err_out:
|
||||
return libbpf_err_ptr(err);
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_perf_event(struct bpf_program *prog, int pfd)
|
||||
{
|
||||
return bpf_program__attach_perf_event_opts(prog, pfd, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is expected to parse integer in the range of [0, 2^31-1] from
|
||||
* given file using scanf format string fmt. If actual parsed value is
|
||||
@@ -9184,8 +9202,9 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
|
||||
struct bpf_link *
|
||||
bpf_program__attach_kprobe_opts(struct bpf_program *prog,
|
||||
const char *func_name,
|
||||
struct bpf_kprobe_opts *opts)
|
||||
const struct bpf_kprobe_opts *opts)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
|
||||
char errmsg[STRERR_BUFSIZE];
|
||||
struct bpf_link *link;
|
||||
unsigned long offset;
|
||||
@@ -9197,6 +9216,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog,
|
||||
|
||||
retprobe = OPTS_GET(opts, retprobe, false);
|
||||
offset = OPTS_GET(opts, offset, 0);
|
||||
pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
|
||||
|
||||
pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name,
|
||||
offset, -1 /* pid */);
|
||||
@@ -9206,7 +9226,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog,
|
||||
libbpf_strerror_r(pfd, errmsg, sizeof(errmsg)));
|
||||
return libbpf_err_ptr(pfd);
|
||||
}
|
||||
link = bpf_program__attach_perf_event(prog, pfd);
|
||||
link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts);
|
||||
err = libbpf_get_error(link);
|
||||
if (err) {
|
||||
close(pfd);
|
||||
@@ -9261,14 +9281,22 @@ static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec,
|
||||
return link;
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,
|
||||
bool retprobe, pid_t pid,
|
||||
const char *binary_path,
|
||||
size_t func_offset)
|
||||
LIBBPF_API struct bpf_link *
|
||||
bpf_program__attach_uprobe_opts(struct bpf_program *prog, pid_t pid,
|
||||
const char *binary_path, size_t func_offset,
|
||||
const struct bpf_uprobe_opts *opts)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
|
||||
char errmsg[STRERR_BUFSIZE];
|
||||
struct bpf_link *link;
|
||||
int pfd, err;
|
||||
bool retprobe;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_uprobe_opts))
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
retprobe = OPTS_GET(opts, retprobe, false);
|
||||
pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
|
||||
|
||||
pfd = perf_event_open_probe(true /* uprobe */, retprobe,
|
||||
binary_path, func_offset, pid);
|
||||
@@ -9279,7 +9307,7 @@ struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,
|
||||
libbpf_strerror_r(pfd, errmsg, sizeof(errmsg)));
|
||||
return libbpf_err_ptr(pfd);
|
||||
}
|
||||
link = bpf_program__attach_perf_event(prog, pfd);
|
||||
link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts);
|
||||
err = libbpf_get_error(link);
|
||||
if (err) {
|
||||
close(pfd);
|
||||
@@ -9292,6 +9320,16 @@ struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,
|
||||
return link;
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,
|
||||
bool retprobe, pid_t pid,
|
||||
const char *binary_path,
|
||||
size_t func_offset)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, opts, .retprobe = retprobe);
|
||||
|
||||
return bpf_program__attach_uprobe_opts(prog, pid, binary_path, func_offset, &opts);
|
||||
}
|
||||
|
||||
static int determine_tracepoint_id(const char *tp_category,
|
||||
const char *tp_name)
|
||||
{
|
||||
@@ -9342,14 +9380,21 @@ static int perf_event_open_tracepoint(const char *tp_category,
|
||||
return pfd;
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog,
|
||||
const char *tp_category,
|
||||
const char *tp_name)
|
||||
struct bpf_link *bpf_program__attach_tracepoint_opts(struct bpf_program *prog,
|
||||
const char *tp_category,
|
||||
const char *tp_name,
|
||||
const struct bpf_tracepoint_opts *opts)
|
||||
{
|
||||
DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
|
||||
char errmsg[STRERR_BUFSIZE];
|
||||
struct bpf_link *link;
|
||||
int pfd, err;
|
||||
|
||||
if (!OPTS_VALID(opts, bpf_tracepoint_opts))
|
||||
return libbpf_err_ptr(-EINVAL);
|
||||
|
||||
pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
|
||||
|
||||
pfd = perf_event_open_tracepoint(tp_category, tp_name);
|
||||
if (pfd < 0) {
|
||||
pr_warn("prog '%s': failed to create tracepoint '%s/%s' perf event: %s\n",
|
||||
@@ -9357,7 +9402,7 @@ struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog,
|
||||
libbpf_strerror_r(pfd, errmsg, sizeof(errmsg)));
|
||||
return libbpf_err_ptr(pfd);
|
||||
}
|
||||
link = bpf_program__attach_perf_event(prog, pfd);
|
||||
link = bpf_program__attach_perf_event_opts(prog, pfd, &pe_opts);
|
||||
err = libbpf_get_error(link);
|
||||
if (err) {
|
||||
close(pfd);
|
||||
@@ -9369,6 +9414,13 @@ struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog,
|
||||
return link;
|
||||
}
|
||||
|
||||
struct bpf_link *bpf_program__attach_tracepoint(struct bpf_program *prog,
|
||||
const char *tp_category,
|
||||
const char *tp_name)
|
||||
{
|
||||
return bpf_program__attach_tracepoint_opts(prog, tp_category, tp_name, NULL);
|
||||
}
|
||||
|
||||
static struct bpf_link *attach_tp(const struct bpf_sec_def *sec,
|
||||
struct bpf_program *prog)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user