Re: [PATCH bpf-next 1/3] libbpf: allow "incomplete" basic tracing SEC() definitions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Apr 8, 2022 at 1:46 PM Song Liu <song@xxxxxxxxxx> wrote:
>
> On Fri, Apr 8, 2022 at 1:34 PM Andrii Nakryiko <andrii@xxxxxxxxxx> wrote:
> >
> > In a lot of cases the target of kprobe/kretprobe, tracepoint, raw
> > tracepoint, etc BPF program might not be known at the compilation time
> > and will be discovered at runtime. This was always a supported case by
> > libbpf, with APIs like bpf_program__attach_{kprobe,tracepoint,etc}()
> > accepting full target definition, regardless of what was defined in
> > SEC() definition in BPF source code.
> >
> > Unfortunately, up till now libbpf still enforced users to specify at
> > least something for the fake target, e.g., SEC("kprobe/whatever"), which
> > is cumbersome and somewhat misleading.
> >
> > This patch allows target-less SEC() definitions for basic tracing BPF
> > program types:
> >   - kprobe/kretprobe;
> >   - multi-kprobe/multi-kretprobe;
> >   - tracepoints;
> >   - raw tracepoints.
> >
> > Such target-less SEC() definitions are meant to specify declaratively
> > proper BPF program type only. Attachment of them will have to be handled
> > programmatically using correct APIs. As such, skeleton's auto-attachment
> > of such BPF programs is skipped and generic bpf_program__attach() will
> > fail, if attempted, due to the lack of enough target information.
> >
> > Signed-off-by: Andrii Nakryiko <andrii@xxxxxxxxxx>
> > ---
> >  tools/lib/bpf/libbpf.c | 69 +++++++++++++++++++++++++++++++-----------
> >  1 file changed, 51 insertions(+), 18 deletions(-)
> >
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index 9deb1fc67f19..81911a1e1f3e 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -8668,22 +8668,22 @@ static const struct bpf_sec_def section_defs[] = {
> >         SEC_DEF("socket",               SOCKET_FILTER, 0, SEC_NONE | SEC_SLOPPY_PFX),
> >         SEC_DEF("sk_reuseport/migrate", SK_REUSEPORT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, SEC_ATTACHABLE | SEC_SLOPPY_PFX),
> >         SEC_DEF("sk_reuseport",         SK_REUSEPORT, BPF_SK_REUSEPORT_SELECT, SEC_ATTACHABLE | SEC_SLOPPY_PFX),
> > -       SEC_DEF("kprobe/",              KPROBE, 0, SEC_NONE, attach_kprobe),
> > +       SEC_DEF("kprobe+",              KPROBE, 0, SEC_NONE, attach_kprobe),
> >         SEC_DEF("uprobe+",              KPROBE, 0, SEC_NONE, attach_uprobe),
> > -       SEC_DEF("kretprobe/",           KPROBE, 0, SEC_NONE, attach_kprobe),
> > +       SEC_DEF("kretprobe+",           KPROBE, 0, SEC_NONE, attach_kprobe),
> >         SEC_DEF("uretprobe+",           KPROBE, 0, SEC_NONE, attach_uprobe),
> > -       SEC_DEF("kprobe.multi/",        KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
> > -       SEC_DEF("kretprobe.multi/",     KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
> > +       SEC_DEF("kprobe.multi+",        KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
> > +       SEC_DEF("kretprobe.multi+",     KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach_kprobe_multi),
> >         SEC_DEF("usdt+",                KPROBE, 0, SEC_NONE, attach_usdt),
> >         SEC_DEF("tc",                   SCHED_CLS, 0, SEC_NONE),
> >         SEC_DEF("classifier",           SCHED_CLS, 0, SEC_NONE | SEC_SLOPPY_PFX | SEC_DEPRECATED),
> >         SEC_DEF("action",               SCHED_ACT, 0, SEC_NONE | SEC_SLOPPY_PFX),
> > -       SEC_DEF("tracepoint/",          TRACEPOINT, 0, SEC_NONE, attach_tp),
> > -       SEC_DEF("tp/",                  TRACEPOINT, 0, SEC_NONE, attach_tp),
> > -       SEC_DEF("raw_tracepoint/",      RAW_TRACEPOINT, 0, SEC_NONE, attach_raw_tp),
> > -       SEC_DEF("raw_tp/",              RAW_TRACEPOINT, 0, SEC_NONE, attach_raw_tp),
> > -       SEC_DEF("raw_tracepoint.w/",    RAW_TRACEPOINT_WRITABLE, 0, SEC_NONE, attach_raw_tp),
> > -       SEC_DEF("raw_tp.w/",            RAW_TRACEPOINT_WRITABLE, 0, SEC_NONE, attach_raw_tp),
> > +       SEC_DEF("tracepoint+",          TRACEPOINT, 0, SEC_NONE, attach_tp),
> > +       SEC_DEF("tp+",                  TRACEPOINT, 0, SEC_NONE, attach_tp),
> > +       SEC_DEF("raw_tracepoint+",      RAW_TRACEPOINT, 0, SEC_NONE, attach_raw_tp),
> > +       SEC_DEF("raw_tp+",              RAW_TRACEPOINT, 0, SEC_NONE, attach_raw_tp),
> > +       SEC_DEF("raw_tracepoint.w+",    RAW_TRACEPOINT_WRITABLE, 0, SEC_NONE, attach_raw_tp),
> > +       SEC_DEF("raw_tp.w+",            RAW_TRACEPOINT_WRITABLE, 0, SEC_NONE, attach_raw_tp),
> >         SEC_DEF("tp_btf/",              TRACING, BPF_TRACE_RAW_TP, SEC_ATTACH_BTF, attach_trace),
> >         SEC_DEF("fentry/",              TRACING, BPF_TRACE_FENTRY, SEC_ATTACH_BTF, attach_trace),
> >         SEC_DEF("fmod_ret/",            TRACING, BPF_MODIFY_RETURN, SEC_ATTACH_BTF, attach_trace),
> > @@ -10411,6 +10411,12 @@ static int attach_kprobe(const struct bpf_program *prog, long cookie, struct bpf
> >         char *func;
> >         int n;
> >
> > +       *link = NULL;
> > +
> > +       /* no auto-attach for SEC("kprobe") and SEC("kretprobe") */
> > +       if (strcmp(prog->sec_name, "kprobe") == 0 || strcmp(prog->sec_name, "kretprobe") == 0)
> > +               return 0;
> > +
> >         opts.retprobe = str_has_pfx(prog->sec_name, "kretprobe/");
> >         if (opts.retprobe)
> >                 func_name = prog->sec_name + sizeof("kretprobe/") - 1;
> > @@ -10441,6 +10447,13 @@ static int attach_kprobe_multi(const struct bpf_program *prog, long cookie, stru
> >         char *pattern;
> >         int n;
> >
> > +       *link = NULL;
> > +
> > +       /* no auto-attach for SEC("kprobe.multi") and SEC("kretprobe.multi") */
> > +       if (strcmp(prog->sec_name, "kprobe.multi") == 0 ||
> > +           strcmp(prog->sec_name, "kretprobe.multi") == 0)
> > +               return 0;
> > +
> >         opts.retprobe = str_has_pfx(prog->sec_name, "kretprobe.multi/");
> >         if (opts.retprobe)
> >                 spec = prog->sec_name + sizeof("kretprobe.multi/") - 1;
> > @@ -11145,6 +11158,12 @@ static int attach_tp(const struct bpf_program *prog, long cookie, struct bpf_lin
> >         if (!sec_name)
> >                 return -ENOMEM;
> >
> > +       *link = NULL;
> > +
> > +       /* no auto-attach for SEC("tp") or SEC("tracepoint") */
> > +       if (strcmp(prog->sec_name, "tp") == 0 || strcmp(prog->sec_name, "tracepoint") == 0)
> > +               return 0;
> > +
> >         /* extract "tp/<category>/<name>" or "tracepoint/<category>/<name>" */
> >         if (str_has_pfx(prog->sec_name, "tp/"))
> >                 tp_cat = sec_name + sizeof("tp/") - 1;
> > @@ -11196,20 +11215,34 @@ struct bpf_link *bpf_program__attach_raw_tracepoint(const struct bpf_program *pr
> >  static int attach_raw_tp(const struct bpf_program *prog, long cookie, struct bpf_link **link)
> >  {
> >         static const char *const prefixes[] = {
> > -               "raw_tp/",
> > -               "raw_tracepoint/",
> > -               "raw_tp.w/",
> > -               "raw_tracepoint.w/",
> > +               "raw_tp",
> > +               "raw_tracepoint",
> > +               "raw_tp.w",
> > +               "raw_tracepoint.w",
> >         };
> >         size_t i;
> >         const char *tp_name = NULL;
> >
> > +       *link = NULL;
> > +
> >         for (i = 0; i < ARRAY_SIZE(prefixes); i++) {
> > -               if (str_has_pfx(prog->sec_name, prefixes[i])) {
> > -                       tp_name = prog->sec_name + strlen(prefixes[i]);
> > -                       break;
> > -               }
> > +               size_t pfx_len;
> > +
> > +               if (!str_has_pfx(prog->sec_name, prefixes[i]))
> > +                       continue;
> > +
> > +               pfx_len = strlen(prefixes[i]);
> > +               /* no auto-attach case of, e.g., SEC("raw_tp") */
> > +               if (prog->sec_name[pfx_len] == '\0')
> > +                       return 0;
> > +
> > +               if (prog->sec_name[pfx_len] != '/')
> > +                       continue;
>
> Maybe introduce a sec_has_pfx() function with tri-state return value:
> 1 for match with tp_name, 0, for match without tp_name, -1 for no match.
>

Hm.. tri-state might be quite confusing, but there might be some clean
ups to be done around this prefix handling for SEC_DEF()s. I'm
planning to do some more work on SEC() handling, I'll do this clean up
as a follow up, if you don't mind. Need to see how to best consolidate
this across all the places where we do this prefix matching.

> > +
> > +               tp_name = prog->sec_name + pfx_len + 1;
> > +               break;
> >         }
> > +
> >         if (!tp_name) {
> >                 pr_warn("prog '%s': invalid section name '%s'\n",
> >                         prog->name, prog->sec_name);
> > --
> > 2.30.2
> >



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux