Skip to content

Commit 8f4c92f

Browse files
committed
Merge branch 'libbpf: allow users to set kprobe/uprobe attach mode'
Menglong Dong says: ==================== From: Menglong Dong <[email protected]> By default, libbpf will attach the kprobe/uprobe BPF program in the latest mode that supported by kernel. In this series, we add the support to let users manually attach kprobe/uprobe in legacy/perf/link mode in the 1th patch. And in the 2th patch, we split the testing 'attach_probe' into multi subtests, as Andrii suggested. In the 3th patch, we add the testings for loading kprobe/uprobe in different mode. Changes since v3: - rename eBPF to BPF in the doc - use OPTS_GET() to get the value of 'force_ioctl_attach' - error out on attach mode is not supported - use test_attach_probe_manual__open_and_load() directly Changes since v2: - fix the typo in the 2th patch Changes since v1: - some small changes in the 1th patch, as Andrii suggested - split 'attach_probe' into multi subtests ==================== Signed-off-by: Andrii Nakryiko <[email protected]>
2 parents fd4cb29 + c7aec81 commit 8f4c92f

File tree

6 files changed

+357
-143
lines changed

6 files changed

+357
-143
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9724,6 +9724,7 @@ struct bpf_link *bpf_program__attach_perf_event_opts(const struct bpf_program *p
97249724
char errmsg[STRERR_BUFSIZE];
97259725
struct bpf_link_perf *link;
97269726
int prog_fd, link_fd = -1, err;
9727+
bool force_ioctl_attach;
97279728

97289729
if (!OPTS_VALID(opts, bpf_perf_event_opts))
97299730
return libbpf_err_ptr(-EINVAL);
@@ -9747,7 +9748,8 @@ struct bpf_link *bpf_program__attach_perf_event_opts(const struct bpf_program *p
97479748
link->link.dealloc = &bpf_link_perf_dealloc;
97489749
link->perf_event_fd = pfd;
97499750

9750-
if (kernel_supports(prog->obj, FEAT_PERF_LINK)) {
9751+
force_ioctl_attach = OPTS_GET(opts, force_ioctl_attach, false);
9752+
if (kernel_supports(prog->obj, FEAT_PERF_LINK) && !force_ioctl_attach) {
97519753
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts,
97529754
.perf_event.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0));
97539755

@@ -10106,6 +10108,7 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog,
1010610108
const struct bpf_kprobe_opts *opts)
1010710109
{
1010810110
DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
10111+
enum probe_attach_mode attach_mode;
1010910112
char errmsg[STRERR_BUFSIZE];
1011010113
char *legacy_probe = NULL;
1011110114
struct bpf_link *link;
@@ -10116,11 +10119,32 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog,
1011610119
if (!OPTS_VALID(opts, bpf_kprobe_opts))
1011710120
return libbpf_err_ptr(-EINVAL);
1011810121

10122+
attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT);
1011910123
retprobe = OPTS_GET(opts, retprobe, false);
1012010124
offset = OPTS_GET(opts, offset, 0);
1012110125
pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
1012210126

1012310127
legacy = determine_kprobe_perf_type() < 0;
10128+
switch (attach_mode) {
10129+
case PROBE_ATTACH_MODE_LEGACY:
10130+
legacy = true;
10131+
pe_opts.force_ioctl_attach = true;
10132+
break;
10133+
case PROBE_ATTACH_MODE_PERF:
10134+
if (legacy)
10135+
return libbpf_err_ptr(-ENOTSUP);
10136+
pe_opts.force_ioctl_attach = true;
10137+
break;
10138+
case PROBE_ATTACH_MODE_LINK:
10139+
if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK))
10140+
return libbpf_err_ptr(-ENOTSUP);
10141+
break;
10142+
case PROBE_ATTACH_MODE_DEFAULT:
10143+
break;
10144+
default:
10145+
return libbpf_err_ptr(-EINVAL);
10146+
}
10147+
1012410148
if (!legacy) {
1012510149
pfd = perf_event_open_probe(false /* uprobe */, retprobe,
1012610150
func_name, offset,
@@ -10852,6 +10876,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
1085210876
const char *archive_path = NULL, *archive_sep = NULL;
1085310877
char errmsg[STRERR_BUFSIZE], *legacy_probe = NULL;
1085410878
DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
10879+
enum probe_attach_mode attach_mode;
1085510880
char full_path[PATH_MAX];
1085610881
struct bpf_link *link;
1085710882
size_t ref_ctr_off;
@@ -10862,6 +10887,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
1086210887
if (!OPTS_VALID(opts, bpf_uprobe_opts))
1086310888
return libbpf_err_ptr(-EINVAL);
1086410889

10890+
attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT);
1086510891
retprobe = OPTS_GET(opts, retprobe, false);
1086610892
ref_ctr_off = OPTS_GET(opts, ref_ctr_offset, 0);
1086710893
pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
@@ -10903,6 +10929,26 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
1090310929
}
1090410930

