Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libbpf: Add support to set kprobe/uprobe attach mode

By default, libbpf will attach the kprobe/uprobe BPF program in the
latest mode that supported by kernel. In this patch, we add the support
to let users manually attach kprobe/uprobe in legacy or perf mode.

There are 3 mode that supported by the kernel to attach kprobe/uprobe:

LEGACY: create perf event in legacy way and don't use bpf_link
PERF: create perf event with perf_event_open() and don't use bpf_link

Signed-off-by: Menglong Dong <imagedong@tencent.com>
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Reviewed-by: Biao Jiang <benbjiang@tencent.com>
Link: create perf event with perf_event_open() and use bpf_link
Link: https://lore.kernel.org/bpf/20230113093427.1666466-1-imagedong@tencent.com/
Link: https://lore.kernel.org/bpf/20230306064833.7932-2-imagedong@tencent.com

Users now can manually choose the mode with
bpf_program__attach_uprobe_opts()/bpf_program__attach_kprobe_opts().

authored by

Menglong Dong and committed by
Andrii Nakryiko
f8b299bc fd4cb29f

+84 -14
+47 -1
tools/lib/bpf/libbpf.c
··· 9724 9724 char errmsg[STRERR_BUFSIZE]; 9725 9725 struct bpf_link_perf *link; 9726 9726 int prog_fd, link_fd = -1, err; 9727 + bool force_ioctl_attach; 9727 9728 9728 9729 if (!OPTS_VALID(opts, bpf_perf_event_opts)) 9729 9730 return libbpf_err_ptr(-EINVAL); ··· 9748 9747 link->link.dealloc = &bpf_link_perf_dealloc; 9749 9748 link->perf_event_fd = pfd; 9750 9749 9751 - if (kernel_supports(prog->obj, FEAT_PERF_LINK)) { 9750 + force_ioctl_attach = OPTS_GET(opts, force_ioctl_attach, false); 9751 + if (kernel_supports(prog->obj, FEAT_PERF_LINK) && !force_ioctl_attach) { 9752 9752 DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts, 9753 9753 .perf_event.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0)); 9754 9754 ··· 10108 10106 const struct bpf_kprobe_opts *opts) 10109 10107 { 10110 10108 DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts); 10109 + enum probe_attach_mode attach_mode; 10111 10110 char errmsg[STRERR_BUFSIZE]; 10112 10111 char *legacy_probe = NULL; 10113 10112 struct bpf_link *link; ··· 10119 10116 if (!OPTS_VALID(opts, bpf_kprobe_opts)) 10120 10117 return libbpf_err_ptr(-EINVAL); 10121 10118 10119 + attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT); 10122 10120 retprobe = OPTS_GET(opts, retprobe, false); 10123 10121 offset = OPTS_GET(opts, offset, 0); 10124 10122 pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); 10125 10123 10126 10124 legacy = determine_kprobe_perf_type() < 0; 10125 + switch (attach_mode) { 10126 + case PROBE_ATTACH_MODE_LEGACY: 10127 + legacy = true; 10128 + pe_opts.force_ioctl_attach = true; 10129 + break; 10130 + case PROBE_ATTACH_MODE_PERF: 10131 + if (legacy) 10132 + return libbpf_err_ptr(-ENOTSUP); 10133 + pe_opts.force_ioctl_attach = true; 10134 + break; 10135 + case PROBE_ATTACH_MODE_LINK: 10136 + if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK)) 10137 + return libbpf_err_ptr(-ENOTSUP); 10138 + break; 10139 + case PROBE_ATTACH_MODE_DEFAULT: 10140 + break; 10141 + default: 10142 + return libbpf_err_ptr(-EINVAL); 10143 + } 10144 + 10127 10145 if (!legacy) { 10128 10146 pfd = perf_event_open_probe(false /* uprobe */, retprobe, 10129 10147 func_name, offset, ··· 10876 10852 const char *archive_path = NULL, *archive_sep = NULL; 10877 10853 char errmsg[STRERR_BUFSIZE], *legacy_probe = NULL; 10878 10854 DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts); 10855 + enum probe_attach_mode attach_mode; 10879 10856 char full_path[PATH_MAX]; 10880 10857 struct bpf_link *link; 10881 10858 size_t ref_ctr_off; ··· 10887 10862 if (!OPTS_VALID(opts, bpf_uprobe_opts)) 10888 10863 return libbpf_err_ptr(-EINVAL); 10889 10864 10865 + attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT); 10890 10866 retprobe = OPTS_GET(opts, retprobe, false); 10891 10867 ref_ctr_off = OPTS_GET(opts, ref_ctr_offset, 0); 10892 10868 pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0); ··· 10929 10903 } 10930 10904 10931 10905 legacy = determine_uprobe_perf_type() < 0; 10906 + switch (attach_mode) { 10907 + case PROBE_ATTACH_MODE_LEGACY: 10908 + legacy = true; 10909 + pe_opts.force_ioctl_attach = true; 10910 + break; 10911 + case PROBE_ATTACH_MODE_PERF: 10912 + if (legacy) 10913 + return libbpf_err_ptr(-ENOTSUP); 10914 + pe_opts.force_ioctl_attach = true; 10915 + break; 10916 + case PROBE_ATTACH_MODE_LINK: 10917 + if (legacy || !kernel_supports(prog->obj, FEAT_PERF_LINK)) 10918 + return libbpf_err_ptr(-ENOTSUP); 10919 + break; 10920 + case PROBE_ATTACH_MODE_DEFAULT: 10921 + break; 10922 + default: 10923 + return libbpf_err_ptr(-EINVAL); 10924 + } 10925 + 10932 10926 if (!legacy) { 10933 10927 pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path, 10934 10928 func_offset, pid, ref_ctr_off);
+37 -13
tools/lib/bpf/libbpf.h
··· 447 447 bpf_program__attach(const struct bpf_program *prog); 448 448 449 449 struct bpf_perf_event_opts { 450 - /* size of this struct, for forward/backward compatiblity */ 450 + /* size of this struct, for forward/backward compatibility */ 451 451 size_t sz; 452 452 /* custom user-provided value fetchable through bpf_get_attach_cookie() */ 453 453 __u64 bpf_cookie; 454 + /* don't use BPF link when attach BPF program */ 455 + bool force_ioctl_attach; 456 + size_t :0; 454 457 }; 455 - #define bpf_perf_event_opts__last_field bpf_cookie 458 + #define bpf_perf_event_opts__last_field force_ioctl_attach 456 459 457 460 LIBBPF_API struct bpf_link * 458 461 bpf_program__attach_perf_event(const struct bpf_program *prog, int pfd); ··· 464 461 bpf_program__attach_perf_event_opts(const struct bpf_program *prog, int pfd, 465 462 const struct bpf_perf_event_opts *opts); 466 463 464 + /** 465 + * enum probe_attach_mode - the mode to attach kprobe/uprobe 466 + * 467 + * force libbpf to attach kprobe/uprobe in specific mode, -ENOTSUP will 468 + * be returned if it is not supported by the kernel. 469 + */ 470 + enum probe_attach_mode { 471 + /* attach probe in latest supported mode by kernel */ 472 + PROBE_ATTACH_MODE_DEFAULT = 0, 473 + /* attach probe in legacy mode, using debugfs/tracefs */ 474 + PROBE_ATTACH_MODE_LEGACY, 475 + /* create perf event with perf_event_open() syscall */ 476 + PROBE_ATTACH_MODE_PERF, 477 + /* attach probe with BPF link */ 478 + PROBE_ATTACH_MODE_LINK, 479 + }; 480 + 467 481 struct bpf_kprobe_opts { 468 - /* size of this struct, for forward/backward compatiblity */ 482 + /* size of this struct, for forward/backward compatibility */ 469 483 size_t sz; 470 484 /* custom user-provided value fetchable through bpf_get_attach_cookie() */ 471 485 __u64 bpf_cookie; ··· 490 470 size_t offset; 491 471 /* kprobe is return probe */ 492 472 bool retprobe; 473 + /* kprobe attach mode */ 474 + enum probe_attach_mode attach_mode; 493 475 size_t :0; 494 476 }; 495 - #define bpf_kprobe_opts__last_field retprobe 477 + #define bpf_kprobe_opts__last_field attach_mode 496 478 497 479 LIBBPF_API struct bpf_link * 498 480 bpf_program__attach_kprobe(const struct bpf_program *prog, bool retprobe, ··· 528 506 const struct bpf_kprobe_multi_opts *opts); 529 507 530 508 struct bpf_ksyscall_opts { 531 - /* size of this struct, for forward/backward compatiblity */ 509 + /* size of this struct, for forward/backward compatibility */ 532 510 size_t sz; 533 511 /* custom user-provided value fetchable through bpf_get_attach_cookie() */ 534 512 __u64 bpf_cookie; ··· 574 552 const struct bpf_ksyscall_opts *opts); 575 553 576 554 struct bpf_uprobe_opts { 577 - /* size of this struct, for forward/backward compatiblity */ 555 + /* size of this struct, for forward/backward compatibility */ 578 556 size_t sz; 579 557 /* offset of kernel reference counted USDT semaphore, added in 580 558 * a6ca88b241d5 ("trace_uprobe: support reference counter in fd-based uprobe") ··· 592 570 * binary_path. 593 571 */ 594 572 const char *func_name; 573 + /* uprobe attach mode */ 574 + enum probe_attach_mode attach_mode; 595 575 size_t :0; 596 576 }; 597 - #define bpf_uprobe_opts__last_field func_name 577 + #define bpf_uprobe_opts__last_field attach_mode 598 578 599 579 /** 600 580 * @brief **bpf_program__attach_uprobe()** attaches a BPF program ··· 670 646 const struct bpf_usdt_opts *opts); 671 647 672 648 struct bpf_tracepoint_opts { 673 - /* size of this struct, for forward/backward compatiblity */ 649 + /* size of this struct, for forward/backward compatibility */ 674 650 size_t sz; 675 651 /* custom user-provided value fetchable through bpf_get_attach_cookie() */ 676 652 __u64 bpf_cookie; ··· 1134 1110 typedef int (*ring_buffer_sample_fn)(void *ctx, void *data, size_t size); 1135 1111 1136 1112 struct ring_buffer_opts { 1137 - size_t sz; /* size of this struct, for forward/backward compatiblity */ 1113 + size_t sz; /* size of this struct, for forward/backward compatibility */ 1138 1114 }; 1139 1115 1140 1116 #define ring_buffer_opts__last_field sz ··· 1499 1475 bpf_object__destroy_subskeleton(struct bpf_object_subskeleton *s); 1500 1476 1501 1477 struct gen_loader_opts { 1502 - size_t sz; /* size of this struct, for forward/backward compatiblity */ 1478 + size_t sz; /* size of this struct, for forward/backward compatibility */ 1503 1479 const char *data; 1504 1480 const char *insns; 1505 1481 __u32 data_sz; ··· 1517 1493 }; 1518 1494 1519 1495 struct bpf_linker_opts { 1520 - /* size of this struct, for forward/backward compatiblity */ 1496 + /* size of this struct, for forward/backward compatibility */ 1521 1497 size_t sz; 1522 1498 }; 1523 1499 #define bpf_linker_opts__last_field sz 1524 1500 1525 1501 struct bpf_linker_file_opts { 1526 - /* size of this struct, for forward/backward compatiblity */ 1502 + /* size of this struct, for forward/backward compatibility */ 1527 1503 size_t sz; 1528 1504 }; 1529 1505 #define bpf_linker_file_opts__last_field sz ··· 1566 1542 struct bpf_link **link); 1567 1543 1568 1544 struct libbpf_prog_handler_opts { 1569 - /* size of this struct, for forward/backward compatiblity */ 1545 + /* size of this struct, for forward/backward compatibility */ 1570 1546 size_t sz; 1571 1547 /* User-provided value that is passed to prog_setup_fn, 1572 1548 * prog_prepare_load_fn, and prog_attach_fn callbacks. Allows user to