Message ID | 20210714094400.396467-8-jolsa@kernel.org |
---|---|
State | New |
Headers | show |
Series | bpf, x86: Add bpf_get_func_ip helper | expand |
On Wed, Jul 14, 2021 at 2:45 AM Jiri Olsa <jolsa@redhat.com> wrote: > > From: Alan Maguire <alan.maguire@oracle.com> > > kprobes can be placed on most instructions in a function, not > just entry, and ftrace and bpftrace support the function+offset > notification for probe placement. Adding parsing of func_name > into func+offset to bpf_program__attach_kprobe() allows the > user to specify > > SEC("kprobe/bpf_fentry_test5+0x6") > > ...for example, and the offset can be passed to perf_event_open_probe() > to support kprobe attachment. > > [jolsa: changed original code to use bpf_program__attach_kprobe_opts > and use dynamic allocation in sscanf] > > Signed-off-by: Alan Maguire <alan.maguire@oracle.com> > Signed-off-by: Jiri Olsa <jolsa@kernel.org> > --- > tools/lib/bpf/libbpf.c | 24 ++++++++++++++++++++++-- > 1 file changed, 22 insertions(+), 2 deletions(-) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index d93a6f9408d1..abe6d4842bb0 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -10348,6 +10348,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, > > struct bpf_program_attach_kprobe_opts { > bool retprobe; > + unsigned long offset; > }; > > static struct bpf_link* > @@ -10360,7 +10361,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, > int pfd, err; > > pfd = perf_event_open_probe(false /* uprobe */, opts->retprobe, func_name, > - 0 /* offset */, -1 /* pid */); > + opts->offset, -1 /* pid */); > if (pfd < 0) { > pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n", > prog->name, opts->retprobe ? "kretprobe" : "kprobe", func_name, > @@ -10394,12 +10395,31 @@ static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec, > struct bpf_program *prog) > { > struct bpf_program_attach_kprobe_opts opts; > + unsigned long offset = 0; > + struct bpf_link *link; > const char *func_name; > + char *func; > + int n, err; > > func_name = prog->sec_name + sec->len; > opts.retprobe = strcmp(sec->sec, "kretprobe/") == 0; > > - return bpf_program__attach_kprobe_opts(prog, func_name, &opts); > + n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%lx", &func, &offset); could have used %li here to support both +0xabc and +123 forms > + if (n < 1) { > + err = -EINVAL; > + pr_warn("kprobe name is invalid: %s\n", func_name); > + return libbpf_err_ptr(err); > + } > + if (opts.retprobe && offset != 0) { > + err = -EINVAL; leaking func here > + pr_warn("kretprobes do not support offset specification\n"); > + return libbpf_err_ptr(err); > + } > + > + opts.offset = offset; > + link = bpf_program__attach_kprobe_opts(prog, func, &opts); > + free(func); > + return link; > } > > struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog, > -- > 2.31.1 >
On Fri, Jul 16, 2021 at 06:42:05PM -0700, Andrii Nakryiko wrote: > On Wed, Jul 14, 2021 at 2:45 AM Jiri Olsa <jolsa@redhat.com> wrote: > > > > From: Alan Maguire <alan.maguire@oracle.com> > > > > kprobes can be placed on most instructions in a function, not > > just entry, and ftrace and bpftrace support the function+offset > > notification for probe placement. Adding parsing of func_name > > into func+offset to bpf_program__attach_kprobe() allows the > > user to specify > > > > SEC("kprobe/bpf_fentry_test5+0x6") > > > > ...for example, and the offset can be passed to perf_event_open_probe() > > to support kprobe attachment. > > > > [jolsa: changed original code to use bpf_program__attach_kprobe_opts > > and use dynamic allocation in sscanf] > > > > Signed-off-by: Alan Maguire <alan.maguire@oracle.com> > > Signed-off-by: Jiri Olsa <jolsa@kernel.org> > > --- > > tools/lib/bpf/libbpf.c | 24 ++++++++++++++++++++++-- > > 1 file changed, 22 insertions(+), 2 deletions(-) > > > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > > index d93a6f9408d1..abe6d4842bb0 100644 > > --- a/tools/lib/bpf/libbpf.c > > +++ b/tools/lib/bpf/libbpf.c > > @@ -10348,6 +10348,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, > > > > struct bpf_program_attach_kprobe_opts { > > bool retprobe; > > + unsigned long offset; > > }; > > > > static struct bpf_link* > > @@ -10360,7 +10361,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, > > int pfd, err; > > > > pfd = perf_event_open_probe(false /* uprobe */, opts->retprobe, func_name, > > - 0 /* offset */, -1 /* pid */); > > + opts->offset, -1 /* pid */); > > if (pfd < 0) { > > pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n", > > prog->name, opts->retprobe ? "kretprobe" : "kprobe", func_name, > > @@ -10394,12 +10395,31 @@ static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec, > > struct bpf_program *prog) > > { > > struct bpf_program_attach_kprobe_opts opts; > > + unsigned long offset = 0; > > + struct bpf_link *link; > > const char *func_name; > > + char *func; > > + int n, err; > > > > func_name = prog->sec_name + sec->len; > > opts.retprobe = strcmp(sec->sec, "kretprobe/") == 0; > > > > - return bpf_program__attach_kprobe_opts(prog, func_name, &opts); > > + n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%lx", &func, &offset); > > could have used %li here to support both +0xabc and +123 forms ok > > > + if (n < 1) { > > + err = -EINVAL; > > + pr_warn("kprobe name is invalid: %s\n", func_name); > > + return libbpf_err_ptr(err); > > + } > > + if (opts.retprobe && offset != 0) { > > + err = -EINVAL; > > leaking func here ugh.. thanks jirka > > > > + pr_warn("kretprobes do not support offset specification\n"); > > + return libbpf_err_ptr(err); > > + } > > + > > + opts.offset = offset; > > + link = bpf_program__attach_kprobe_opts(prog, func, &opts); > > + free(func); > > + return link; > > } > > > > struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog, > > -- > > 2.31.1 > > >
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index d93a6f9408d1..abe6d4842bb0 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -10348,6 +10348,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name, struct bpf_program_attach_kprobe_opts { bool retprobe; + unsigned long offset; }; static struct bpf_link* @@ -10360,7 +10361,7 @@ bpf_program__attach_kprobe_opts(struct bpf_program *prog, int pfd, err; pfd = perf_event_open_probe(false /* uprobe */, opts->retprobe, func_name, - 0 /* offset */, -1 /* pid */); + opts->offset, -1 /* pid */); if (pfd < 0) { pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n", prog->name, opts->retprobe ? "kretprobe" : "kprobe", func_name, @@ -10394,12 +10395,31 @@ static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec, struct bpf_program *prog) { struct bpf_program_attach_kprobe_opts opts; + unsigned long offset = 0; + struct bpf_link *link; const char *func_name; + char *func; + int n, err; func_name = prog->sec_name + sec->len; opts.retprobe = strcmp(sec->sec, "kretprobe/") == 0; - return bpf_program__attach_kprobe_opts(prog, func_name, &opts); + n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%lx", &func, &offset); + if (n < 1) { + err = -EINVAL; + pr_warn("kprobe name is invalid: %s\n", func_name); + return libbpf_err_ptr(err); + } + if (opts.retprobe && offset != 0) { + err = -EINVAL; + pr_warn("kretprobes do not support offset specification\n"); + return libbpf_err_ptr(err); + } + + opts.offset = offset; + link = bpf_program__attach_kprobe_opts(prog, func, &opts); + free(func); + return link; } struct bpf_link *bpf_program__attach_uprobe(struct bpf_program *prog,