diff mbox series

[PATCHv3,bpf-next,6/7] libbpf: allow specification of "kprobe/function+offset"

Message ID 20210707214751.159713-7-jolsa@kernel.org
State New
Headers show
Series bpf, x86: Add bpf_get_func_ip helper | expand

Commit Message

Jiri Olsa July 7, 2021, 9:47 p.m. UTC
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.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 tools/lib/bpf/libbpf.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

Comments

Andrii Nakryiko July 8, 2021, 12:14 a.m. UTC | #1
On Wed, Jul 7, 2021 at 2:54 PM 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.

>

> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

> Signed-off-by: Jiri Olsa <jolsa@kernel.org>

> ---

>  tools/lib/bpf/libbpf.c | 20 +++++++++++++++++---

>  1 file changed, 17 insertions(+), 3 deletions(-)

>

> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c

> index 1e04ce724240..60c9e3e77684 100644

> --- a/tools/lib/bpf/libbpf.c

> +++ b/tools/lib/bpf/libbpf.c

> @@ -10309,11 +10309,25 @@ struct bpf_link *bpf_program__attach_kprobe(struct bpf_program *prog,

>                                             const char *func_name)


I think we should add bpf_program__attach_kprobe_opts instead for the
programmatic API instead of parsing it here from func_name. It's a
cumbersome API.

Parsing SEC() is fine, of course, but then it has to call into
bpf_program__attach_kprobe_opts() internally.

>  {

>         char errmsg[STRERR_BUFSIZE];

> +       char func[BPF_OBJ_NAME_LEN];

> +       unsigned long offset = 0;

>         struct bpf_link *link;

> -       int pfd, err;

> +       int pfd, err, n;

> +

> +       n = sscanf(func_name, "%[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 (retprobe && offset != 0) {

> +               err = -EINVAL;

> +               pr_warn("kretprobes do not support offset specification\n");

> +               return libbpf_err_ptr(err);

> +       }

>

> -       pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name,

> -                                   0 /* offset */, -1 /* pid */);

> +       pfd = perf_event_open_probe(false /* uprobe */, retprobe, func,

> +                                   offset, -1 /* pid */);

>         if (pfd < 0) {

>                 pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n",

>                         prog->name, retprobe ? "kretprobe" : "kprobe", func_name,

> --

> 2.31.1

>
Jiri Olsa July 11, 2021, 2:48 p.m. UTC | #2
On Wed, Jul 07, 2021 at 05:14:20PM -0700, Andrii Nakryiko wrote:
> On Wed, Jul 7, 2021 at 2:54 PM 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.

> >

> > Signed-off-by: Alan Maguire <alan.maguire@oracle.com>

> > Signed-off-by: Jiri Olsa <jolsa@kernel.org>

> > ---

> >  tools/lib/bpf/libbpf.c | 20 +++++++++++++++++---

> >  1 file changed, 17 insertions(+), 3 deletions(-)

> >

> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c

> > index 1e04ce724240..60c9e3e77684 100644

> > --- a/tools/lib/bpf/libbpf.c

> > +++ b/tools/lib/bpf/libbpf.c

> > @@ -10309,11 +10309,25 @@ struct bpf_link *bpf_program__attach_kprobe(struct bpf_program *prog,

> >                                             const char *func_name)

> 

> I think we should add bpf_program__attach_kprobe_opts instead for the

> programmatic API instead of parsing it here from func_name. It's a

> cumbersome API.

> 

> Parsing SEC() is fine, of course, but then it has to call into

> bpf_program__attach_kprobe_opts() internally.


ok, Alan, will you make the change, or should I do that?

thanks,
jirka

> 

> >  {

> >         char errmsg[STRERR_BUFSIZE];

> > +       char func[BPF_OBJ_NAME_LEN];

> > +       unsigned long offset = 0;

> >         struct bpf_link *link;

> > -       int pfd, err;

> > +       int pfd, err, n;

> > +

> > +       n = sscanf(func_name, "%[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 (retprobe && offset != 0) {

> > +               err = -EINVAL;

> > +               pr_warn("kretprobes do not support offset specification\n");

> > +               return libbpf_err_ptr(err);

> > +       }

> >

> > -       pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name,

> > -                                   0 /* offset */, -1 /* pid */);

> > +       pfd = perf_event_open_probe(false /* uprobe */, retprobe, func,

> > +                                   offset, -1 /* pid */);

> >         if (pfd < 0) {

> >                 pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n",

> >                         prog->name, retprobe ? "kretprobe" : "kprobe", func_name,

> > --

> > 2.31.1

> >

>
diff mbox series

Patch

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 1e04ce724240..60c9e3e77684 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -10309,11 +10309,25 @@  struct bpf_link *bpf_program__attach_kprobe(struct bpf_program *prog,
 					    const char *func_name)
 {
 	char errmsg[STRERR_BUFSIZE];
+	char func[BPF_OBJ_NAME_LEN];
+	unsigned long offset = 0;
 	struct bpf_link *link;
-	int pfd, err;
+	int pfd, err, n;
+
+	n = sscanf(func_name, "%[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 (retprobe && offset != 0) {
+		err = -EINVAL;
+		pr_warn("kretprobes do not support offset specification\n");
+		return libbpf_err_ptr(err);
+	}
 
-	pfd = perf_event_open_probe(false /* uprobe */, retprobe, func_name,
-				    0 /* offset */, -1 /* pid */);
+	pfd = perf_event_open_probe(false /* uprobe */, retprobe, func,
+				    offset, -1 /* pid */);
 	if (pfd < 0) {
 		pr_warn("prog '%s': failed to create %s '%s' perf event: %s\n",
 			prog->name, retprobe ? "kretprobe" : "kprobe", func_name,