1090510931
legacy = determine_uprobe_perf_type() < 0;
10932+
switch (attach_mode) {
10933+
case PROBE_ATTACH_MODE_LEGACY:
10934+
legacy = true;
10935+
pe_opts.force_ioctl_attach = true;
10936+
break;
10937+
case PROBE_ATTACH_MODE_PERF:
10938+
if (legacy)
10939+
return libbpf_err_ptr(-ENOTSUP);
10940+
pe_opts.force_ioctl_attach = true;
10941+
break;
10942+
case PROBE_ATTACH_MODE_LINK:
10943+
if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK))
10944+
return libbpf_err_ptr(-ENOTSUP);
10945+
break;
10946+
case PROBE_ATTACH_MODE_DEFAULT:
10947+
break;
10948+
default:
10949+
return libbpf_err_ptr(-EINVAL);
10950+
}
10951+
1090610952
if (!legacy) {
1090710953
pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path,
1090810954
func_offset, pid, ref_ctr_off);

tools/lib/bpf/libbpf.h

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -447,12 +447,15 @@ LIBBPF_API struct bpf_link *
447447
bpf_program__attach(const struct bpf_program *prog);
448448

449449
struct bpf_perf_event_opts {
450-
/* size of this struct, for forward/backward compatiblity */
450+
/* size of this struct, for forward/backward compatibility */
451451
size_t sz;
452452
/* custom user-provided value fetchable through bpf_get_attach_cookie() */
453453
__u64 bpf_cookie;
454+
/* don't use BPF link when attach BPF program */
455+
bool force_ioctl_attach;
456+
size_t :0;
454457
};
455-
#define bpf_perf_event_opts__last_field bpf_cookie
458+
#define bpf_perf_event_opts__last_field force_ioctl_attach
456459

457460
LIBBPF_API struct bpf_link *
458461
bpf_program__attach_perf_event(const struct bpf_program *prog, int pfd);
@@ -461,18 +464,37 @@ LIBBPF_API struct bpf_link *
461464
bpf_program__attach_perf_event_opts(const struct bpf_program *prog, int pfd,
462465
const struct bpf_perf_event_opts *opts);
463466

467+
/**
468+
* enum probe_attach_mode - the mode to attach kprobe/uprobe
469+
*
470+
* force libbpf to attach kprobe/uprobe in specific mode, -ENOTSUP will
471+
* be returned if it is not supported by the kernel.
472+
*/
473+
enum probe_attach_mode {
474+
/* attach probe in latest supported mode by kernel */
475+
PROBE_ATTACH_MODE_DEFAULT = 0,
476+
/* attach probe in legacy mode, using debugfs/tracefs */
477+
PROBE_ATTACH_MODE_LEGACY,
478+
/* create perf event with perf_event_open() syscall */
479+
PROBE_ATTACH_MODE_PERF,
480+
/* attach probe with BPF link */
481+
PROBE_ATTACH_MODE_LINK,
482+
};
483+
464484
struct bpf_kprobe_opts {
465-
/* size of this struct, for forward/backward compatiblity */
485+
/* size of this struct, for forward/backward compatibility */
466486
size_t sz;
467487
/* custom user-provided value fetchable through bpf_get_attach_cookie() */
468488
__u64 bpf_cookie;
469489
/* function's offset to install kprobe to */
470490
size_t offset;
471491
/* kprobe is return probe */
472492
bool retprobe;
493+
/* kprobe attach mode */
494+
enum probe_attach_mode attach_mode;
473495
size_t :0;
474496
};
475-
#define bpf_kprobe_opts__last_field retprobe
497+
#define bpf_kprobe_opts__last_field attach_mode
476498

