diff mbox series

[perf,3/3] tools/perf: recognize and process RECORD_MMAP events for bpf progs

Message ID 20180919223935.999270-4-ast@kernel.org
State Changes Requested, archived
Delegated to: BPF Maintainers
Headers show
Series perf, bpf: reveal invisible bpf programs | expand

Commit Message

Alexei Starovoitov Sept. 19, 2018, 10:39 p.m. UTC
Recognize JITed bpf prog load/unload events.
Add/remove kernel symbols accordingly.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
 tools/perf/util/machine.c | 27 +++++++++++++++++++++++++++
 tools/perf/util/symbol.c  | 13 +++++++++++++
 tools/perf/util/symbol.h  |  1 +
 3 files changed, 41 insertions(+)

Comments

Arnaldo Carvalho de Melo Sept. 20, 2018, 1:36 p.m. UTC | #1
Em Wed, Sep 19, 2018 at 03:39:35PM -0700, Alexei Starovoitov escreveu:
> Recognize JITed bpf prog load/unload events.
> Add/remove kernel symbols accordingly.
> 
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> ---
>  tools/perf/util/machine.c | 27 +++++++++++++++++++++++++++
>  tools/perf/util/symbol.c  | 13 +++++++++++++
>  tools/perf/util/symbol.h  |  1 +
>  3 files changed, 41 insertions(+)
> 
> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
> index c4acd2001db0..ae4f8a0fdc7e 100644
> --- a/tools/perf/util/machine.c
> +++ b/tools/perf/util/machine.c
> @@ -25,6 +25,7 @@
>  #include "sane_ctype.h"
>  #include <symbol/kallsyms.h>
>  #include <linux/mman.h>
> +#include <linux/magic.h>
>  
>  static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
>  
> @@ -1460,6 +1461,32 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
>  	enum dso_kernel_type kernel_type;
>  	bool is_kernel_mmap;
>  
> +	/* process JITed bpf programs load/unload events */
> +	if (event->mmap.pid == ~0u && event->mmap.tid == BPF_FS_MAGIC) {


So, this would be in machine__process_kernel_munmap-event(machine), etc,
no check for BPF_FS_MAGIC would be needed with a PERF_RECORD_MUNMAP.

> +		struct symbol *sym;
> +		u64 ip;
> +
> +		map = map_groups__find(&machine->kmaps, event->mmap.start);
> +		if (!map) {
> +			pr_err("No kernel map for IP %lx\n", event->mmap.start);
> +			goto out_problem;
> +		}
> +		ip = event->mmap.start - map->start + map->pgoff;
> +		if (event->mmap.filename[0]) {
> +			sym = symbol__new(ip, event->mmap.len, 0, 0,
> +					  event->mmap.filename);

Humm, so the bpf program would be just one symbol... bpf-to-bpf calls
will be to a different bpf program, right? 

/me goes to read https://lwn.net/Articles/741773/
                 "[PATCH bpf-next 00/13] bpf: introduce function calls"

> +			dso__insert_symbol(map->dso, sym);
> +		} else {
> +			if (symbols__erase(&map->dso->symbols, ip)) {
> +				pr_err("No bpf prog at IP %lx/%lx\n",
> +				       event->mmap.start, ip);
> +				goto out_problem;
> +			}
> +			dso__reset_find_symbol_cache(map->dso);
> +		}
> +		return 0;
> +	}
> +
>  	/* If we have maps from kcore then we do not need or want any others */
>  	if (machine__uses_kcore(machine))
>  		return 0;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index d188b7588152..0653f313661d 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -353,6 +353,19 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
>  	return NULL;
>  }
>  
> +int symbols__erase(struct rb_root *symbols, u64 ip)
> +{
> +	struct symbol *s;
> +
> +	s = symbols__find(symbols, ip);
> +	if (!s)
> +		return -ENOENT;
> +
> +	rb_erase(&s->rb_node, symbols);
> +	symbol__delete(s);
> +	return 0;
> +}
> +
>  static struct symbol *symbols__first(struct rb_root *symbols)
>  {
>  	struct rb_node *n = rb_first(symbols);
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index f25fae4b5743..92ef31953d9a 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -310,6 +310,7 @@ char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
>  
>  void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
>  void symbols__insert(struct rb_root *symbols, struct symbol *sym);
> +int symbols__erase(struct rb_root *symbols, u64 ip);
>  void symbols__fixup_duplicate(struct rb_root *symbols);
>  void symbols__fixup_end(struct rb_root *symbols);
>  void map_groups__fixup_end(struct map_groups *mg);
> -- 
> 2.17.1
Arnaldo Carvalho de Melo Sept. 20, 2018, 2:05 p.m. UTC | #2
Em Thu, Sep 20, 2018 at 10:36:17AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Wed, Sep 19, 2018 at 03:39:35PM -0700, Alexei Starovoitov escreveu:
> > Recognize JITed bpf prog load/unload events.
> > Add/remove kernel symbols accordingly.
> > 
> > Signed-off-by: Alexei Starovoitov <ast@kernel.org>
> > ---
> >  tools/perf/util/machine.c | 27 +++++++++++++++++++++++++++
> >  tools/perf/util/symbol.c  | 13 +++++++++++++
> >  tools/perf/util/symbol.h  |  1 +
> >  3 files changed, 41 insertions(+)
> > 
> > diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
> > index c4acd2001db0..ae4f8a0fdc7e 100644
> > --- a/tools/perf/util/machine.c
> > +++ b/tools/perf/util/machine.c
> > @@ -25,6 +25,7 @@
> >  #include "sane_ctype.h"
> >  #include <symbol/kallsyms.h>
> >  #include <linux/mman.h>
> > +#include <linux/magic.h>
> >  
> >  static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
> >  
> > @@ -1460,6 +1461,32 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
> >  	enum dso_kernel_type kernel_type;
> >  	bool is_kernel_mmap;
> >  
> > +	/* process JITed bpf programs load/unload events */
> > +	if (event->mmap.pid == ~0u && event->mmap.tid == BPF_FS_MAGIC) {
> 
> 
> So, this would be in machine__process_kernel_munmap-event(machine), etc,
> no check for BPF_FS_MAGIC would be needed with a PERF_RECORD_MUNMAP.
> 
> > +		struct symbol *sym;
> > +		u64 ip;
> > +
> > +		map = map_groups__find(&machine->kmaps, event->mmap.start);
> > +		if (!map) {
> > +			pr_err("No kernel map for IP %lx\n", event->mmap.start);
> > +			goto out_problem;
> > +		}
> > +		ip = event->mmap.start - map->start + map->pgoff;
> > +		if (event->mmap.filename[0]) {
> > +			sym = symbol__new(ip, event->mmap.len, 0, 0,
> > +					  event->mmap.filename);
> 
> Humm, so the bpf program would be just one symbol... bpf-to-bpf calls
> will be to a different bpf program, right? 
> 
> /me goes to read https://lwn.net/Articles/741773/
>                  "[PATCH bpf-next 00/13] bpf: introduce function calls"

After reading it, yeah, I think we need some way to access a symbol
table for a BPF program, and also its binary so that we can do
annotation, static (perf annotate) and live (perf top), was this already
considered? I think one can get the binary for a program giving
sufficient perms somehow, right? One other thing I need to catch up 8-)

- Arnaldo
 
> > +			dso__insert_symbol(map->dso, sym);
> > +		} else {
> > +			if (symbols__erase(&map->dso->symbols, ip)) {
> > +				pr_err("No bpf prog at IP %lx/%lx\n",
> > +				       event->mmap.start, ip);
> > +				goto out_problem;
> > +			}
> > +			dso__reset_find_symbol_cache(map->dso);
> > +		}
> > +		return 0;
> > +	}
> > +
> >  	/* If we have maps from kcore then we do not need or want any others */
> >  	if (machine__uses_kcore(machine))
> >  		return 0;
> > diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> > index d188b7588152..0653f313661d 100644
> > --- a/tools/perf/util/symbol.c
> > +++ b/tools/perf/util/symbol.c
> > @@ -353,6 +353,19 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
> >  	return NULL;
> >  }
> >  
> > +int symbols__erase(struct rb_root *symbols, u64 ip)
> > +{
> > +	struct symbol *s;
> > +
> > +	s = symbols__find(symbols, ip);
> > +	if (!s)
> > +		return -ENOENT;
> > +
> > +	rb_erase(&s->rb_node, symbols);
> > +	symbol__delete(s);
> > +	return 0;
> > +}
> > +
> >  static struct symbol *symbols__first(struct rb_root *symbols)
> >  {
> >  	struct rb_node *n = rb_first(symbols);
> > diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> > index f25fae4b5743..92ef31953d9a 100644
> > --- a/tools/perf/util/symbol.h
> > +++ b/tools/perf/util/symbol.h
> > @@ -310,6 +310,7 @@ char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
> >  
> >  void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
> >  void symbols__insert(struct rb_root *symbols, struct symbol *sym);
> > +int symbols__erase(struct rb_root *symbols, u64 ip);
> >  void symbols__fixup_duplicate(struct rb_root *symbols);
> >  void symbols__fixup_end(struct rb_root *symbols);
> >  void map_groups__fixup_end(struct map_groups *mg);
> > -- 
> > 2.17.1
Song Liu Sept. 21, 2018, 10:57 p.m. UTC | #3
On Wed, Sep 19, 2018 at 3:51 PM Alexei Starovoitov <ast@kernel.org> wrote:
>
> Recognize JITed bpf prog load/unload events.
> Add/remove kernel symbols accordingly.
>
> Signed-off-by: Alexei Starovoitov <ast@kernel.org>

Acked-by: Song Liu <songliubraving@fb.com>

> ---
>  tools/perf/util/machine.c | 27 +++++++++++++++++++++++++++
>  tools/perf/util/symbol.c  | 13 +++++++++++++
>  tools/perf/util/symbol.h  |  1 +
>  3 files changed, 41 insertions(+)
>
> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
> index c4acd2001db0..ae4f8a0fdc7e 100644
> --- a/tools/perf/util/machine.c
> +++ b/tools/perf/util/machine.c
> @@ -25,6 +25,7 @@
>  #include "sane_ctype.h"
>  #include <symbol/kallsyms.h>
>  #include <linux/mman.h>
> +#include <linux/magic.h>
>
>  static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
>
> @@ -1460,6 +1461,32 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
>         enum dso_kernel_type kernel_type;
>         bool is_kernel_mmap;
>
> +       /* process JITed bpf programs load/unload events */
> +       if (event->mmap.pid == ~0u && event->mmap.tid == BPF_FS_MAGIC) {
> +               struct symbol *sym;
> +               u64 ip;
> +
> +               map = map_groups__find(&machine->kmaps, event->mmap.start);
> +               if (!map) {
> +                       pr_err("No kernel map for IP %lx\n", event->mmap.start);
> +                       goto out_problem;
> +               }
> +               ip = event->mmap.start - map->start + map->pgoff;
> +               if (event->mmap.filename[0]) {
> +                       sym = symbol__new(ip, event->mmap.len, 0, 0,
> +                                         event->mmap.filename);
> +                       dso__insert_symbol(map->dso, sym);
> +               } else {
> +                       if (symbols__erase(&map->dso->symbols, ip)) {
> +                               pr_err("No bpf prog at IP %lx/%lx\n",
> +                                      event->mmap.start, ip);
> +                               goto out_problem;
> +                       }
> +                       dso__reset_find_symbol_cache(map->dso);
> +               }
> +               return 0;
> +       }
> +
>         /* If we have maps from kcore then we do not need or want any others */
>         if (machine__uses_kcore(machine))
>                 return 0;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index d188b7588152..0653f313661d 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -353,6 +353,19 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
>         return NULL;
>  }
>
> +int symbols__erase(struct rb_root *symbols, u64 ip)
> +{
> +       struct symbol *s;
> +
> +       s = symbols__find(symbols, ip);
> +       if (!s)
> +               return -ENOENT;
> +
> +       rb_erase(&s->rb_node, symbols);
> +       symbol__delete(s);
> +       return 0;
> +}
> +
>  static struct symbol *symbols__first(struct rb_root *symbols)
>  {
>         struct rb_node *n = rb_first(symbols);
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index f25fae4b5743..92ef31953d9a 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -310,6 +310,7 @@ char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
>
>  void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
>  void symbols__insert(struct rb_root *symbols, struct symbol *sym);
> +int symbols__erase(struct rb_root *symbols, u64 ip);
>  void symbols__fixup_duplicate(struct rb_root *symbols);
>  void symbols__fixup_end(struct rb_root *symbols);
>  void map_groups__fixup_end(struct map_groups *mg);
> --
> 2.17.1
>
diff mbox series

Patch

diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index c4acd2001db0..ae4f8a0fdc7e 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -25,6 +25,7 @@ 
 #include "sane_ctype.h"
 #include <symbol/kallsyms.h>
 #include <linux/mman.h>
+#include <linux/magic.h>
 
 static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
 
@@ -1460,6 +1461,32 @@  static int machine__process_kernel_mmap_event(struct machine *machine,
 	enum dso_kernel_type kernel_type;
 	bool is_kernel_mmap;
 
+	/* process JITed bpf programs load/unload events */
+	if (event->mmap.pid == ~0u && event->mmap.tid == BPF_FS_MAGIC) {
+		struct symbol *sym;
+		u64 ip;
+
+		map = map_groups__find(&machine->kmaps, event->mmap.start);
+		if (!map) {
+			pr_err("No kernel map for IP %lx\n", event->mmap.start);
+			goto out_problem;
+		}
+		ip = event->mmap.start - map->start + map->pgoff;
+		if (event->mmap.filename[0]) {
+			sym = symbol__new(ip, event->mmap.len, 0, 0,
+					  event->mmap.filename);
+			dso__insert_symbol(map->dso, sym);
+		} else {
+			if (symbols__erase(&map->dso->symbols, ip)) {
+				pr_err("No bpf prog at IP %lx/%lx\n",
+				       event->mmap.start, ip);
+				goto out_problem;
+			}
+			dso__reset_find_symbol_cache(map->dso);
+		}
+		return 0;
+	}
+
 	/* If we have maps from kcore then we do not need or want any others */
 	if (machine__uses_kcore(machine))
 		return 0;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index d188b7588152..0653f313661d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -353,6 +353,19 @@  static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
 	return NULL;
 }
 
+int symbols__erase(struct rb_root *symbols, u64 ip)
+{
+	struct symbol *s;
+
+	s = symbols__find(symbols, ip);
+	if (!s)
+		return -ENOENT;
+
+	rb_erase(&s->rb_node, symbols);
+	symbol__delete(s);
+	return 0;
+}
+
 static struct symbol *symbols__first(struct rb_root *symbols)
 {
 	struct rb_node *n = rb_first(symbols);
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index f25fae4b5743..92ef31953d9a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -310,6 +310,7 @@  char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name);
 
 void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
 void symbols__insert(struct rb_root *symbols, struct symbol *sym);
+int symbols__erase(struct rb_root *symbols, u64 ip);
 void symbols__fixup_duplicate(struct rb_root *symbols);
 void symbols__fixup_end(struct rb_root *symbols);
 void map_groups__fixup_end(struct map_groups *mg);