477499
LIBBPF_API struct bpf_link *
478500
bpf_program__attach_kprobe(const struct bpf_program *prog, bool retprobe,
@@ -506,7 +528,7 @@ bpf_program__attach_kprobe_multi_opts(const struct bpf_program *prog,
506528
const struct bpf_kprobe_multi_opts *opts);
507529

508530
struct bpf_ksyscall_opts {
509-
/* size of this struct, for forward/backward compatiblity */
531+
/* size of this struct, for forward/backward compatibility */
510532
size_t sz;
511533
/* custom user-provided value fetchable through bpf_get_attach_cookie() */
512534
__u64 bpf_cookie;
@@ -552,7 +574,7 @@ bpf_program__attach_ksyscall(const struct bpf_program *prog,
552574
const struct bpf_ksyscall_opts *opts);
553575

554576
struct bpf_uprobe_opts {
555-
/* size of this struct, for forward/backward compatiblity */
577+
/* size of this struct, for forward/backward compatibility */
556578
size_t sz;
557579
/* offset of kernel reference counted USDT semaphore, added in
558580
* a6ca88b241d5 ("trace_uprobe: support reference counter in fd-based uprobe")
@@ -570,9 +592,11 @@ struct bpf_uprobe_opts {
570592
* binary_path.
571593
*/
572594
const char *func_name;
595+
/* uprobe attach mode */
596+
enum probe_attach_mode attach_mode;
573597
size_t :0;
574598
};
575-
#define bpf_uprobe_opts__last_field func_name
599+
#define bpf_uprobe_opts__last_field attach_mode
576600

577601
/**
578602
* @brief **bpf_program__attach_uprobe()** attaches a BPF program
@@ -646,7 +670,7 @@ bpf_program__attach_usdt(const struct bpf_program *prog,
646670
const struct bpf_usdt_opts *opts);
647671

648672
struct bpf_tracepoint_opts {
649-
/* size of this struct, for forward/backward compatiblity */
673+
/* size of this struct, for forward/backward compatibility */
650674
size_t sz;
651675
/* custom user-provided value fetchable through bpf_get_attach_cookie() */
652676
__u64 bpf_cookie;
@@ -1110,7 +1134,7 @@ struct user_ring_buffer;
11101134
typedef int (*ring_buffer_sample_fn)(void *ctx, void *data, size_t size);
11111135

11121136
struct ring_buffer_opts {
1113-
size_t sz; /* size of this struct, for forward/backward compatiblity */
1137+
size_t sz; /* size of this struct, for forward/backward compatibility */
11141138
};
11151139

11161140
#define ring_buffer_opts__last_field sz
@@ -1475,7 +1499,7 @@ LIBBPF_API void
14751499
bpf_object__destroy_subskeleton(struct bpf_object_subskeleton *s);
14761500

14771501
struct gen_loader_opts {
1478-
size_t sz; /* size of this struct, for forward/backward compatiblity */
1502+
size_t sz; /* size of this struct, for forward/backward compatibility */
14791503
const char *data;
14801504
const char *insns;
14811505
__u32 data_sz;
@@ -1493,13 +1517,13 @@ enum libbpf_tristate {
14931517
};
14941518

14951519
struct bpf_linker_opts {
1496-
/* size of this struct, for forward/backward compatiblity */
1520+
/* size of this struct, for forward/backward compatibility */
14971521
size_t sz;
14981522
};
14991523
#define bpf_linker_opts__last_field sz
15001524

15011525
struct bpf_linker_file_opts {
1502-
/* size of this struct, for forward/backward compatiblity */
1526+
/* size of this struct, for forward/backward compatibility */
15031527
size_t sz;
15041528
};
15051529
#define bpf_linker_file_opts__last_field sz
@@ -1542,7 +1566,7 @@ typedef int (*libbpf_prog_attach_fn_t)(const struct bpf_program *prog, long cook
15421566
struct bpf_link **link);
15431567

15441568
struct libbpf_prog_handler_opts {
1545-
/* size of this struct, for forward/backward compatiblity */
1569+
/* size of this struct, for forward/backward compatibility */
15461570
size_t sz;
15471571
/* User-provided value that is passed to prog_setup_fn,
15481572
* prog_prepare_load_fn, and prog_attach_fn callbacks. Allows user to

0 commit comments

Comments
 (0)