diff mbox series

[v9,perf,bpf,12/15] perf, bpf: enable annotation of bpf program

Message ID 20190312053051.2690567-13-songliubraving@fb.com
State Awaiting Upstream
Delegated to: BPF Maintainers
Headers show
Series perf annotation of BPF programs | expand

Commit Message

Song Liu March 12, 2019, 5:30 a.m. UTC
This patch enables the annotation of bpf program.

A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
calls into a new function symbol__disassemble_bpf(), where annotation
line information is filled based bpf_prog_info and btf saved in given
perf_env.

symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.

Signed-off-by: Song Liu <songliubraving@fb.com>
---
 tools/build/Makefile.feature |   6 +-
 tools/perf/Makefile.config   |   4 +
 tools/perf/util/annotate.c   | 150 ++++++++++++++++++++++++++++++++++-
 tools/perf/util/dso.c        |   1 +
 tools/perf/util/dso.h        |  32 +++++---
 tools/perf/util/symbol.c     |   1 +
 6 files changed, 180 insertions(+), 14 deletions(-)

Comments

Arnaldo Carvalho de Melo March 18, 2019, 4:38 p.m. UTC | #1
Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
> This patch enables the annotation of bpf program.
> 
> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
> calls into a new function symbol__disassemble_bpf(), where annotation
> line information is filled based bpf_prog_info and btf saved in given
> perf_env.
> 
> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
> 
> Signed-off-by: Song Liu <songliubraving@fb.com>
> ---
>  tools/build/Makefile.feature |   6 +-
>  tools/perf/Makefile.config   |   4 +

I see the changes to these two files, but I can't see the feature test
that it triggers, forgot to do a git-add? Or is it in an upcoming patch
in this series?

After applying this test it "works":

  make: Entering directory '/home/acme/git/perf/tools/perf'
    BUILD:   Doing 'make -j8' parallel build

  Auto-detecting system features:
  ...                         dwarf: [ on  ]
  ...            dwarf_getlocations: [ on  ]
  <SNIP>
  ...                           bpf: [ on  ]
  ...                        libaio: [ on  ]
  ...        disassembler-four-args: [ on  ]

Because you added it to FEATURE_TESTS_BASIC, and this means that if
tools/build/feature/test-all.c builds, then what is in
FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
tools/build/feature/test-all.c, so it works because all the other
features are present.

Take a look at:

  2a07d814747b ("tools build feature: Check if libaio is available")

To see what needs to be done.

Either way, its interesting to break this patch in two, one adding the
feature test and another to use it, i.e. the second patch out of this
should have the commit log message in this patch.

I've applied the patches up to before this one and will continue
processing other patches while you address this.

Thanks,

- Arnaldo

>  tools/perf/util/annotate.c   | 150 ++++++++++++++++++++++++++++++++++-
>  tools/perf/util/dso.c        |   1 +
>  tools/perf/util/dso.h        |  32 +++++---
>  tools/perf/util/symbol.c     |   1 +
>  6 files changed, 180 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
> index 61e46d54a67c..8d3864b061f3 100644
> --- a/tools/build/Makefile.feature
> +++ b/tools/build/Makefile.feature
> @@ -66,7 +66,8 @@ FEATURE_TESTS_BASIC :=                  \
>          sched_getcpu			\
>          sdt				\
>          setns				\
> -        libaio
> +        libaio				\
> +        disassembler-four-args
>  
>  # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
>  # of all feature tests
> @@ -118,7 +119,8 @@ FEATURE_DISPLAY ?=              \
>           lzma                   \
>           get_cpuid              \
>           bpf			\
> -         libaio
> +         libaio			\
> +         disassembler-four-args
>  
>  # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
>  # If in the future we need per-feature checks/flags for features not
> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
> index df4ad45599ca..c51b59e43dcc 100644
> --- a/tools/perf/Makefile.config
> +++ b/tools/perf/Makefile.config
> @@ -808,6 +808,10 @@ ifdef HAVE_KVM_STAT_SUPPORT
>      CFLAGS += -DHAVE_KVM_STAT_SUPPORT
>  endif
>  
> +ifeq ($(feature-disassembler-four-args), 1)
> +    CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
> +endif
> +
>  ifeq (${IS_64_BIT}, 1)
>    ifndef NO_PERF_READ_VDSO32
>      $(call feature_check,compile-32)
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index 5f6dbbf5d749..e492b19a157c 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
> @@ -10,6 +10,10 @@
>  #include <errno.h>
>  #include <inttypes.h>
>  #include <libgen.h>
> +#include <bpf/bpf.h>
> +#include <bpf/btf.h>
> +#include <bpf/libbpf.h>
> +#include <linux/btf.h>
>  #include "util.h"
>  #include "ui/ui.h"
>  #include "sort.h"
> @@ -24,6 +28,7 @@
>  #include "annotate.h"
>  #include "evsel.h"
>  #include "evlist.h"
> +#include "bpf-event.h"
>  #include "block-range.h"
>  #include "string2.h"
>  #include "arch/common.h"
> @@ -31,6 +36,9 @@
>  #include <pthread.h>
>  #include <linux/bitops.h>
>  #include <linux/kernel.h>
> +#include <bfd.h>
> +#include <dis-asm.h>
> +#include <bpf/libbpf.h>
>  
>  /* FIXME: For the HE_COLORSET */
>  #include "ui/browser.h"
> @@ -1674,6 +1682,144 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
>  	return 0;
>  }
>  
> +static int symbol__disassemble_bpf(struct symbol *sym,
> +				   struct annotate_args *args)
> +{
> +	struct annotation *notes = symbol__annotation(sym);
> +	struct annotation_options *opts = args->options;
> +	struct bpf_prog_info_linear *info_linear;
> +	struct bpf_prog_linfo *prog_linfo = NULL;
> +	struct bpf_prog_info_node *info_node;
> +	int len = sym->end - sym->start;
> +	disassembler_ftype disassemble;
> +	struct map *map = args->ms.map;
> +	struct disassemble_info info;
> +	struct dso *dso = map->dso;
> +	int pc = 0, count, sub_id;
> +	struct btf *btf = NULL;
> +	char tpath[PATH_MAX];
> +	size_t buf_size;
> +	int nr_skip = 0;
> +	int ret = -1;
> +	char *buf;
> +	bfd *bfdf;
> +	FILE *s;
> +
> +	if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
> +		return -1;
> +
> +	pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
> +		 sym->name, sym->start, sym->end - sym->start);
> +
> +	memset(tpath, 0, sizeof(tpath));
> +	perf_exe(tpath, sizeof(tpath));
> +
> +	bfdf = bfd_openr(tpath, NULL);
> +	assert(bfdf);
> +	assert(bfd_check_format(bfdf, bfd_object));
> +
> +	s = open_memstream(&buf, &buf_size);
> +	if (!s)
> +		goto out;
> +	init_disassemble_info(&info, s,
> +			      (fprintf_ftype) fprintf);
> +
> +	info.arch = bfd_get_arch(bfdf);
> +	info.mach = bfd_get_mach(bfdf);
> +
> +	info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
> +						 dso->bpf_prog.id);
> +	if (!info_node)
> +		goto out;
> +	info_linear = info_node->info_linear;
> +	sub_id = dso->bpf_prog.sub_id;
> +
> +	info.buffer = (void *)(info_linear->info.jited_prog_insns);
> +	info.buffer_length = info_linear->info.jited_prog_len;
> +
> +	if (info_linear->info.nr_line_info)
> +		prog_linfo = bpf_prog_linfo__new(&info_linear->info);
> +
> +	if (info_linear->info.btf_id) {
> +		struct btf_node *node;
> +
> +		node = perf_env__find_btf(dso->bpf_prog.env,
> +					  info_linear->info.btf_id);
> +		if (node)
> +			btf = btf__new((__u8 *)(node->data),
> +				       node->data_size);
> +	}
> +
> +	disassemble_init_for_target(&info);
> +
> +#ifdef DISASM_FOUR_ARGS_SIGNATURE
> +	disassemble = disassembler(info.arch,
> +				   bfd_big_endian(bfdf),
> +				   info.mach,
> +				   bfdf);
> +#else
> +	disassemble = disassembler(bfdf);
> +#endif
> +	assert(disassemble);
> +
> +	fflush(s);
> +	do {
> +		const struct bpf_line_info *linfo = NULL;
> +		struct disasm_line *dl;
> +		size_t prev_buf_size;
> +		const char *srcline;
> +		u64 addr;
> +
> +		addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
> +		count = disassemble(pc, &info);
> +
> +		if (prog_linfo)
> +			linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
> +								addr, sub_id,
> +								nr_skip);
> +
> +		if (linfo && btf) {
> +			srcline = btf__name_by_offset(btf, linfo->line_off);
> +			nr_skip++;
> +		} else
> +			srcline = NULL;
> +
> +		fprintf(s, "\n");
> +		prev_buf_size = buf_size;
> +		fflush(s);
> +
> +		if (!opts->hide_src_code && srcline) {
> +			args->offset = -1;
> +			args->line = strdup(srcline);
> +			args->line_nr = 0;
> +			args->ms.sym  = sym;
> +			dl = disasm_line__new(args);
> +			if (dl) {
> +				annotation_line__add(&dl->al,
> +						     &notes->src->source);
> +			}
> +		}
> +
> +		args->offset = pc;
> +		args->line = buf + prev_buf_size;
> +		args->line_nr = 0;
> +		args->ms.sym  = sym;
> +		dl = disasm_line__new(args);
> +		if (dl)
> +			annotation_line__add(&dl->al, &notes->src->source);
> +
> +		pc += count;
> +	} while (count > 0 && pc < len);
> +
> +	ret = 0;
> +out:
> +	free(prog_linfo);
> +	free(btf);
> +	fclose(s);
> +	bfd_close(bfdf);
> +	return ret;
> +}
> +
>  static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
>  {
>  	struct annotation_options *opts = args->options;
> @@ -1701,7 +1847,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
>  	pr_debug("annotating [%p] %30s : [%p] %30s\n",
>  		 dso, dso->long_name, sym, sym->name);
>  
> -	if (dso__is_kcore(dso)) {
> +	if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
> +		return symbol__disassemble_bpf(sym, args);
> +	} else if (dso__is_kcore(dso)) {
>  		kce.kcore_filename = symfs_filename;
>  		kce.addr = map__rip_2objdump(map, sym->start);
>  		kce.offs = sym->start;
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index ba58ba603b69..58547c468c65 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
>  	case DSO_BINARY_TYPE__KALLSYMS:
>  	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
>  	case DSO_BINARY_TYPE__JAVA_JIT:
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
>  	case DSO_BINARY_TYPE__NOT_FOUND:
>  		ret = -1;
>  		break;
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index bb417c54c25a..c274b5aa839d 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -14,6 +14,7 @@
>  
>  struct machine;
>  struct map;
> +struct perf_env;
>  
>  enum dso_binary_type {
>  	DSO_BINARY_TYPE__KALLSYMS = 0,
> @@ -35,6 +36,7 @@ enum dso_binary_type {
>  	DSO_BINARY_TYPE__KCORE,
>  	DSO_BINARY_TYPE__GUEST_KCORE,
>  	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> +	DSO_BINARY_TYPE__BPF_PROG_INFO,
>  	DSO_BINARY_TYPE__NOT_FOUND,
>  };
>  
> @@ -178,17 +180,25 @@ struct dso {
>  	struct auxtrace_cache *auxtrace_cache;
>  	int		 comp;
>  
> -	/* dso data file */
> -	struct {
> -		struct rb_root	 cache;
> -		int		 fd;
> -		int		 status;
> -		u32		 status_seen;
> -		size_t		 file_size;
> -		struct list_head open_entry;
> -		u64		 debug_frame_offset;
> -		u64		 eh_frame_hdr_offset;
> -	} data;
> +	union {
> +		/* dso data file */
> +		struct {
> +			struct rb_root	 cache;
> +			int		 fd;
> +			int		 status;
> +			u32		 status_seen;
> +			size_t		 file_size;
> +			struct list_head open_entry;
> +			u64		 debug_frame_offset;
> +			u64		 eh_frame_hdr_offset;
> +		} data;
> +		/* bpf prog information */
> +		struct {
> +			u32		id;
> +			u32		sub_id;
> +			struct perf_env	*env;
> +		} bpf_prog;
> +	};
>  
>  	union { /* Tool specific area */
>  		void	 *priv;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 758bf5f74e6e..4e2e304d4037 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1451,6 +1451,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
>  	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
>  		return true;
>  
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
>  	case DSO_BINARY_TYPE__NOT_FOUND:
>  	default:
>  		return false;
> -- 
> 2.17.1
Arnaldo Carvalho de Melo March 18, 2019, 4:43 p.m. UTC | #2
Em Mon, Mar 18, 2019 at 01:38:48PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
> > This patch enables the annotation of bpf program.
> > 
> > A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
> > programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
> > calls into a new function symbol__disassemble_bpf(), where annotation
> > line information is filled based bpf_prog_info and btf saved in given
> > perf_env.
> > 
> > symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
> > 
> > Signed-off-by: Song Liu <songliubraving@fb.com>
> > ---
> >  tools/build/Makefile.feature |   6 +-
> >  tools/perf/Makefile.config   |   4 +
> 
> I see the changes to these two files, but I can't see the feature test
> that it triggers, forgot to do a git-add? Or is it in an upcoming patch
> in this series?
> 
> After applying this test it "works":
> 
>   make: Entering directory '/home/acme/git/perf/tools/perf'
>     BUILD:   Doing 'make -j8' parallel build
> 
>   Auto-detecting system features:
>   ...                         dwarf: [ on  ]
>   ...            dwarf_getlocations: [ on  ]
>   <SNIP>
>   ...                           bpf: [ on  ]
>   ...                        libaio: [ on  ]
>   ...        disassembler-four-args: [ on  ]
> 
> Because you added it to FEATURE_TESTS_BASIC, and this means that if
> tools/build/feature/test-all.c builds, then what is in
> FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
> tools/build/feature/test-all.c, so it works because all the other
> features are present.
> 
> Take a look at:
> 
>   2a07d814747b ("tools build feature: Check if libaio is available")
> 
> To see what needs to be done.
> 
> Either way, its interesting to break this patch in two, one adding the
> feature test and another to use it, i.e. the second patch out of this
> should have the commit log message in this patch.
> 
> I've applied the patches up to before this one and will continue
> processing other patches while you address this.

Ok, to continue processing the other patches I chunked out the part
below into a 3rd patch from the above one and have it applied already.

commit f326de312abc3657b0397817c66cd7e1540655f7
Author: Song Liu <songliubraving@fb.com>
Date:   Mon Mar 11 22:30:48 2019 -0700

    perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO
    
    Introduce a new dso type DSO_BINARY_TYPE__BPF_PROG_INFO for BPF programs. In
    symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso will call into a new
    function symbol__disassemble_bpf() in an upcoming patch, where annotation line
    information is filled based bpf_prog_info and btf saved in given perf_env.
    
    Signed-off-by: Song Liu <songliubraving@fb.com>
    Reviewed-by: Jiri Olsa <jolsa@kernel.org>
    Cc: Alexei Starovoitov <ast@kernel.org>
    Cc: Daniel Borkmann <daniel@iogearbox.net>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Stanislav Fomichev <sdf@google.com>
    Cc: kernel-team@fb.com
    Link: http://lkml.kernel.org/r/20190312053051.2690567-13-songliubraving@fb.com
    [ split from a larger patch ]
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index ba58ba603b69..58547c468c65 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
 	case DSO_BINARY_TYPE__KALLSYMS:
 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
 	case DSO_BINARY_TYPE__JAVA_JIT:
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
 	case DSO_BINARY_TYPE__NOT_FOUND:
 		ret = -1;
 		break;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bb417c54c25a..c274b5aa839d 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -14,6 +14,7 @@
 
 struct machine;
 struct map;
+struct perf_env;
 
 enum dso_binary_type {
 	DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -35,6 +36,7 @@ enum dso_binary_type {
 	DSO_BINARY_TYPE__KCORE,
 	DSO_BINARY_TYPE__GUEST_KCORE,
 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+	DSO_BINARY_TYPE__BPF_PROG_INFO,
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
@@ -178,17 +180,25 @@ struct dso {
 	struct auxtrace_cache *auxtrace_cache;
 	int		 comp;
 
-	/* dso data file */
-	struct {
-		struct rb_root	 cache;
-		int		 fd;
-		int		 status;
-		u32		 status_seen;
-		size_t		 file_size;
-		struct list_head open_entry;
-		u64		 debug_frame_offset;
-		u64		 eh_frame_hdr_offset;
-	} data;
+	union {
+		/* dso data file */
+		struct {
+			struct rb_root	 cache;
+			int		 fd;
+			int		 status;
+			u32		 status_seen;
+			size_t		 file_size;
+			struct list_head open_entry;
+			u64		 debug_frame_offset;
+			u64		 eh_frame_hdr_offset;
+		} data;
+		/* bpf prog information */
+		struct {
+			u32		id;
+			u32		sub_id;
+			struct perf_env	*env;
+		} bpf_prog;
+	};
 
 	union { /* Tool specific area */
 		void	 *priv;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 58442ca5e3c4..5cbad55cd99d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1455,6 +1455,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
 		return true;
 
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
 	case DSO_BINARY_TYPE__NOT_FOUND:
 	default:
 		return false;
Song Liu March 19, 2019, 6:05 a.m. UTC | #3
Sorry for the late response. 

> On Mar 18, 2019, at 9:38 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> 
> Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
>> This patch enables the annotation of bpf program.
>> 
>> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
>> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
>> calls into a new function symbol__disassemble_bpf(), where annotation
>> line information is filled based bpf_prog_info and btf saved in given
>> perf_env.
>> 
>> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
>> 
>> Signed-off-by: Song Liu <songliubraving@fb.com>
>> ---
>> tools/build/Makefile.feature |   6 +-
>> tools/perf/Makefile.config   |   4 +
> 
> I see the changes to these two files, but I can't see the feature test
> that it triggers, forgot to do a git-add? Or is it in an upcoming patch
> in this series?

test-disassembler-four-args.c is an existing test used by bpftool.
It was added in fb982666e380c1632a74495b68b3c33a66e76430 .  

> 
> After applying this test it "works":
> 
>  make: Entering directory '/home/acme/git/perf/tools/perf'
>    BUILD:   Doing 'make -j8' parallel build
> 
>  Auto-detecting system features:
>  ...                         dwarf: [ on  ]
>  ...            dwarf_getlocations: [ on  ]
>  <SNIP>
>  ...                           bpf: [ on  ]
>  ...                        libaio: [ on  ]
>  ...        disassembler-four-args: [ on  ]
> 
> Because you added it to FEATURE_TESTS_BASIC, and this means that if
> tools/build/feature/test-all.c builds, then what is in
> FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
> tools/build/feature/test-all.c, so it works because all the other
> features are present.
> 
> Take a look at:
> 
>  2a07d814747b ("tools build feature: Check if libaio is available")
> 
> To see what needs to be done.

I used different versions of gcc to verify that current version of the 
patch works for both test-succeed and test-fail cases. I guess something 
like the following is needed? But the test does work without it. 

Thanks,
Song


diff --git i/tools/build/feature/test-all.c w/tools/build/feature/test-all.c
index e903b86b742f..7853e6d91090 100644
--- i/tools/build/feature/test-all.c
+++ w/tools/build/feature/test-all.c
@@ -178,6 +178,10 @@
 # include "test-reallocarray.c"
 #undef main

+#define main main_test_disassembler_four_args
+# include "test-disassembler-four-args.c"
+#undef main
+
 int main(int argc, char *argv[])
 {
        main_test_libpython();
@@ -219,6 +223,7 @@ int main(int argc, char *argv[])
        main_test_setns();
        main_test_libaio();
        main_test_reallocarray();
+       main_test_disassembler_four_args();

        return 0;
 }


> 
> Either way, its interesting to break this patch in two, one adding the
> feature test and another to use it, i.e. the second patch out of this
> should have the commit log message in this patch.
> 
> I've applied the patches up to before this one and will continue
> processing other patches while you address this.
> 
> Thanks,
> 
> - Arnaldo
> 
>> tools/perf/util/annotate.c   | 150 ++++++++++++++++++++++++++++++++++-
>> tools/perf/util/dso.c        |   1 +
>> tools/perf/util/dso.h        |  32 +++++---
>> tools/perf/util/symbol.c     |   1 +
>> 6 files changed, 180 insertions(+), 14 deletions(-)
>> 
>> diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
>> index 61e46d54a67c..8d3864b061f3 100644
>> --- a/tools/build/Makefile.feature
>> +++ b/tools/build/Makefile.feature
>> @@ -66,7 +66,8 @@ FEATURE_TESTS_BASIC :=                  \
>>         sched_getcpu			\
>>         sdt				\
>>         setns				\
>> -        libaio
>> +        libaio				\
>> +        disassembler-four-args
>> 
>> # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
>> # of all feature tests
>> @@ -118,7 +119,8 @@ FEATURE_DISPLAY ?=              \
>>          lzma                   \
>>          get_cpuid              \
>>          bpf			\
>> -         libaio
>> +         libaio			\
>> +         disassembler-four-args
>> 
>> # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
>> # If in the future we need per-feature checks/flags for features not
>> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
>> index df4ad45599ca..c51b59e43dcc 100644
>> --- a/tools/perf/Makefile.config
>> +++ b/tools/perf/Makefile.config
>> @@ -808,6 +808,10 @@ ifdef HAVE_KVM_STAT_SUPPORT
>>     CFLAGS += -DHAVE_KVM_STAT_SUPPORT
>> endif
>> 
>> +ifeq ($(feature-disassembler-four-args), 1)
>> +    CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
>> +endif
>> +
>> ifeq (${IS_64_BIT}, 1)
>>   ifndef NO_PERF_READ_VDSO32
>>     $(call feature_check,compile-32)
>> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
>> index 5f6dbbf5d749..e492b19a157c 100644
>> --- a/tools/perf/util/annotate.c
>> +++ b/tools/perf/util/annotate.c
>> @@ -10,6 +10,10 @@
>> #include <errno.h>
>> #include <inttypes.h>
>> #include <libgen.h>
>> +#include <bpf/bpf.h>
>> +#include <bpf/btf.h>
>> +#include <bpf/libbpf.h>
>> +#include <linux/btf.h>
>> #include "util.h"
>> #include "ui/ui.h"
>> #include "sort.h"
>> @@ -24,6 +28,7 @@
>> #include "annotate.h"
>> #include "evsel.h"
>> #include "evlist.h"
>> +#include "bpf-event.h"
>> #include "block-range.h"
>> #include "string2.h"
>> #include "arch/common.h"
>> @@ -31,6 +36,9 @@
>> #include <pthread.h>
>> #include <linux/bitops.h>
>> #include <linux/kernel.h>
>> +#include <bfd.h>
>> +#include <dis-asm.h>
>> +#include <bpf/libbpf.h>
>> 
>> /* FIXME: For the HE_COLORSET */
>> #include "ui/browser.h"
>> @@ -1674,6 +1682,144 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
>> 	return 0;
>> }
>> 
>> +static int symbol__disassemble_bpf(struct symbol *sym,
>> +				   struct annotate_args *args)
>> +{
>> +	struct annotation *notes = symbol__annotation(sym);
>> +	struct annotation_options *opts = args->options;
>> +	struct bpf_prog_info_linear *info_linear;
>> +	struct bpf_prog_linfo *prog_linfo = NULL;
>> +	struct bpf_prog_info_node *info_node;
>> +	int len = sym->end - sym->start;
>> +	disassembler_ftype disassemble;
>> +	struct map *map = args->ms.map;
>> +	struct disassemble_info info;
>> +	struct dso *dso = map->dso;
>> +	int pc = 0, count, sub_id;
>> +	struct btf *btf = NULL;
>> +	char tpath[PATH_MAX];
>> +	size_t buf_size;
>> +	int nr_skip = 0;
>> +	int ret = -1;
>> +	char *buf;
>> +	bfd *bfdf;
>> +	FILE *s;
>> +
>> +	if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
>> +		return -1;
>> +
>> +	pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
>> +		 sym->name, sym->start, sym->end - sym->start);
>> +
>> +	memset(tpath, 0, sizeof(tpath));
>> +	perf_exe(tpath, sizeof(tpath));
>> +
>> +	bfdf = bfd_openr(tpath, NULL);
>> +	assert(bfdf);
>> +	assert(bfd_check_format(bfdf, bfd_object));
>> +
>> +	s = open_memstream(&buf, &buf_size);
>> +	if (!s)
>> +		goto out;
>> +	init_disassemble_info(&info, s,
>> +			      (fprintf_ftype) fprintf);
>> +
>> +	info.arch = bfd_get_arch(bfdf);
>> +	info.mach = bfd_get_mach(bfdf);
>> +
>> +	info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
>> +						 dso->bpf_prog.id);
>> +	if (!info_node)
>> +		goto out;
>> +	info_linear = info_node->info_linear;
>> +	sub_id = dso->bpf_prog.sub_id;
>> +
>> +	info.buffer = (void *)(info_linear->info.jited_prog_insns);
>> +	info.buffer_length = info_linear->info.jited_prog_len;
>> +
>> +	if (info_linear->info.nr_line_info)
>> +		prog_linfo = bpf_prog_linfo__new(&info_linear->info);
>> +
>> +	if (info_linear->info.btf_id) {
>> +		struct btf_node *node;
>> +
>> +		node = perf_env__find_btf(dso->bpf_prog.env,
>> +					  info_linear->info.btf_id);
>> +		if (node)
>> +			btf = btf__new((__u8 *)(node->data),
>> +				       node->data_size);
>> +	}
>> +
>> +	disassemble_init_for_target(&info);
>> +
>> +#ifdef DISASM_FOUR_ARGS_SIGNATURE
>> +	disassemble = disassembler(info.arch,
>> +				   bfd_big_endian(bfdf),
>> +				   info.mach,
>> +				   bfdf);
>> +#else
>> +	disassemble = disassembler(bfdf);
>> +#endif
>> +	assert(disassemble);
>> +
>> +	fflush(s);
>> +	do {
>> +		const struct bpf_line_info *linfo = NULL;
>> +		struct disasm_line *dl;
>> +		size_t prev_buf_size;
>> +		const char *srcline;
>> +		u64 addr;
>> +
>> +		addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
>> +		count = disassemble(pc, &info);
>> +
>> +		if (prog_linfo)
>> +			linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
>> +								addr, sub_id,
>> +								nr_skip);
>> +
>> +		if (linfo && btf) {
>> +			srcline = btf__name_by_offset(btf, linfo->line_off);
>> +			nr_skip++;
>> +		} else
>> +			srcline = NULL;
>> +
>> +		fprintf(s, "\n");
>> +		prev_buf_size = buf_size;
>> +		fflush(s);
>> +
>> +		if (!opts->hide_src_code && srcline) {
>> +			args->offset = -1;
>> +			args->line = strdup(srcline);
>> +			args->line_nr = 0;
>> +			args->ms.sym  = sym;
>> +			dl = disasm_line__new(args);
>> +			if (dl) {
>> +				annotation_line__add(&dl->al,
>> +						     &notes->src->source);
>> +			}
>> +		}
>> +
>> +		args->offset = pc;
>> +		args->line = buf + prev_buf_size;
>> +		args->line_nr = 0;
>> +		args->ms.sym  = sym;
>> +		dl = disasm_line__new(args);
>> +		if (dl)
>> +			annotation_line__add(&dl->al, &notes->src->source);
>> +
>> +		pc += count;
>> +	} while (count > 0 && pc < len);
>> +
>> +	ret = 0;
>> +out:
>> +	free(prog_linfo);
>> +	free(btf);
>> +	fclose(s);
>> +	bfd_close(bfdf);
>> +	return ret;
>> +}
>> +
>> static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
>> {
>> 	struct annotation_options *opts = args->options;
>> @@ -1701,7 +1847,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
>> 	pr_debug("annotating [%p] %30s : [%p] %30s\n",
>> 		 dso, dso->long_name, sym, sym->name);
>> 
>> -	if (dso__is_kcore(dso)) {
>> +	if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
>> +		return symbol__disassemble_bpf(sym, args);
>> +	} else if (dso__is_kcore(dso)) {
>> 		kce.kcore_filename = symfs_filename;
>> 		kce.addr = map__rip_2objdump(map, sym->start);
>> 		kce.offs = sym->start;
>> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
>> index ba58ba603b69..58547c468c65 100644
>> --- a/tools/perf/util/dso.c
>> +++ b/tools/perf/util/dso.c
>> @@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
>> 	case DSO_BINARY_TYPE__KALLSYMS:
>> 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
>> 	case DSO_BINARY_TYPE__JAVA_JIT:
>> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
>> 	case DSO_BINARY_TYPE__NOT_FOUND:
>> 		ret = -1;
>> 		break;
>> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
>> index bb417c54c25a..c274b5aa839d 100644
>> --- a/tools/perf/util/dso.h
>> +++ b/tools/perf/util/dso.h
>> @@ -14,6 +14,7 @@
>> 
>> struct machine;
>> struct map;
>> +struct perf_env;
>> 
>> enum dso_binary_type {
>> 	DSO_BINARY_TYPE__KALLSYMS = 0,
>> @@ -35,6 +36,7 @@ enum dso_binary_type {
>> 	DSO_BINARY_TYPE__KCORE,
>> 	DSO_BINARY_TYPE__GUEST_KCORE,
>> 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
>> +	DSO_BINARY_TYPE__BPF_PROG_INFO,
>> 	DSO_BINARY_TYPE__NOT_FOUND,
>> };
>> 
>> @@ -178,17 +180,25 @@ struct dso {
>> 	struct auxtrace_cache *auxtrace_cache;
>> 	int		 comp;
>> 
>> -	/* dso data file */
>> -	struct {
>> -		struct rb_root	 cache;
>> -		int		 fd;
>> -		int		 status;
>> -		u32		 status_seen;
>> -		size_t		 file_size;
>> -		struct list_head open_entry;
>> -		u64		 debug_frame_offset;
>> -		u64		 eh_frame_hdr_offset;
>> -	} data;
>> +	union {
>> +		/* dso data file */
>> +		struct {
>> +			struct rb_root	 cache;
>> +			int		 fd;
>> +			int		 status;
>> +			u32		 status_seen;
>> +			size_t		 file_size;
>> +			struct list_head open_entry;
>> +			u64		 debug_frame_offset;
>> +			u64		 eh_frame_hdr_offset;
>> +		} data;
>> +		/* bpf prog information */
>> +		struct {
>> +			u32		id;
>> +			u32		sub_id;
>> +			struct perf_env	*env;
>> +		} bpf_prog;
>> +	};
>> 
>> 	union { /* Tool specific area */
>> 		void	 *priv;
>> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
>> index 758bf5f74e6e..4e2e304d4037 100644
>> --- a/tools/perf/util/symbol.c
>> +++ b/tools/perf/util/symbol.c
>> @@ -1451,6 +1451,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
>> 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
>> 		return true;
>> 
>> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
>> 	case DSO_BINARY_TYPE__NOT_FOUND:
>> 	default:
>> 		return false;
>> -- 
>> 2.17.1
> 
> -- 
> 
> - Arnaldo
Song Liu March 19, 2019, 6:10 a.m. UTC | #4
> On Mar 18, 2019, at 9:43 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> 
> Em Mon, Mar 18, 2019 at 01:38:48PM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
>>> This patch enables the annotation of bpf program.
>>> 
>>> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
>>> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
>>> calls into a new function symbol__disassemble_bpf(), where annotation
>>> line information is filled based bpf_prog_info and btf saved in given
>>> perf_env.
>>> 
>>> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
>>> 
>>> Signed-off-by: Song Liu <songliubraving@fb.com>
>>> ---
>>> tools/build/Makefile.feature |   6 +-
>>> tools/perf/Makefile.config   |   4 +
>> 
>> I see the changes to these two files, but I can't see the feature test
>> that it triggers, forgot to do a git-add? Or is it in an upcoming patch
>> in this series?
>> 
>> After applying this test it "works":
>> 
>>  make: Entering directory '/home/acme/git/perf/tools/perf'
>>    BUILD:   Doing 'make -j8' parallel build
>> 
>>  Auto-detecting system features:
>>  ...                         dwarf: [ on  ]
>>  ...            dwarf_getlocations: [ on  ]
>>  <SNIP>
>>  ...                           bpf: [ on  ]
>>  ...                        libaio: [ on  ]
>>  ...        disassembler-four-args: [ on  ]
>> 
>> Because you added it to FEATURE_TESTS_BASIC, and this means that if
>> tools/build/feature/test-all.c builds, then what is in
>> FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
>> tools/build/feature/test-all.c, so it works because all the other
>> features are present.
>> 
>> Take a look at:
>> 
>>  2a07d814747b ("tools build feature: Check if libaio is available")
>> 
>> To see what needs to be done.
>> 
>> Either way, its interesting to break this patch in two, one adding the
>> feature test and another to use it, i.e. the second patch out of this
>> should have the commit log message in this patch.
>> 
>> I've applied the patches up to before this one and will continue
>> processing other patches while you address this.
> 
> Ok, to continue processing the other patches I chunked out the part
> below into a 3rd patch from the above one and have it applied already.

Could you please push applied patches to the tmp.perf/bpf-annotation 
branch? 

Thanks,
Song

> 
> commit f326de312abc3657b0397817c66cd7e1540655f7
> Author: Song Liu <songliubraving@fb.com>
> Date:   Mon Mar 11 22:30:48 2019 -0700
> 
>    perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO
> 
>    Introduce a new dso type DSO_BINARY_TYPE__BPF_PROG_INFO for BPF programs. In
>    symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso will call into a new
>    function symbol__disassemble_bpf() in an upcoming patch, where annotation line
>    information is filled based bpf_prog_info and btf saved in given perf_env.
> 
>    Signed-off-by: Song Liu <songliubraving@fb.com>
>    Reviewed-by: Jiri Olsa <jolsa@kernel.org>
>    Cc: Alexei Starovoitov <ast@kernel.org>
>    Cc: Daniel Borkmann <daniel@iogearbox.net>
>    Cc: Namhyung Kim <namhyung@kernel.org>
>    Cc: Peter Zijlstra <peterz@infradead.org>
>    Cc: Stanislav Fomichev <sdf@google.com>
>    Cc: kernel-team@fb.com
>    Link: http://lkml.kernel.org/r/20190312053051.2690567-13-songliubraving@fb.com
>    [ split from a larger patch ]
>    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> 
> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> index ba58ba603b69..58547c468c65 100644
> --- a/tools/perf/util/dso.c
> +++ b/tools/perf/util/dso.c
> @@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
> 	case DSO_BINARY_TYPE__KALLSYMS:
> 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> 	case DSO_BINARY_TYPE__JAVA_JIT:
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> 	case DSO_BINARY_TYPE__NOT_FOUND:
> 		ret = -1;
> 		break;
> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> index bb417c54c25a..c274b5aa839d 100644
> --- a/tools/perf/util/dso.h
> +++ b/tools/perf/util/dso.h
> @@ -14,6 +14,7 @@
> 
> struct machine;
> struct map;
> +struct perf_env;
> 
> enum dso_binary_type {
> 	DSO_BINARY_TYPE__KALLSYMS = 0,
> @@ -35,6 +36,7 @@ enum dso_binary_type {
> 	DSO_BINARY_TYPE__KCORE,
> 	DSO_BINARY_TYPE__GUEST_KCORE,
> 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> +	DSO_BINARY_TYPE__BPF_PROG_INFO,
> 	DSO_BINARY_TYPE__NOT_FOUND,
> };
> 
> @@ -178,17 +180,25 @@ struct dso {
> 	struct auxtrace_cache *auxtrace_cache;
> 	int		 comp;
> 
> -	/* dso data file */
> -	struct {
> -		struct rb_root	 cache;
> -		int		 fd;
> -		int		 status;
> -		u32		 status_seen;
> -		size_t		 file_size;
> -		struct list_head open_entry;
> -		u64		 debug_frame_offset;
> -		u64		 eh_frame_hdr_offset;
> -	} data;
> +	union {
> +		/* dso data file */
> +		struct {
> +			struct rb_root	 cache;
> +			int		 fd;
> +			int		 status;
> +			u32		 status_seen;
> +			size_t		 file_size;
> +			struct list_head open_entry;
> +			u64		 debug_frame_offset;
> +			u64		 eh_frame_hdr_offset;
> +		} data;
> +		/* bpf prog information */
> +		struct {
> +			u32		id;
> +			u32		sub_id;
> +			struct perf_env	*env;
> +		} bpf_prog;
> +	};
> 
> 	union { /* Tool specific area */
> 		void	 *priv;
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index 58442ca5e3c4..5cbad55cd99d 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -1455,6 +1455,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
> 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> 		return true;
> 
> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> 	case DSO_BINARY_TYPE__NOT_FOUND:
> 	default:
> 		return false;
Arnaldo Carvalho de Melo March 19, 2019, 1:37 p.m. UTC | #5
Em Tue, Mar 19, 2019 at 06:05:30AM +0000, Song Liu escreveu:
> Sorry for the late response. 
> 
> > On Mar 18, 2019, at 9:38 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> > 
> > Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
> >> This patch enables the annotation of bpf program.
> >> 
> >> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
> >> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
> >> calls into a new function symbol__disassemble_bpf(), where annotation
> >> line information is filled based bpf_prog_info and btf saved in given
> >> perf_env.
> >> 
> >> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
> >> 
> >> Signed-off-by: Song Liu <songliubraving@fb.com>
> >> ---
> >> tools/build/Makefile.feature |   6 +-
> >> tools/perf/Makefile.config   |   4 +
> > 
> > I see the changes to these two files, but I can't see the feature test
> > that it triggers, forgot to do a git-add? Or is it in an upcoming patch
> > in this series?
> 
> test-disassembler-four-args.c is an existing test used by bpftool.
> It was added in fb982666e380c1632a74495b68b3c33a66e76430 .  

Ok, I'll add that to the commit log message, but see below
 
> > 
> > After applying this test it "works":
> > 
> >  make: Entering directory '/home/acme/git/perf/tools/perf'
> >    BUILD:   Doing 'make -j8' parallel build
> > 
> >  Auto-detecting system features:
> >  ...                         dwarf: [ on  ]
> >  ...            dwarf_getlocations: [ on  ]
> >  <SNIP>
> >  ...                           bpf: [ on  ]
> >  ...                        libaio: [ on  ]
> >  ...        disassembler-four-args: [ on  ]
> > 
> > Because you added it to FEATURE_TESTS_BASIC, and this means that if
> > tools/build/feature/test-all.c builds, then what is in
> > FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
> > tools/build/feature/test-all.c, so it works because all the other
> > features are present.
> > 
> > Take a look at:
> > 
> >  2a07d814747b ("tools build feature: Check if libaio is available")
> > 
> > To see what needs to be done.
> 
> I used different versions of gcc to verify that current version of the 
> patch works for both test-succeed and test-fail cases. I guess something 
> like the following is needed? But the test does work without it. 

The following is definetely needed, otherwise if all the other tests in
test-all.c works, this disassembler-four-args feature test will never be
performed.

- Arnaldo
 
> diff --git i/tools/build/feature/test-all.c w/tools/build/feature/test-all.c
> index e903b86b742f..7853e6d91090 100644
> --- i/tools/build/feature/test-all.c
> +++ w/tools/build/feature/test-all.c
> @@ -178,6 +178,10 @@
>  # include "test-reallocarray.c"
>  #undef main
> 
> +#define main main_test_disassembler_four_args
> +# include "test-disassembler-four-args.c"
> +#undef main
> +
>  int main(int argc, char *argv[])
>  {
>         main_test_libpython();
> @@ -219,6 +223,7 @@ int main(int argc, char *argv[])
>         main_test_setns();
>         main_test_libaio();
>         main_test_reallocarray();
> +       main_test_disassembler_four_args();
> 
>         return 0;
>  }
> 
> 
> > 
> > Either way, its interesting to break this patch in two, one adding the
> > feature test and another to use it, i.e. the second patch out of this
> > should have the commit log message in this patch.
> > 
> > I've applied the patches up to before this one and will continue
> > processing other patches while you address this.
> > 
> > Thanks,
> > 
> > - Arnaldo
> > 
> >> tools/perf/util/annotate.c   | 150 ++++++++++++++++++++++++++++++++++-
> >> tools/perf/util/dso.c        |   1 +
> >> tools/perf/util/dso.h        |  32 +++++---
> >> tools/perf/util/symbol.c     |   1 +
> >> 6 files changed, 180 insertions(+), 14 deletions(-)
> >> 
> >> diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
> >> index 61e46d54a67c..8d3864b061f3 100644
> >> --- a/tools/build/Makefile.feature
> >> +++ b/tools/build/Makefile.feature
> >> @@ -66,7 +66,8 @@ FEATURE_TESTS_BASIC :=                  \
> >>         sched_getcpu			\
> >>         sdt				\
> >>         setns				\
> >> -        libaio
> >> +        libaio				\
> >> +        disassembler-four-args
> >> 
> >> # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
> >> # of all feature tests
> >> @@ -118,7 +119,8 @@ FEATURE_DISPLAY ?=              \
> >>          lzma                   \
> >>          get_cpuid              \
> >>          bpf			\
> >> -         libaio
> >> +         libaio			\
> >> +         disassembler-four-args
> >> 
> >> # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
> >> # If in the future we need per-feature checks/flags for features not
> >> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
> >> index df4ad45599ca..c51b59e43dcc 100644
> >> --- a/tools/perf/Makefile.config
> >> +++ b/tools/perf/Makefile.config
> >> @@ -808,6 +808,10 @@ ifdef HAVE_KVM_STAT_SUPPORT
> >>     CFLAGS += -DHAVE_KVM_STAT_SUPPORT
> >> endif
> >> 
> >> +ifeq ($(feature-disassembler-four-args), 1)
> >> +    CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
> >> +endif
> >> +
> >> ifeq (${IS_64_BIT}, 1)
> >>   ifndef NO_PERF_READ_VDSO32
> >>     $(call feature_check,compile-32)
> >> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> >> index 5f6dbbf5d749..e492b19a157c 100644
> >> --- a/tools/perf/util/annotate.c
> >> +++ b/tools/perf/util/annotate.c
> >> @@ -10,6 +10,10 @@
> >> #include <errno.h>
> >> #include <inttypes.h>
> >> #include <libgen.h>
> >> +#include <bpf/bpf.h>
> >> +#include <bpf/btf.h>
> >> +#include <bpf/libbpf.h>
> >> +#include <linux/btf.h>
> >> #include "util.h"
> >> #include "ui/ui.h"
> >> #include "sort.h"
> >> @@ -24,6 +28,7 @@
> >> #include "annotate.h"
> >> #include "evsel.h"
> >> #include "evlist.h"
> >> +#include "bpf-event.h"
> >> #include "block-range.h"
> >> #include "string2.h"
> >> #include "arch/common.h"
> >> @@ -31,6 +36,9 @@
> >> #include <pthread.h>
> >> #include <linux/bitops.h>
> >> #include <linux/kernel.h>
> >> +#include <bfd.h>
> >> +#include <dis-asm.h>
> >> +#include <bpf/libbpf.h>
> >> 
> >> /* FIXME: For the HE_COLORSET */
> >> #include "ui/browser.h"
> >> @@ -1674,6 +1682,144 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
> >> 	return 0;
> >> }
> >> 
> >> +static int symbol__disassemble_bpf(struct symbol *sym,
> >> +				   struct annotate_args *args)
> >> +{
> >> +	struct annotation *notes = symbol__annotation(sym);
> >> +	struct annotation_options *opts = args->options;
> >> +	struct bpf_prog_info_linear *info_linear;
> >> +	struct bpf_prog_linfo *prog_linfo = NULL;
> >> +	struct bpf_prog_info_node *info_node;
> >> +	int len = sym->end - sym->start;
> >> +	disassembler_ftype disassemble;
> >> +	struct map *map = args->ms.map;
> >> +	struct disassemble_info info;
> >> +	struct dso *dso = map->dso;
> >> +	int pc = 0, count, sub_id;
> >> +	struct btf *btf = NULL;
> >> +	char tpath[PATH_MAX];
> >> +	size_t buf_size;
> >> +	int nr_skip = 0;
> >> +	int ret = -1;
> >> +	char *buf;
> >> +	bfd *bfdf;
> >> +	FILE *s;
> >> +
> >> +	if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
> >> +		return -1;
> >> +
> >> +	pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
> >> +		 sym->name, sym->start, sym->end - sym->start);
> >> +
> >> +	memset(tpath, 0, sizeof(tpath));
> >> +	perf_exe(tpath, sizeof(tpath));
> >> +
> >> +	bfdf = bfd_openr(tpath, NULL);
> >> +	assert(bfdf);
> >> +	assert(bfd_check_format(bfdf, bfd_object));
> >> +
> >> +	s = open_memstream(&buf, &buf_size);
> >> +	if (!s)
> >> +		goto out;
> >> +	init_disassemble_info(&info, s,
> >> +			      (fprintf_ftype) fprintf);
> >> +
> >> +	info.arch = bfd_get_arch(bfdf);
> >> +	info.mach = bfd_get_mach(bfdf);
> >> +
> >> +	info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
> >> +						 dso->bpf_prog.id);
> >> +	if (!info_node)
> >> +		goto out;
> >> +	info_linear = info_node->info_linear;
> >> +	sub_id = dso->bpf_prog.sub_id;
> >> +
> >> +	info.buffer = (void *)(info_linear->info.jited_prog_insns);
> >> +	info.buffer_length = info_linear->info.jited_prog_len;
> >> +
> >> +	if (info_linear->info.nr_line_info)
> >> +		prog_linfo = bpf_prog_linfo__new(&info_linear->info);
> >> +
> >> +	if (info_linear->info.btf_id) {
> >> +		struct btf_node *node;
> >> +
> >> +		node = perf_env__find_btf(dso->bpf_prog.env,
> >> +					  info_linear->info.btf_id);
> >> +		if (node)
> >> +			btf = btf__new((__u8 *)(node->data),
> >> +				       node->data_size);
> >> +	}
> >> +
> >> +	disassemble_init_for_target(&info);
> >> +
> >> +#ifdef DISASM_FOUR_ARGS_SIGNATURE
> >> +	disassemble = disassembler(info.arch,
> >> +				   bfd_big_endian(bfdf),
> >> +				   info.mach,
> >> +				   bfdf);
> >> +#else
> >> +	disassemble = disassembler(bfdf);
> >> +#endif
> >> +	assert(disassemble);
> >> +
> >> +	fflush(s);
> >> +	do {
> >> +		const struct bpf_line_info *linfo = NULL;
> >> +		struct disasm_line *dl;
> >> +		size_t prev_buf_size;
> >> +		const char *srcline;
> >> +		u64 addr;
> >> +
> >> +		addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
> >> +		count = disassemble(pc, &info);
> >> +
> >> +		if (prog_linfo)
> >> +			linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
> >> +								addr, sub_id,
> >> +								nr_skip);
> >> +
> >> +		if (linfo && btf) {
> >> +			srcline = btf__name_by_offset(btf, linfo->line_off);
> >> +			nr_skip++;
> >> +		} else
> >> +			srcline = NULL;
> >> +
> >> +		fprintf(s, "\n");
> >> +		prev_buf_size = buf_size;
> >> +		fflush(s);
> >> +
> >> +		if (!opts->hide_src_code && srcline) {
> >> +			args->offset = -1;
> >> +			args->line = strdup(srcline);
> >> +			args->line_nr = 0;
> >> +			args->ms.sym  = sym;
> >> +			dl = disasm_line__new(args);
> >> +			if (dl) {
> >> +				annotation_line__add(&dl->al,
> >> +						     &notes->src->source);
> >> +			}
> >> +		}
> >> +
> >> +		args->offset = pc;
> >> +		args->line = buf + prev_buf_size;
> >> +		args->line_nr = 0;
> >> +		args->ms.sym  = sym;
> >> +		dl = disasm_line__new(args);
> >> +		if (dl)
> >> +			annotation_line__add(&dl->al, &notes->src->source);
> >> +
> >> +		pc += count;
> >> +	} while (count > 0 && pc < len);
> >> +
> >> +	ret = 0;
> >> +out:
> >> +	free(prog_linfo);
> >> +	free(btf);
> >> +	fclose(s);
> >> +	bfd_close(bfdf);
> >> +	return ret;
> >> +}
> >> +
> >> static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
> >> {
> >> 	struct annotation_options *opts = args->options;
> >> @@ -1701,7 +1847,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
> >> 	pr_debug("annotating [%p] %30s : [%p] %30s\n",
> >> 		 dso, dso->long_name, sym, sym->name);
> >> 
> >> -	if (dso__is_kcore(dso)) {
> >> +	if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
> >> +		return symbol__disassemble_bpf(sym, args);
> >> +	} else if (dso__is_kcore(dso)) {
> >> 		kce.kcore_filename = symfs_filename;
> >> 		kce.addr = map__rip_2objdump(map, sym->start);
> >> 		kce.offs = sym->start;
> >> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> >> index ba58ba603b69..58547c468c65 100644
> >> --- a/tools/perf/util/dso.c
> >> +++ b/tools/perf/util/dso.c
> >> @@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
> >> 	case DSO_BINARY_TYPE__KALLSYMS:
> >> 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> >> 	case DSO_BINARY_TYPE__JAVA_JIT:
> >> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> >> 	case DSO_BINARY_TYPE__NOT_FOUND:
> >> 		ret = -1;
> >> 		break;
> >> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> >> index bb417c54c25a..c274b5aa839d 100644
> >> --- a/tools/perf/util/dso.h
> >> +++ b/tools/perf/util/dso.h
> >> @@ -14,6 +14,7 @@
> >> 
> >> struct machine;
> >> struct map;
> >> +struct perf_env;
> >> 
> >> enum dso_binary_type {
> >> 	DSO_BINARY_TYPE__KALLSYMS = 0,
> >> @@ -35,6 +36,7 @@ enum dso_binary_type {
> >> 	DSO_BINARY_TYPE__KCORE,
> >> 	DSO_BINARY_TYPE__GUEST_KCORE,
> >> 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> >> +	DSO_BINARY_TYPE__BPF_PROG_INFO,
> >> 	DSO_BINARY_TYPE__NOT_FOUND,
> >> };
> >> 
> >> @@ -178,17 +180,25 @@ struct dso {
> >> 	struct auxtrace_cache *auxtrace_cache;
> >> 	int		 comp;
> >> 
> >> -	/* dso data file */
> >> -	struct {
> >> -		struct rb_root	 cache;
> >> -		int		 fd;
> >> -		int		 status;
> >> -		u32		 status_seen;
> >> -		size_t		 file_size;
> >> -		struct list_head open_entry;
> >> -		u64		 debug_frame_offset;
> >> -		u64		 eh_frame_hdr_offset;
> >> -	} data;
> >> +	union {
> >> +		/* dso data file */
> >> +		struct {
> >> +			struct rb_root	 cache;
> >> +			int		 fd;
> >> +			int		 status;
> >> +			u32		 status_seen;
> >> +			size_t		 file_size;
> >> +			struct list_head open_entry;
> >> +			u64		 debug_frame_offset;
> >> +			u64		 eh_frame_hdr_offset;
> >> +		} data;
> >> +		/* bpf prog information */
> >> +		struct {
> >> +			u32		id;
> >> +			u32		sub_id;
> >> +			struct perf_env	*env;
> >> +		} bpf_prog;
> >> +	};
> >> 
> >> 	union { /* Tool specific area */
> >> 		void	 *priv;
> >> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> >> index 758bf5f74e6e..4e2e304d4037 100644
> >> --- a/tools/perf/util/symbol.c
> >> +++ b/tools/perf/util/symbol.c
> >> @@ -1451,6 +1451,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
> >> 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> >> 		return true;
> >> 
> >> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> >> 	case DSO_BINARY_TYPE__NOT_FOUND:
> >> 	default:
> >> 		return false;
> >> -- 
> >> 2.17.1
> > 
> > -- 
> > 
> > - Arnaldo
Arnaldo Carvalho de Melo March 19, 2019, 1:37 p.m. UTC | #6
Em Tue, Mar 19, 2019 at 06:10:42AM +0000, Song Liu escreveu:
> 
> 
> > On Mar 18, 2019, at 9:43 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> > 
> > Em Mon, Mar 18, 2019 at 01:38:48PM -0300, Arnaldo Carvalho de Melo escreveu:
> >> Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
> >>> This patch enables the annotation of bpf program.
> >>> 
> >>> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
> >>> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
> >>> calls into a new function symbol__disassemble_bpf(), where annotation
> >>> line information is filled based bpf_prog_info and btf saved in given
> >>> perf_env.
> >>> 
> >>> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
> >>> 
> >>> Signed-off-by: Song Liu <songliubraving@fb.com>
> >>> ---
> >>> tools/build/Makefile.feature |   6 +-
> >>> tools/perf/Makefile.config   |   4 +
> >> 
> >> I see the changes to these two files, but I can't see the feature test
> >> that it triggers, forgot to do a git-add? Or is it in an upcoming patch
> >> in this series?
> >> 
> >> After applying this test it "works":
> >> 
> >>  make: Entering directory '/home/acme/git/perf/tools/perf'
> >>    BUILD:   Doing 'make -j8' parallel build
> >> 
> >>  Auto-detecting system features:
> >>  ...                         dwarf: [ on  ]
> >>  ...            dwarf_getlocations: [ on  ]
> >>  <SNIP>
> >>  ...                           bpf: [ on  ]
> >>  ...                        libaio: [ on  ]
> >>  ...        disassembler-four-args: [ on  ]
> >> 
> >> Because you added it to FEATURE_TESTS_BASIC, and this means that if
> >> tools/build/feature/test-all.c builds, then what is in
> >> FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
> >> tools/build/feature/test-all.c, so it works because all the other
> >> features are present.
> >> 
> >> Take a look at:
> >> 
> >>  2a07d814747b ("tools build feature: Check if libaio is available")
> >> 
> >> To see what needs to be done.
> >> 
> >> Either way, its interesting to break this patch in two, one adding the
> >> feature test and another to use it, i.e. the second patch out of this
> >> should have the commit log message in this patch.
> >> 
> >> I've applied the patches up to before this one and will continue
> >> processing other patches while you address this.
> > 
> > Ok, to continue processing the other patches I chunked out the part
> > below into a 3rd patch from the above one and have it applied already.
> 
> Could you please push applied patches to the tmp.perf/bpf-annotation 
> branch? 

It is in my perf/core branch already.
 
> Thanks,
> Song
> 
> > 
> > commit f326de312abc3657b0397817c66cd7e1540655f7
> > Author: Song Liu <songliubraving@fb.com>
> > Date:   Mon Mar 11 22:30:48 2019 -0700
> > 
> >    perf symbols: Introduce DSO_BINARY_TYPE__BPF_PROG_INFO
> > 
> >    Introduce a new dso type DSO_BINARY_TYPE__BPF_PROG_INFO for BPF programs. In
> >    symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso will call into a new
> >    function symbol__disassemble_bpf() in an upcoming patch, where annotation line
> >    information is filled based bpf_prog_info and btf saved in given perf_env.
> > 
> >    Signed-off-by: Song Liu <songliubraving@fb.com>
> >    Reviewed-by: Jiri Olsa <jolsa@kernel.org>
> >    Cc: Alexei Starovoitov <ast@kernel.org>
> >    Cc: Daniel Borkmann <daniel@iogearbox.net>
> >    Cc: Namhyung Kim <namhyung@kernel.org>
> >    Cc: Peter Zijlstra <peterz@infradead.org>
> >    Cc: Stanislav Fomichev <sdf@google.com>
> >    Cc: kernel-team@fb.com
> >    Link: http://lkml.kernel.org/r/20190312053051.2690567-13-songliubraving@fb.com
> >    [ split from a larger patch ]
> >    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
> > 
> > diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> > index ba58ba603b69..58547c468c65 100644
> > --- a/tools/perf/util/dso.c
> > +++ b/tools/perf/util/dso.c
> > @@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
> > 	case DSO_BINARY_TYPE__KALLSYMS:
> > 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> > 	case DSO_BINARY_TYPE__JAVA_JIT:
> > +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> > 	case DSO_BINARY_TYPE__NOT_FOUND:
> > 		ret = -1;
> > 		break;
> > diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> > index bb417c54c25a..c274b5aa839d 100644
> > --- a/tools/perf/util/dso.h
> > +++ b/tools/perf/util/dso.h
> > @@ -14,6 +14,7 @@
> > 
> > struct machine;
> > struct map;
> > +struct perf_env;
> > 
> > enum dso_binary_type {
> > 	DSO_BINARY_TYPE__KALLSYMS = 0,
> > @@ -35,6 +36,7 @@ enum dso_binary_type {
> > 	DSO_BINARY_TYPE__KCORE,
> > 	DSO_BINARY_TYPE__GUEST_KCORE,
> > 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> > +	DSO_BINARY_TYPE__BPF_PROG_INFO,
> > 	DSO_BINARY_TYPE__NOT_FOUND,
> > };
> > 
> > @@ -178,17 +180,25 @@ struct dso {
> > 	struct auxtrace_cache *auxtrace_cache;
> > 	int		 comp;
> > 
> > -	/* dso data file */
> > -	struct {
> > -		struct rb_root	 cache;
> > -		int		 fd;
> > -		int		 status;
> > -		u32		 status_seen;
> > -		size_t		 file_size;
> > -		struct list_head open_entry;
> > -		u64		 debug_frame_offset;
> > -		u64		 eh_frame_hdr_offset;
> > -	} data;
> > +	union {
> > +		/* dso data file */
> > +		struct {
> > +			struct rb_root	 cache;
> > +			int		 fd;
> > +			int		 status;
> > +			u32		 status_seen;
> > +			size_t		 file_size;
> > +			struct list_head open_entry;
> > +			u64		 debug_frame_offset;
> > +			u64		 eh_frame_hdr_offset;
> > +		} data;
> > +		/* bpf prog information */
> > +		struct {
> > +			u32		id;
> > +			u32		sub_id;
> > +			struct perf_env	*env;
> > +		} bpf_prog;
> > +	};
> > 
> > 	union { /* Tool specific area */
> > 		void	 *priv;
> > diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> > index 58442ca5e3c4..5cbad55cd99d 100644
> > --- a/tools/perf/util/symbol.c
> > +++ b/tools/perf/util/symbol.c
> > @@ -1455,6 +1455,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
> > 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> > 		return true;
> > 
> > +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> > 	case DSO_BINARY_TYPE__NOT_FOUND:
> > 	default:
> > 		return false;
Arnaldo Carvalho de Melo March 19, 2019, 1:58 p.m. UTC | #7
Em Tue, Mar 19, 2019 at 06:05:30AM +0000, Song Liu escreveu:
> Sorry for the late response. 
> 
> > On Mar 18, 2019, at 9:38 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> > 
> > Em Mon, Mar 11, 2019 at 10:30:48PM -0700, Song Liu escreveu:
> >> This patch enables the annotation of bpf program.
> >> 
> >> A new dso type DSO_BINARY_TYPE__BPF_PROG_INFO is introduced to for BPF
> >> programs. In symbol__disassemble(), DSO_BINARY_TYPE__BPF_PROG_INFO dso
> >> calls into a new function symbol__disassemble_bpf(), where annotation
> >> line information is filled based bpf_prog_info and btf saved in given
> >> perf_env.
> >> 
> >> symbol__disassemble_bpf() uses libbfd to disassemble bpf programs.
> >> 
> >> Signed-off-by: Song Liu <songliubraving@fb.com>
> >> ---
> >> tools/build/Makefile.feature |   6 +-
> >> tools/perf/Makefile.config   |   4 +
> > 
> > I see the changes to these two files, but I can't see the feature test
> > that it triggers, forgot to do a git-add? Or is it in an upcoming patch
> > in this series?
> 
> test-disassembler-four-args.c is an existing test used by bpftool.
> It was added in fb982666e380c1632a74495b68b3c33a66e76430 .  
> 
> > 
> > After applying this test it "works":
> > 
> >  make: Entering directory '/home/acme/git/perf/tools/perf'
> >    BUILD:   Doing 'make -j8' parallel build
> > 
> >  Auto-detecting system features:
> >  ...                         dwarf: [ on  ]
> >  ...            dwarf_getlocations: [ on  ]
> >  <SNIP>
> >  ...                           bpf: [ on  ]
> >  ...                        libaio: [ on  ]
> >  ...        disassembler-four-args: [ on  ]
> > 
> > Because you added it to FEATURE_TESTS_BASIC, and this means that if
> > tools/build/feature/test-all.c builds, then what is in
> > FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
> > tools/build/feature/test-all.c, so it works because all the other
> > features are present.
> > 
> > Take a look at:
> > 
> >  2a07d814747b ("tools build feature: Check if libaio is available")
> > 
> > To see what needs to be done.
> 
> I used different versions of gcc to verify that current version of the 
> patch works for both test-succeed and test-fail cases. I guess something 
> like the following is needed? But the test does work without it. 

Even with the file below, it fails, as:

[acme@quaco perf]$ cat /tmp/build/perf/feature/test-all.make.output
/usr/bin/ld: /tmp/ccTj7iV6.o: in function `main_test_disassembler_four_args':
/home/acme/git/perf/tools/build/feature/test-disassembler-four-args.c:9: undefined reference to `disassembler'
collect2: error: ld returned 1 exit status
[acme@quaco perf]$

Then we do the test for each of the features and _then_ this works:

[acme@quaco perf]$ ls -la /tmp/build/perf/feature/test-disassembler-four-args.*
-rwxrwxr-x. 1 acme acme 2098312 Mar 19 10:51 /tmp/build/perf/feature/test-disassembler-four-args.bin
-rw-rw-r--. 1 acme acme    1079 Mar 19 10:51 /tmp/build/perf/feature/test-disassembler-four-args.d
-rw-rw-r--. 1 acme acme       0 Mar 19 10:51 /tmp/build/perf/feature/test-disassembler-four-args.make.output
[acme@quaco perf]$

So there is still something missing, i.e. which objects to add to the
test-all case, I'll fix it.
 
> Thanks,
> Song
> 
> 
> diff --git i/tools/build/feature/test-all.c w/tools/build/feature/test-all.c
> index e903b86b742f..7853e6d91090 100644
> --- i/tools/build/feature/test-all.c
> +++ w/tools/build/feature/test-all.c
> @@ -178,6 +178,10 @@
>  # include "test-reallocarray.c"
>  #undef main
> 
> +#define main main_test_disassembler_four_args
> +# include "test-disassembler-four-args.c"
> +#undef main
> +
>  int main(int argc, char *argv[])
>  {
>         main_test_libpython();
> @@ -219,6 +223,7 @@ int main(int argc, char *argv[])
>         main_test_setns();
>         main_test_libaio();
>         main_test_reallocarray();
> +       main_test_disassembler_four_args();
> 
>         return 0;
>  }
> 
> 
> > 
> > Either way, its interesting to break this patch in two, one adding the
> > feature test and another to use it, i.e. the second patch out of this
> > should have the commit log message in this patch.
> > 
> > I've applied the patches up to before this one and will continue
> > processing other patches while you address this.
> > 
> > Thanks,
> > 
> > - Arnaldo
> > 
> >> tools/perf/util/annotate.c   | 150 ++++++++++++++++++++++++++++++++++-
> >> tools/perf/util/dso.c        |   1 +
> >> tools/perf/util/dso.h        |  32 +++++---
> >> tools/perf/util/symbol.c     |   1 +
> >> 6 files changed, 180 insertions(+), 14 deletions(-)
> >> 
> >> diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
> >> index 61e46d54a67c..8d3864b061f3 100644
> >> --- a/tools/build/Makefile.feature
> >> +++ b/tools/build/Makefile.feature
> >> @@ -66,7 +66,8 @@ FEATURE_TESTS_BASIC :=                  \
> >>         sched_getcpu			\
> >>         sdt				\
> >>         setns				\
> >> -        libaio
> >> +        libaio				\
> >> +        disassembler-four-args
> >> 
> >> # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
> >> # of all feature tests
> >> @@ -118,7 +119,8 @@ FEATURE_DISPLAY ?=              \
> >>          lzma                   \
> >>          get_cpuid              \
> >>          bpf			\
> >> -         libaio
> >> +         libaio			\
> >> +         disassembler-four-args
> >> 
> >> # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
> >> # If in the future we need per-feature checks/flags for features not
> >> diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
> >> index df4ad45599ca..c51b59e43dcc 100644
> >> --- a/tools/perf/Makefile.config
> >> +++ b/tools/perf/Makefile.config
> >> @@ -808,6 +808,10 @@ ifdef HAVE_KVM_STAT_SUPPORT
> >>     CFLAGS += -DHAVE_KVM_STAT_SUPPORT
> >> endif
> >> 
> >> +ifeq ($(feature-disassembler-four-args), 1)
> >> +    CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
> >> +endif
> >> +
> >> ifeq (${IS_64_BIT}, 1)
> >>   ifndef NO_PERF_READ_VDSO32
> >>     $(call feature_check,compile-32)
> >> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> >> index 5f6dbbf5d749..e492b19a157c 100644
> >> --- a/tools/perf/util/annotate.c
> >> +++ b/tools/perf/util/annotate.c
> >> @@ -10,6 +10,10 @@
> >> #include <errno.h>
> >> #include <inttypes.h>
> >> #include <libgen.h>
> >> +#include <bpf/bpf.h>
> >> +#include <bpf/btf.h>
> >> +#include <bpf/libbpf.h>
> >> +#include <linux/btf.h>
> >> #include "util.h"
> >> #include "ui/ui.h"
> >> #include "sort.h"
> >> @@ -24,6 +28,7 @@
> >> #include "annotate.h"
> >> #include "evsel.h"
> >> #include "evlist.h"
> >> +#include "bpf-event.h"
> >> #include "block-range.h"
> >> #include "string2.h"
> >> #include "arch/common.h"
> >> @@ -31,6 +36,9 @@
> >> #include <pthread.h>
> >> #include <linux/bitops.h>
> >> #include <linux/kernel.h>
> >> +#include <bfd.h>
> >> +#include <dis-asm.h>
> >> +#include <bpf/libbpf.h>
> >> 
> >> /* FIXME: For the HE_COLORSET */
> >> #include "ui/browser.h"
> >> @@ -1674,6 +1682,144 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
> >> 	return 0;
> >> }
> >> 
> >> +static int symbol__disassemble_bpf(struct symbol *sym,
> >> +				   struct annotate_args *args)
> >> +{
> >> +	struct annotation *notes = symbol__annotation(sym);
> >> +	struct annotation_options *opts = args->options;
> >> +	struct bpf_prog_info_linear *info_linear;
> >> +	struct bpf_prog_linfo *prog_linfo = NULL;
> >> +	struct bpf_prog_info_node *info_node;
> >> +	int len = sym->end - sym->start;
> >> +	disassembler_ftype disassemble;
> >> +	struct map *map = args->ms.map;
> >> +	struct disassemble_info info;
> >> +	struct dso *dso = map->dso;
> >> +	int pc = 0, count, sub_id;
> >> +	struct btf *btf = NULL;
> >> +	char tpath[PATH_MAX];
> >> +	size_t buf_size;
> >> +	int nr_skip = 0;
> >> +	int ret = -1;
> >> +	char *buf;
> >> +	bfd *bfdf;
> >> +	FILE *s;
> >> +
> >> +	if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
> >> +		return -1;
> >> +
> >> +	pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
> >> +		 sym->name, sym->start, sym->end - sym->start);
> >> +
> >> +	memset(tpath, 0, sizeof(tpath));
> >> +	perf_exe(tpath, sizeof(tpath));
> >> +
> >> +	bfdf = bfd_openr(tpath, NULL);
> >> +	assert(bfdf);
> >> +	assert(bfd_check_format(bfdf, bfd_object));
> >> +
> >> +	s = open_memstream(&buf, &buf_size);
> >> +	if (!s)
> >> +		goto out;
> >> +	init_disassemble_info(&info, s,
> >> +			      (fprintf_ftype) fprintf);
> >> +
> >> +	info.arch = bfd_get_arch(bfdf);
> >> +	info.mach = bfd_get_mach(bfdf);
> >> +
> >> +	info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
> >> +						 dso->bpf_prog.id);
> >> +	if (!info_node)
> >> +		goto out;
> >> +	info_linear = info_node->info_linear;
> >> +	sub_id = dso->bpf_prog.sub_id;
> >> +
> >> +	info.buffer = (void *)(info_linear->info.jited_prog_insns);
> >> +	info.buffer_length = info_linear->info.jited_prog_len;
> >> +
> >> +	if (info_linear->info.nr_line_info)
> >> +		prog_linfo = bpf_prog_linfo__new(&info_linear->info);
> >> +
> >> +	if (info_linear->info.btf_id) {
> >> +		struct btf_node *node;
> >> +
> >> +		node = perf_env__find_btf(dso->bpf_prog.env,
> >> +					  info_linear->info.btf_id);
> >> +		if (node)
> >> +			btf = btf__new((__u8 *)(node->data),
> >> +				       node->data_size);
> >> +	}
> >> +
> >> +	disassemble_init_for_target(&info);
> >> +
> >> +#ifdef DISASM_FOUR_ARGS_SIGNATURE
> >> +	disassemble = disassembler(info.arch,
> >> +				   bfd_big_endian(bfdf),
> >> +				   info.mach,
> >> +				   bfdf);
> >> +#else
> >> +	disassemble = disassembler(bfdf);
> >> +#endif
> >> +	assert(disassemble);
> >> +
> >> +	fflush(s);
> >> +	do {
> >> +		const struct bpf_line_info *linfo = NULL;
> >> +		struct disasm_line *dl;
> >> +		size_t prev_buf_size;
> >> +		const char *srcline;
> >> +		u64 addr;
> >> +
> >> +		addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
> >> +		count = disassemble(pc, &info);
> >> +
> >> +		if (prog_linfo)
> >> +			linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
> >> +								addr, sub_id,
> >> +								nr_skip);
> >> +
> >> +		if (linfo && btf) {
> >> +			srcline = btf__name_by_offset(btf, linfo->line_off);
> >> +			nr_skip++;
> >> +		} else
> >> +			srcline = NULL;
> >> +
> >> +		fprintf(s, "\n");
> >> +		prev_buf_size = buf_size;
> >> +		fflush(s);
> >> +
> >> +		if (!opts->hide_src_code && srcline) {
> >> +			args->offset = -1;
> >> +			args->line = strdup(srcline);
> >> +			args->line_nr = 0;
> >> +			args->ms.sym  = sym;
> >> +			dl = disasm_line__new(args);
> >> +			if (dl) {
> >> +				annotation_line__add(&dl->al,
> >> +						     &notes->src->source);
> >> +			}
> >> +		}
> >> +
> >> +		args->offset = pc;
> >> +		args->line = buf + prev_buf_size;
> >> +		args->line_nr = 0;
> >> +		args->ms.sym  = sym;
> >> +		dl = disasm_line__new(args);
> >> +		if (dl)
> >> +			annotation_line__add(&dl->al, &notes->src->source);
> >> +
> >> +		pc += count;
> >> +	} while (count > 0 && pc < len);
> >> +
> >> +	ret = 0;
> >> +out:
> >> +	free(prog_linfo);
> >> +	free(btf);
> >> +	fclose(s);
> >> +	bfd_close(bfdf);
> >> +	return ret;
> >> +}
> >> +
> >> static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
> >> {
> >> 	struct annotation_options *opts = args->options;
> >> @@ -1701,7 +1847,9 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
> >> 	pr_debug("annotating [%p] %30s : [%p] %30s\n",
> >> 		 dso, dso->long_name, sym, sym->name);
> >> 
> >> -	if (dso__is_kcore(dso)) {
> >> +	if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
> >> +		return symbol__disassemble_bpf(sym, args);
> >> +	} else if (dso__is_kcore(dso)) {
> >> 		kce.kcore_filename = symfs_filename;
> >> 		kce.addr = map__rip_2objdump(map, sym->start);
> >> 		kce.offs = sym->start;
> >> diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
> >> index ba58ba603b69..58547c468c65 100644
> >> --- a/tools/perf/util/dso.c
> >> +++ b/tools/perf/util/dso.c
> >> @@ -184,6 +184,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
> >> 	case DSO_BINARY_TYPE__KALLSYMS:
> >> 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
> >> 	case DSO_BINARY_TYPE__JAVA_JIT:
> >> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> >> 	case DSO_BINARY_TYPE__NOT_FOUND:
> >> 		ret = -1;
> >> 		break;
> >> diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
> >> index bb417c54c25a..c274b5aa839d 100644
> >> --- a/tools/perf/util/dso.h
> >> +++ b/tools/perf/util/dso.h
> >> @@ -14,6 +14,7 @@
> >> 
> >> struct machine;
> >> struct map;
> >> +struct perf_env;
> >> 
> >> enum dso_binary_type {
> >> 	DSO_BINARY_TYPE__KALLSYMS = 0,
> >> @@ -35,6 +36,7 @@ enum dso_binary_type {
> >> 	DSO_BINARY_TYPE__KCORE,
> >> 	DSO_BINARY_TYPE__GUEST_KCORE,
> >> 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
> >> +	DSO_BINARY_TYPE__BPF_PROG_INFO,
> >> 	DSO_BINARY_TYPE__NOT_FOUND,
> >> };
> >> 
> >> @@ -178,17 +180,25 @@ struct dso {
> >> 	struct auxtrace_cache *auxtrace_cache;
> >> 	int		 comp;
> >> 
> >> -	/* dso data file */
> >> -	struct {
> >> -		struct rb_root	 cache;
> >> -		int		 fd;
> >> -		int		 status;
> >> -		u32		 status_seen;
> >> -		size_t		 file_size;
> >> -		struct list_head open_entry;
> >> -		u64		 debug_frame_offset;
> >> -		u64		 eh_frame_hdr_offset;
> >> -	} data;
> >> +	union {
> >> +		/* dso data file */
> >> +		struct {
> >> +			struct rb_root	 cache;
> >> +			int		 fd;
> >> +			int		 status;
> >> +			u32		 status_seen;
> >> +			size_t		 file_size;
> >> +			struct list_head open_entry;
> >> +			u64		 debug_frame_offset;
> >> +			u64		 eh_frame_hdr_offset;
> >> +		} data;
> >> +		/* bpf prog information */
> >> +		struct {
> >> +			u32		id;
> >> +			u32		sub_id;
> >> +			struct perf_env	*env;
> >> +		} bpf_prog;
> >> +	};
> >> 
> >> 	union { /* Tool specific area */
> >> 		void	 *priv;
> >> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> >> index 758bf5f74e6e..4e2e304d4037 100644
> >> --- a/tools/perf/util/symbol.c
> >> +++ b/tools/perf/util/symbol.c
> >> @@ -1451,6 +1451,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
> >> 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
> >> 		return true;
> >> 
> >> +	case DSO_BINARY_TYPE__BPF_PROG_INFO:
> >> 	case DSO_BINARY_TYPE__NOT_FOUND:
> >> 	default:
> >> 		return false;
> >> -- 
> >> 2.17.1
> > 
> > -- 
> > 
> > - Arnaldo
Arnaldo Carvalho de Melo March 19, 2019, 2:14 p.m. UTC | #8
Em Tue, Mar 19, 2019 at 10:58:13AM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Mar 19, 2019 at 06:05:30AM +0000, Song Liu escreveu:
> > test-disassembler-four-args.c is an existing test used by bpftool.
> > It was added in fb982666e380c1632a74495b68b3c33a66e76430 .  

> > > After applying this test it "works":

> > >  make: Entering directory '/home/acme/git/perf/tools/perf'
> > >    BUILD:   Doing 'make -j8' parallel build

> > >  Auto-detecting system features:
> > >  ...                         dwarf: [ on  ]
> > >  ...            dwarf_getlocations: [ on  ]
> > >  <SNIP>
> > >  ...                           bpf: [ on  ]
> > >  ...                        libaio: [ on  ]
> > >  ...        disassembler-four-args: [ on  ]
> > > 
> > > Because you added it to FEATURE_TESTS_BASIC, and this means that if
> > > tools/build/feature/test-all.c builds, then what is in
> > > FEATURE_TESTS_BASIC is set to 'on', but you didn't add anything to
> > > tools/build/feature/test-all.c, so it works because all the other
> > > features are present.

> > > Take a look at:

> > >  2a07d814747b ("tools build feature: Check if libaio is available")

> > > To see what needs to be done.

> > I used different versions of gcc to verify that current version of the 
> > patch works for both test-succeed and test-fail cases. I guess something 
> > like the following is needed? But the test does work without it. 

> Even with the file below, it fails, as:

> [acme@quaco perf]$ cat /tmp/build/perf/feature/test-all.make.output
> /usr/bin/ld: /tmp/ccTj7iV6.o: in function `main_test_disassembler_four_args':
> /home/acme/git/perf/tools/build/feature/test-disassembler-four-args.c:9: undefined reference to `disassembler'
> collect2: error: ld returned 1 exit status
> [acme@quaco perf]$

> Then we do the test for each of the features and _then_ this works:

> [acme@quaco perf]$ ls -la /tmp/build/perf/feature/test-disassembler-four-args.*
> -rwxrwxr-x. 1 acme acme 2098312 Mar 19 10:51 /tmp/build/perf/feature/test-disassembler-four-args.bin
> -rw-rw-r--. 1 acme acme    1079 Mar 19 10:51 /tmp/build/perf/feature/test-disassembler-four-args.d
> -rw-rw-r--. 1 acme acme       0 Mar 19 10:51 /tmp/build/perf/feature/test-disassembler-four-args.make.output
> [acme@quaco perf]$
> 
> So there is still something missing, i.e. which objects to add to the
> test-all case, I'll fix it.

This was missing:

diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index c51b59e43dcc..4f491ad4f492 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -227,6 +227,8 @@ FEATURE_CHECK_LDFLAGS-libpython-version := $(PYTHON_EMBED_LDOPTS)
 
 FEATURE_CHECK_LDFLAGS-libaio = -lrt
 
+FEATURE_CHECK_LDFLAGS-disassembler-four-args = -lopcodes
+
 CFLAGS += -fno-omit-frame-pointer
 CFLAGS += -ggdb3
 CFLAGS += -funwind-tables

----------------------

After that, and with a clean /tmp/build/perf, re-running:

  make -C tools/perf O=/tmp/build/perf

we get:

[acme@quaco perf]$ ls -la /tmp/build/perf/feature/
total 2888
drwxrwxr-x.  2 acme acme     400 Mar 19 11:08 .
drwxrwxr-x. 16 acme acme    4280 Mar 19 11:08 ..
-rwxrwxr-x.  1 acme acme 2680352 Mar 19 11:07 test-all.bin
-rw-rw-r--.  1 acme acme   38753 Mar 19 11:07 test-all.d
-rw-rw-r--.  1 acme acme       0 Mar 19 11:07 test-all.make.output
-rw-rw-r--.  1 acme acme     168 Mar 19 11:07 test-bionic.make.output
-rwxrwxr-x.  1 acme acme  140960 Mar 19 11:08 test-cplus-demangle.bin
-rw-rw-r--.  1 acme acme     101 Mar 19 11:08 test-cplus-demangle.d
-rw-rw-r--.  1 acme acme       0 Mar 19 11:08 test-cplus-demangle.make.output
-rwxrwxr-x.  1 acme acme   17976 Mar 19 11:08 test-jvmti.bin
-rwxrwxr-x.  1 acme acme   17984 Mar 19 11:08 test-jvmti-cmlr.bin
-rw-rw-r--.  1 acme acme    1107 Mar 19 11:08 test-jvmti-cmlr.d
-rw-rw-r--.  1 acme acme       0 Mar 19 11:08 test-jvmti-cmlr.make.output
-rw-rw-r--.  1 acme acme    1014 Mar 19 11:08 test-jvmti.d
-rw-rw-r--.  1 acme acme       0 Mar 19 11:08 test-jvmti.make.output
-rwxrwxr-x.  1 acme acme   18368 Mar 19 11:07 test-libbabeltrace.bin
-rw-rw-r--.  1 acme acme    1470 Mar 19 11:07 test-libbabeltrace.d
-rw-rw-r--.  1 acme acme       0 Mar 19 11:07 test-libbabeltrace.make.output
-rw-rw-r--.  1 acme acme     179 Mar 19 11:07 test-libunwind-aarch64.make.output
-rw-rw-r--.  1 acme acme     163 Mar 19 11:07 test-libunwind-x86.make.output
[acme@quaco perf]$

I.e. test-all.bin got built, and if we look at it:

[acme@quaco perf]$ nm /tmp/build/perf/feature/test-all.bin  | grep disassembler
0000000000061f90 T disassembler
0000000000062110 T disassembler_options_cmp
0000000000061fb0 T disassembler_usage
0000000000061f40 T main_test_disassembler_four_args
000000000006b7c0 T print_i386_disassembler_options
[acme@quaco perf]$ 

I.e. the -lopcodes was added to the test-all.bin, and as we include that
itest-disassembler-four-args.c in the test-all.c file, it gets linked
and that test-all.c build doesn't fail, so all that is in
FEATURE_TESTS_BASIC is marked as present, CFLAGS +=
-DDISASM_FOUR_ARGS_SIGNATURE gets set, etc.

Now the test is really being performed, the test-all.bin feature
detection fast path is working, proceeding.

- Arnaldo
Arnaldo Carvalho de Melo March 19, 2019, 2:52 p.m. UTC | #9
Em Tue, Mar 19, 2019 at 11:14:35AM -0300, Arnaldo Carvalho de Melo escreveu:
> 
> Now the test is really being performed, the test-all.bin feature
> detection fast path is working, proceeding.

Now it all works, really nice!

I added a 'Committer testing' section with all the steps to test this
and pushed to:

https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/commit/?h=perf/core&id=6530d44e7dc1d41c73fe70b9e6ea1b9cabebb57f

Which I repeat here, please go thru it and check if everything is ok, if
the disassembled + original BPF source code looks ok, etc:

    Committer testing:
    
    1) Have a BPF program running, one that has BTF info, etc, I used
       the tools/perf/examples/bpf/augmented_raw_syscalls.c put in place
       by 'perf trace'.
    
      # grep -B1 augmented_raw ~/.perfconfig
      [trace]
            add_events = /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c
      #
      # perf trace -e *mmsg
      dnf/6245 sendmmsg(20, 0x7f5485a88030, 2, MSG_NOSIGNAL) = 2
      NetworkManager/10055 sendmmsg(22<socket:[1056822]>, 0x7f8126ad1bb0, 2, MSG_NOSIGNAL) = 2
    
    2) Then do a 'perf record' system wide for a while:
    
      # perf record -a
      ^C[ perf record: Woken up 68 times to write data ]
      [ perf record: Captured and wrote 19.427 MB perf.data (366891 samples) ]
      #
    
    3) Check that we captured BPF and BTF info in the perf.data file:
    
      # perf report --header-only | grep 'b[pt]f'
      # event : name = cycles:ppp, , id = { 294789, 294790, 294791, 294792, 294793, 294794, 294795, 294796 }, size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, read_format = ID, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, task = 1, precise_ip = 3, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, ksymbol = 1, bpf_event = 1
      # bpf_prog_info of id 13
      # bpf_prog_info of id 14
      # bpf_prog_info of id 15
      # bpf_prog_info of id 16
      # bpf_prog_info of id 17
      # bpf_prog_info of id 18
      # bpf_prog_info of id 21
      # bpf_prog_info of id 22
      # bpf_prog_info of id 41
      # bpf_prog_info of id 42
      # btf info of id 2
      #
    
    4) Check which programs got recorded:
    
       # perf report | grep bpf_prog | head
         0.16%  exe              bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
         0.14%  exe              bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
         0.08%  fuse-overlayfs   bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
         0.07%  fuse-overlayfs   bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
         0.01%  clang-4.0        bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
         0.01%  clang-4.0        bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
         0.00%  clang            bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
         0.00%  runc             bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
         0.00%  clang            bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
         0.00%  sh               bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
      #
    
      This was with the default --sort order for 'perf report', which is:
    
        --sort comm,dso,symbol
    
      If we just look for the symbol, for instance:
    
       # perf report --sort symbol | grep bpf_prog | head
         0.26%  [k] bpf_prog_819967866022f1e1_sys_enter                -      -
         0.24%  [k] bpf_prog_c1bd85c092d6e4aa_sys_exit                 -      -
       #
    
      or the DSO:
    
       # perf report --sort dso | grep bpf_prog | head
         0.26%  bpf_prog_819967866022f1e1_sys_enter
         0.24%  bpf_prog_c1bd85c092d6e4aa_sys_exit
      #
    
    We'll see the two BPF programs that augmented_raw_syscalls.o puts in
    place,  one attached to the raw_syscalls:sys_enter and another to the
    raw_syscalls:sys_exit tracepoints, as expected.
    
    Now we can finally do, from the command line, annotation for one of
    those two symbols, with the original BPF program source coude intermixed
    with the disassembled JITed code:
    
      # perf annotate --stdio2 bpf_prog_819967866022f1e1_sys_enter
    
      Samples: 950  of event 'cycles:ppp', 4000 Hz, Event count (approx.): 553756947, [percent: local period]
      bpf_prog_819967866022f1e1_sys_enter() bpf_prog_819967866022f1e1_sys_enter
      Percent      int sys_enter(struct syscall_enter_args *args)
       53.41         push   %rbp
    
        0.63         mov    %rsp,%rbp
        0.31         sub    $0x170,%rsp
        1.93         sub    $0x28,%rbp
        7.02         mov    %rbx,0x0(%rbp)
        3.20         mov    %r13,0x8(%rbp)
        1.07         mov    %r14,0x10(%rbp)
        0.61         mov    %r15,0x18(%rbp)
        0.11         xor    %eax,%eax
        1.29         mov    %rax,0x20(%rbp)
        0.11         mov    %rdi,%rbx
                    return bpf_get_current_pid_tgid();
        2.02       → callq  *ffffffffda6776d9
        2.76         mov    %eax,-0x148(%rbp)
                     mov    %rbp,%rsi
                   int sys_enter(struct syscall_enter_args *args)
                     add    $0xfffffffffffffeb8,%rsi
                    return bpf_map_lookup_elem(pids, &pid) != NULL;
                     movabs $0xffff975ac2607800,%rdi
    
        1.26       → callq  *ffffffffda6789e9
                     cmp    $0x0,%rax
        2.43       → je     0
                     add    $0x38,%rax
        0.21         xor    %r13d,%r13d
                    if (pid_filter__has(&pids_filtered, getpid()))
        0.81         cmp    $0x0,%rax
                   → jne    0
                     mov    %rbp,%rdi
                    probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
        2.22         add    $0xfffffffffffffeb8,%rdi
        0.11         mov    $0x40,%esi
        0.32         mov    %rbx,%rdx
        2.74       → callq  *ffffffffda658409
                    syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr);
        0.22         mov    %rbp,%rsi
        1.69         add    $0xfffffffffffffec0,%rsi
                    syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr);
                     movabs $0xffff975bfcd36000,%rdi
    
                     add    $0xd0,%rdi
        0.21         mov    0x0(%rsi),%eax
        0.93         cmp    $0x200,%rax
                   → jae    0
        0.10         shl    $0x3,%rax
    
        0.11         add    %rdi,%rax
        0.11       → jmp    0
                     xor    %eax,%eax
                    if (syscall == NULL || !syscall->enabled)
        1.07         cmp    $0x0,%rax
                   → je     0
                    if (syscall == NULL || !syscall->enabled)
        6.57         movzbq 0x0(%rax),%rdi
    
                    if (syscall == NULL || !syscall->enabled)
                     cmp    $0x0,%rdi
        0.95       → je     0
                     mov    $0x40,%r8d
                    switch (augmented_args.args.syscall_nr) {
                     mov    -0x140(%rbp),%rdi
                    switch (augmented_args.args.syscall_nr) {
                     cmp    $0x2,%rdi
                   → je     0
                     cmp    $0x101,%rdi
                   → je     0
                     cmp    $0x15,%rdi
                   → jne    0
                    case SYS_OPEN:   filename_arg = (const void *)args->args[0];
                     mov    0x10(%rbx),%rdx
                   → jmp    0
                    case SYS_OPENAT: filename_arg = (const void *)args->args[1];
                     mov    0x18(%rbx),%rdx
                    if (filename_arg != NULL) {
                     cmp    $0x0,%rdx
                   → je     0
                     xor    %edi,%edi
                            augmented_args.filename.reserved = 0;
                     mov    %edi,-0x104(%rbp)
                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
                     mov    %rbp,%rdi
                     add    $0xffffffffffffff00,%rdi
                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
                     mov    $0x100,%esi
                   → callq  *ffffffffda658499
                     mov    $0x148,%r8d
                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
                     mov    %eax,-0x108(%rbp)
                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
                     mov    %rax,%rdi
                     shl    $0x20,%rdi
    
                     shr    $0x20,%rdi
    
                            if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) {
                     cmp    $0xff,%rdi
                   → ja     0
                                    len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size;
                     add    $0x48,%rax
                                    len &= sizeof(augmented_args.filename.value) - 1;
                     and    $0xff,%rax
                     mov    %rax,%r8
                     mov    %rbp,%rcx
                    return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, len);
                     add    $0xfffffffffffffeb8,%rcx
                     mov    %rbx,%rdi
                     movabs $0xffff975fbd72d800,%rsi
    
                     mov    $0xffffffff,%edx
                   → callq  *ffffffffda658ad9
                     mov    %rax,%r13
                   }
                     mov    %r13,%rax
        0.72         mov    0x0(%rbp),%rbx
                     mov    0x8(%rbp),%r13
        1.16         mov    0x10(%rbp),%r14
        0.10         mov    0x18(%rbp),%r15
        0.42         add    $0x28,%rbp
        0.54         leaveq
        0.54       ← retq
      #
    
    Please see 'man perf-config' to see how to control what should be seen,
    via ~/.perfconfig [annotate] section, for instance, one can suppress the
    source code and see just the disassembly, etc.
    
    Alternatively, use the TUI bu just using 'perf annotate', press
    '/bpf_prog' to see the bpf symbols, press enter and do the interactive
    annotation, which allows for dumping to a file after selecting the
    the various output tunables, for instance, the above without source code
    intermixed, plus showing all the instruction offsets:
    
      # perf annotate bpf_prog_819967866022f1e1_sys_enter
    
    Then press: 's' to hide the source code + 'O' twice to show all
    instruction offsets, then 'P' to print to the
    bpf_prog_819967866022f1e1_sys_enter.annotation file, which will have:
    
      # cat bpf_prog_819967866022f1e1_sys_enter.annotation
      bpf_prog_819967866022f1e1_sys_enter() bpf_prog_819967866022f1e1_sys_enter
      Event: cycles:ppp
    
       53.41    0:   push   %rbp
    
        0.63    1:   mov    %rsp,%rbp
        0.31    4:   sub    $0x170,%rsp
        1.93    b:   sub    $0x28,%rbp
        7.02    f:   mov    %rbx,0x0(%rbp)
        3.20   13:   mov    %r13,0x8(%rbp)
        1.07   17:   mov    %r14,0x10(%rbp)
        0.61   1b:   mov    %r15,0x18(%rbp)
        0.11   1f:   xor    %eax,%eax
        1.29   21:   mov    %rax,0x20(%rbp)
        0.11   25:   mov    %rdi,%rbx
        2.02   28: → callq  *ffffffffda6776d9
        2.76   2d:   mov    %eax,-0x148(%rbp)
               33:   mov    %rbp,%rsi
               36:   add    $0xfffffffffffffeb8,%rsi
               3d:   movabs $0xffff975ac2607800,%rdi
    
        1.26   47: → callq  *ffffffffda6789e9
               4c:   cmp    $0x0,%rax
        2.43   50: → je     0
               52:   add    $0x38,%rax
        0.21   56:   xor    %r13d,%r13d
        0.81   59:   cmp    $0x0,%rax
               5d: → jne    0
               63:   mov    %rbp,%rdi
        2.22   66:   add    $0xfffffffffffffeb8,%rdi
        0.11   6d:   mov    $0x40,%esi
        0.32   72:   mov    %rbx,%rdx
        2.74   75: → callq  *ffffffffda658409
        0.22   7a:   mov    %rbp,%rsi
        1.69   7d:   add    $0xfffffffffffffec0,%rsi
               84:   movabs $0xffff975bfcd36000,%rdi
    
               8e:   add    $0xd0,%rdi
        0.21   95:   mov    0x0(%rsi),%eax
        0.93   98:   cmp    $0x200,%rax
               9f: → jae    0
        0.10   a1:   shl    $0x3,%rax
    
        0.11   a5:   add    %rdi,%rax
        0.11   a8: → jmp    0
               aa:   xor    %eax,%eax
        1.07   ac:   cmp    $0x0,%rax
               b0: → je     0
        6.57   b6:   movzbq 0x0(%rax),%rdi
    
               bb:   cmp    $0x0,%rdi
        0.95   bf: → je     0
               c5:   mov    $0x40,%r8d
               cb:   mov    -0x140(%rbp),%rdi
               d2:   cmp    $0x2,%rdi
               d6: → je     0
               d8:   cmp    $0x101,%rdi
               df: → je     0
               e1:   cmp    $0x15,%rdi
               e5: → jne    0
               e7:   mov    0x10(%rbx),%rdx
               eb: → jmp    0
               ed:   mov    0x18(%rbx),%rdx
               f1:   cmp    $0x0,%rdx
               f5: → je     0
               f7:   xor    %edi,%edi
               f9:   mov    %edi,-0x104(%rbp)
               ff:   mov    %rbp,%rdi
              102:   add    $0xffffffffffffff00,%rdi
              109:   mov    $0x100,%esi
              10e: → callq  *ffffffffda658499
              113:   mov    $0x148,%r8d
              119:   mov    %eax,-0x108(%rbp)
              11f:   mov    %rax,%rdi
              122:   shl    $0x20,%rdi
    
              126:   shr    $0x20,%rdi
    
              12a:   cmp    $0xff,%rdi
              131: → ja     0
              133:   add    $0x48,%rax
              137:   and    $0xff,%rax
              13d:   mov    %rax,%r8
              140:   mov    %rbp,%rcx
              143:   add    $0xfffffffffffffeb8,%rcx
              14a:   mov    %rbx,%rdi
              14d:   movabs $0xffff975fbd72d800,%rsi
    
              157:   mov    $0xffffffff,%edx
              15c: → callq  *ffffffffda658ad9
              161:   mov    %rax,%r13
              164:   mov    %r13,%rax
        0.72  167:   mov    0x0(%rbp),%rbx
              16b:   mov    0x8(%rbp),%r13
        1.16  16f:   mov    0x10(%rbp),%r14
        0.10  173:   mov    0x18(%rbp),%r15
        0.42  177:   add    $0x28,%rbp
        0.54  17b:   leaveq
        0.54  17c: ← retq
    
    Another cool way to test all this is to symple use 'perf top' look for
    those symbols, go there and press enter, annotate it live :-)
    
    Signed-off-by: Song Liu <songliubraving@fb.com>
    Reviewed-by: Jiri Olsa <jolsa@kernel.org>
    Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Alexei Starovoitov <ast@kernel.org>
    Cc: Daniel Borkmann <daniel@iogearbox.net>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Stanislav Fomichev <sdf@google.com>
    Link: http://lkml.kernel.org/r/20190312053051.2690567-13-songliubraving@fb.com
    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Song Liu March 19, 2019, 4:51 p.m. UTC | #10
> On Mar 19, 2019, at 7:52 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> 
> Em Tue, Mar 19, 2019 at 11:14:35AM -0300, Arnaldo Carvalho de Melo escreveu:
>> 
>> Now the test is really being performed, the test-all.bin feature
>> detection fast path is working, proceeding.
> 
> Now it all works, really nice!
> 
> I added a 'Committer testing' section with all the steps to test this
> and pushed to:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/commit/?h=perf/core&id=6530d44e7dc1d41c73fe70b9e6ea1b9cabebb57f

Thanks Arnaldo! This looks great!

I will rebase https://lkml.org/lkml/2019/3/14/681 on top of this branch
and resend. 

Song


> Which I repeat here, please go thru it and check if everything is ok, if
> the disassembled + original BPF source code looks ok, etc:
> 
>    Committer testing:
> 
>    1) Have a BPF program running, one that has BTF info, etc, I used
>       the tools/perf/examples/bpf/augmented_raw_syscalls.c put in place
>       by 'perf trace'.
> 
>      # grep -B1 augmented_raw ~/.perfconfig
>      [trace]
>            add_events = /home/acme/git/perf/tools/perf/examples/bpf/augmented_raw_syscalls.c
>      #
>      # perf trace -e *mmsg
>      dnf/6245 sendmmsg(20, 0x7f5485a88030, 2, MSG_NOSIGNAL) = 2
>      NetworkManager/10055 sendmmsg(22<socket:[1056822]>, 0x7f8126ad1bb0, 2, MSG_NOSIGNAL) = 2
> 
>    2) Then do a 'perf record' system wide for a while:
> 
>      # perf record -a
>      ^C[ perf record: Woken up 68 times to write data ]
>      [ perf record: Captured and wrote 19.427 MB perf.data (366891 samples) ]
>      #
> 
>    3) Check that we captured BPF and BTF info in the perf.data file:
> 
>      # perf report --header-only | grep 'b[pt]f'
>      # event : name = cycles:ppp, , id = { 294789, 294790, 294791, 294792, 294793, 294794, 294795, 294796 }, size = 112, { sample_period, sample_freq } = 4000, sample_type = IP|TID|TIME|CPU|PERIOD, read_format = ID, disabled = 1, inherit = 1, mmap = 1, comm = 1, freq = 1, task = 1, precise_ip = 3, sample_id_all = 1, exclude_guest = 1, mmap2 = 1, comm_exec = 1, ksymbol = 1, bpf_event = 1
>      # bpf_prog_info of id 13
>      # bpf_prog_info of id 14
>      # bpf_prog_info of id 15
>      # bpf_prog_info of id 16
>      # bpf_prog_info of id 17
>      # bpf_prog_info of id 18
>      # bpf_prog_info of id 21
>      # bpf_prog_info of id 22
>      # bpf_prog_info of id 41
>      # bpf_prog_info of id 42
>      # btf info of id 2
>      #
> 
>    4) Check which programs got recorded:
> 
>       # perf report | grep bpf_prog | head
>         0.16%  exe              bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
>         0.14%  exe              bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
>         0.08%  fuse-overlayfs   bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
>         0.07%  fuse-overlayfs   bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
>         0.01%  clang-4.0        bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
>         0.01%  clang-4.0        bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
>         0.00%  clang            bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
>         0.00%  runc             bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
>         0.00%  clang            bpf_prog_819967866022f1e1_sys_enter      [k] bpf_prog_819967866022f1e1_sys_enter
>         0.00%  sh               bpf_prog_c1bd85c092d6e4aa_sys_exit       [k] bpf_prog_c1bd85c092d6e4aa_sys_exit
>      #
> 
>      This was with the default --sort order for 'perf report', which is:
> 
>        --sort comm,dso,symbol
> 
>      If we just look for the symbol, for instance:
> 
>       # perf report --sort symbol | grep bpf_prog | head
>         0.26%  [k] bpf_prog_819967866022f1e1_sys_enter                -      -
>         0.24%  [k] bpf_prog_c1bd85c092d6e4aa_sys_exit                 -      -
>       #
> 
>      or the DSO:
> 
>       # perf report --sort dso | grep bpf_prog | head
>         0.26%  bpf_prog_819967866022f1e1_sys_enter
>         0.24%  bpf_prog_c1bd85c092d6e4aa_sys_exit
>      #
> 
>    We'll see the two BPF programs that augmented_raw_syscalls.o puts in
>    place,  one attached to the raw_syscalls:sys_enter and another to the
>    raw_syscalls:sys_exit tracepoints, as expected.
> 
>    Now we can finally do, from the command line, annotation for one of
>    those two symbols, with the original BPF program source coude intermixed
>    with the disassembled JITed code:
> 
>      # perf annotate --stdio2 bpf_prog_819967866022f1e1_sys_enter
> 
>      Samples: 950  of event 'cycles:ppp', 4000 Hz, Event count (approx.): 553756947, [percent: local period]
>      bpf_prog_819967866022f1e1_sys_enter() bpf_prog_819967866022f1e1_sys_enter
>      Percent      int sys_enter(struct syscall_enter_args *args)
>       53.41         push   %rbp
> 
>        0.63         mov    %rsp,%rbp
>        0.31         sub    $0x170,%rsp
>        1.93         sub    $0x28,%rbp
>        7.02         mov    %rbx,0x0(%rbp)
>        3.20         mov    %r13,0x8(%rbp)
>        1.07         mov    %r14,0x10(%rbp)
>        0.61         mov    %r15,0x18(%rbp)
>        0.11         xor    %eax,%eax
>        1.29         mov    %rax,0x20(%rbp)
>        0.11         mov    %rdi,%rbx
>                    return bpf_get_current_pid_tgid();
>        2.02       → callq  *ffffffffda6776d9
>        2.76         mov    %eax,-0x148(%rbp)
>                     mov    %rbp,%rsi
>                   int sys_enter(struct syscall_enter_args *args)
>                     add    $0xfffffffffffffeb8,%rsi
>                    return bpf_map_lookup_elem(pids, &pid) != NULL;
>                     movabs $0xffff975ac2607800,%rdi
> 
>        1.26       → callq  *ffffffffda6789e9
>                     cmp    $0x0,%rax
>        2.43       → je     0
>                     add    $0x38,%rax
>        0.21         xor    %r13d,%r13d
>                    if (pid_filter__has(&pids_filtered, getpid()))
>        0.81         cmp    $0x0,%rax
>                   → jne    0
>                     mov    %rbp,%rdi
>                    probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
>        2.22         add    $0xfffffffffffffeb8,%rdi
>        0.11         mov    $0x40,%esi
>        0.32         mov    %rbx,%rdx
>        2.74       → callq  *ffffffffda658409
>                    syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr);
>        0.22         mov    %rbp,%rsi
>        1.69         add    $0xfffffffffffffec0,%rsi
>                    syscall = bpf_map_lookup_elem(&syscalls, &augmented_args.args.syscall_nr);
>                     movabs $0xffff975bfcd36000,%rdi
> 
>                     add    $0xd0,%rdi
>        0.21         mov    0x0(%rsi),%eax
>        0.93         cmp    $0x200,%rax
>                   → jae    0
>        0.10         shl    $0x3,%rax
> 
>        0.11         add    %rdi,%rax
>        0.11       → jmp    0
>                     xor    %eax,%eax
>                    if (syscall == NULL || !syscall->enabled)
>        1.07         cmp    $0x0,%rax
>                   → je     0
>                    if (syscall == NULL || !syscall->enabled)
>        6.57         movzbq 0x0(%rax),%rdi
> 
>                    if (syscall == NULL || !syscall->enabled)
>                     cmp    $0x0,%rdi
>        0.95       → je     0
>                     mov    $0x40,%r8d
>                    switch (augmented_args.args.syscall_nr) {
>                     mov    -0x140(%rbp),%rdi
>                    switch (augmented_args.args.syscall_nr) {
>                     cmp    $0x2,%rdi
>                   → je     0
>                     cmp    $0x101,%rdi
>                   → je     0
>                     cmp    $0x15,%rdi
>                   → jne    0
>                    case SYS_OPEN:   filename_arg = (const void *)args->args[0];
>                     mov    0x10(%rbx),%rdx
>                   → jmp    0
>                    case SYS_OPENAT: filename_arg = (const void *)args->args[1];
>                     mov    0x18(%rbx),%rdx
>                    if (filename_arg != NULL) {
>                     cmp    $0x0,%rdx
>                   → je     0
>                     xor    %edi,%edi
>                            augmented_args.filename.reserved = 0;
>                     mov    %edi,-0x104(%rbp)
>                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
>                     mov    %rbp,%rdi
>                     add    $0xffffffffffffff00,%rdi
>                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
>                     mov    $0x100,%esi
>                   → callq  *ffffffffda658499
>                     mov    $0x148,%r8d
>                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
>                     mov    %eax,-0x108(%rbp)
>                            augmented_args.filename.size = probe_read_str(&augmented_args.filename.value,
>                     mov    %rax,%rdi
>                     shl    $0x20,%rdi
> 
>                     shr    $0x20,%rdi
> 
>                            if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) {
>                     cmp    $0xff,%rdi
>                   → ja     0
>                                    len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size;
>                     add    $0x48,%rax
>                                    len &= sizeof(augmented_args.filename.value) - 1;
>                     and    $0xff,%rax
>                     mov    %rax,%r8
>                     mov    %rbp,%rcx
>                    return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, len);
>                     add    $0xfffffffffffffeb8,%rcx
>                     mov    %rbx,%rdi
>                     movabs $0xffff975fbd72d800,%rsi
> 
>                     mov    $0xffffffff,%edx
>                   → callq  *ffffffffda658ad9
>                     mov    %rax,%r13
>                   }
>                     mov    %r13,%rax
>        0.72         mov    0x0(%rbp),%rbx
>                     mov    0x8(%rbp),%r13
>        1.16         mov    0x10(%rbp),%r14
>        0.10         mov    0x18(%rbp),%r15
>        0.42         add    $0x28,%rbp
>        0.54         leaveq
>        0.54       ← retq
>      #
> 
>    Please see 'man perf-config' to see how to control what should be seen,
>    via ~/.perfconfig [annotate] section, for instance, one can suppress the
>    source code and see just the disassembly, etc.
> 
>    Alternatively, use the TUI bu just using 'perf annotate', press
>    '/bpf_prog' to see the bpf symbols, press enter and do the interactive
>    annotation, which allows for dumping to a file after selecting the
>    the various output tunables, for instance, the above without source code
>    intermixed, plus showing all the instruction offsets:
> 
>      # perf annotate bpf_prog_819967866022f1e1_sys_enter
> 
>    Then press: 's' to hide the source code + 'O' twice to show all
>    instruction offsets, then 'P' to print to the
>    bpf_prog_819967866022f1e1_sys_enter.annotation file, which will have:
> 
>      # cat bpf_prog_819967866022f1e1_sys_enter.annotation
>      bpf_prog_819967866022f1e1_sys_enter() bpf_prog_819967866022f1e1_sys_enter
>      Event: cycles:ppp
> 
>       53.41    0:   push   %rbp
> 
>        0.63    1:   mov    %rsp,%rbp
>        0.31    4:   sub    $0x170,%rsp
>        1.93    b:   sub    $0x28,%rbp
>        7.02    f:   mov    %rbx,0x0(%rbp)
>        3.20   13:   mov    %r13,0x8(%rbp)
>        1.07   17:   mov    %r14,0x10(%rbp)
>        0.61   1b:   mov    %r15,0x18(%rbp)
>        0.11   1f:   xor    %eax,%eax
>        1.29   21:   mov    %rax,0x20(%rbp)
>        0.11   25:   mov    %rdi,%rbx
>        2.02   28: → callq  *ffffffffda6776d9
>        2.76   2d:   mov    %eax,-0x148(%rbp)
>               33:   mov    %rbp,%rsi
>               36:   add    $0xfffffffffffffeb8,%rsi
>               3d:   movabs $0xffff975ac2607800,%rdi
> 
>        1.26   47: → callq  *ffffffffda6789e9
>               4c:   cmp    $0x0,%rax
>        2.43   50: → je     0
>               52:   add    $0x38,%rax
>        0.21   56:   xor    %r13d,%r13d
>        0.81   59:   cmp    $0x0,%rax
>               5d: → jne    0
>               63:   mov    %rbp,%rdi
>        2.22   66:   add    $0xfffffffffffffeb8,%rdi
>        0.11   6d:   mov    $0x40,%esi
>        0.32   72:   mov    %rbx,%rdx
>        2.74   75: → callq  *ffffffffda658409
>        0.22   7a:   mov    %rbp,%rsi
>        1.69   7d:   add    $0xfffffffffffffec0,%rsi
>               84:   movabs $0xffff975bfcd36000,%rdi
> 
>               8e:   add    $0xd0,%rdi
>        0.21   95:   mov    0x0(%rsi),%eax
>        0.93   98:   cmp    $0x200,%rax
>               9f: → jae    0
>        0.10   a1:   shl    $0x3,%rax
> 
>        0.11   a5:   add    %rdi,%rax
>        0.11   a8: → jmp    0
>               aa:   xor    %eax,%eax
>        1.07   ac:   cmp    $0x0,%rax
>               b0: → je     0
>        6.57   b6:   movzbq 0x0(%rax),%rdi
> 
>               bb:   cmp    $0x0,%rdi
>        0.95   bf: → je     0
>               c5:   mov    $0x40,%r8d
>               cb:   mov    -0x140(%rbp),%rdi
>               d2:   cmp    $0x2,%rdi
>               d6: → je     0
>               d8:   cmp    $0x101,%rdi
>               df: → je     0
>               e1:   cmp    $0x15,%rdi
>               e5: → jne    0
>               e7:   mov    0x10(%rbx),%rdx
>               eb: → jmp    0
>               ed:   mov    0x18(%rbx),%rdx
>               f1:   cmp    $0x0,%rdx
>               f5: → je     0
>               f7:   xor    %edi,%edi
>               f9:   mov    %edi,-0x104(%rbp)
>               ff:   mov    %rbp,%rdi
>              102:   add    $0xffffffffffffff00,%rdi
>              109:   mov    $0x100,%esi
>              10e: → callq  *ffffffffda658499
>              113:   mov    $0x148,%r8d
>              119:   mov    %eax,-0x108(%rbp)
>              11f:   mov    %rax,%rdi
>              122:   shl    $0x20,%rdi
> 
>              126:   shr    $0x20,%rdi
> 
>              12a:   cmp    $0xff,%rdi
>              131: → ja     0
>              133:   add    $0x48,%rax
>              137:   and    $0xff,%rax
>              13d:   mov    %rax,%r8
>              140:   mov    %rbp,%rcx
>              143:   add    $0xfffffffffffffeb8,%rcx
>              14a:   mov    %rbx,%rdi
>              14d:   movabs $0xffff975fbd72d800,%rsi
> 
>              157:   mov    $0xffffffff,%edx
>              15c: → callq  *ffffffffda658ad9
>              161:   mov    %rax,%r13
>              164:   mov    %r13,%rax
>        0.72  167:   mov    0x0(%rbp),%rbx
>              16b:   mov    0x8(%rbp),%r13
>        1.16  16f:   mov    0x10(%rbp),%r14
>        0.10  173:   mov    0x18(%rbp),%r15
>        0.42  177:   add    $0x28,%rbp
>        0.54  17b:   leaveq
>        0.54  17c: ← retq
> 
>    Another cool way to test all this is to symple use 'perf top' look for
>    those symbols, go there and press enter, annotate it live :-)
> 
>    Signed-off-by: Song Liu <songliubraving@fb.com>
>    Reviewed-by: Jiri Olsa <jolsa@kernel.org>
>    Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
>    Cc: Alexei Starovoitov <ast@kernel.org>
>    Cc: Daniel Borkmann <daniel@iogearbox.net>
>    Cc: Namhyung Kim <namhyung@kernel.org>
>    Cc: Peter Zijlstra <peterz@infradead.org>
>    Cc: Stanislav Fomichev <sdf@google.com>
>    Link: http://lkml.kernel.org/r/20190312053051.2690567-13-songliubraving@fb.com
>    Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Arnaldo Carvalho de Melo March 19, 2019, 4:55 p.m. UTC | #11
Em Tue, Mar 19, 2019 at 04:51:44PM +0000, Song Liu escreveu:
> 
> 
> > On Mar 19, 2019, at 7:52 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> > 
> > Em Tue, Mar 19, 2019 at 11:14:35AM -0300, Arnaldo Carvalho de Melo escreveu:
> >> 
> >> Now the test is really being performed, the test-all.bin feature
> >> detection fast path is working, proceeding.
> > 
> > Now it all works, really nice!
> > 
> > I added a 'Committer testing' section with all the steps to test this
> > and pushed to:
> > 
> > https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/commit/?h=perf/core&id=6530d44e7dc1d41c73fe70b9e6ea1b9cabebb57f
> 
> Thanks Arnaldo! This looks great!
> 
> I will rebase https://lkml.org/lkml/2019/3/14/681 on top of this branch
> and resend. 

I just found one new bug, that may appear now since I took a series of
fixes found by gcc's ASan feature, i.e. on the exit path we're crashing
on:

[root@quaco ~]# perf top
perf: Segmentation fault
-------- backtrace --------
perf[0x5a785a]
/lib64/libc.so.6(+0x385bf)[0x7fd68443c5bf]
perf(rb_first+0x2b)[0x4d6eeb]
perf(dso__delete+0xb7)[0x4dffb7]
perf[0x4f9e37]
perf(perf_session__delete+0x64)[0x504df4]
perf(cmd_top+0x1957)[0x454467]
perf[0x4aad18]
perf(main+0x61c)[0x42ec7c]
/lib64/libc.so.6(__libc_start_main+0xf2)[0x7fd684428412]
perf(_start+0x2d)[0x42eead]
[root@quaco ~]#
[root@quaco ~]# addr2line -fe ~/bin/perf 0x4dffb7
dso_cache__free
/home/acme/git/perf/tools/perf/util/dso.c:713


And that is because of that union:

+       union {
+               /* dso data file */
+               struct {
+                       struct rb_root   cache;
+                       int              fd;
+                       int              status;
+                       u32              status_seen;
+                       size_t           file_size;
+                       struct list_head open_entry;
+                       u64              debug_frame_offset;
+                       u64              eh_frame_hdr_offset;
+               } data;
+               /* bpf prog information */
+               struct {
+                       u32             id;
+                       u32             sub_id;
+                       struct perf_env *env;
+               } bpf_prog;
+       };


On the dso exit path, it is trying to traverse the data.cache rbtree,
when what is that is that bpf_prog.id, etc, I'll just remove the union
for now, later we can do the data.cache access or bpf_prog based on some
other test.
Arnaldo Carvalho de Melo March 19, 2019, 5:07 p.m. UTC | #12
Em Tue, Mar 19, 2019 at 01:55:31PM -0300, Arnaldo Carvalho de Melo escreveu:
> Em Tue, Mar 19, 2019 at 04:51:44PM +0000, Song Liu escreveu:
> > 
> > 
> > > On Mar 19, 2019, at 7:52 AM, Arnaldo Carvalho de Melo <arnaldo.melo@gmail.com> wrote:
> > > 
> > > Em Tue, Mar 19, 2019 at 11:14:35AM -0300, Arnaldo Carvalho de Melo escreveu:
> > >> 
> > >> Now the test is really being performed, the test-all.bin feature
> > >> detection fast path is working, proceeding.
> > > 
> > > Now it all works, really nice!
> > > 
> > > I added a 'Committer testing' section with all the steps to test this
> > > and pushed to:
> > > 
> > > https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/commit/?h=perf/core&id=6530d44e7dc1d41c73fe70b9e6ea1b9cabebb57f
> > 
> > Thanks Arnaldo! This looks great!
> > 
> > I will rebase https://lkml.org/lkml/2019/3/14/681 on top of this branch
> > and resend. 
> 
> I just found one new bug, that may appear now since I took a series of
> fixes found by gcc's ASan feature, i.e. on the exit path we're crashing
> on:
> 
> [root@quaco ~]# perf top
> perf: Segmentation fault
> -------- backtrace --------
> perf[0x5a785a]
> /lib64/libc.so.6(+0x385bf)[0x7fd68443c5bf]
> perf(rb_first+0x2b)[0x4d6eeb]
> perf(dso__delete+0xb7)[0x4dffb7]
> perf[0x4f9e37]
> perf(perf_session__delete+0x64)[0x504df4]
> perf(cmd_top+0x1957)[0x454467]
> perf[0x4aad18]
> perf(main+0x61c)[0x42ec7c]
> /lib64/libc.so.6(__libc_start_main+0xf2)[0x7fd684428412]
> perf(_start+0x2d)[0x42eead]
> [root@quaco ~]#
> [root@quaco ~]# addr2line -fe ~/bin/perf 0x4dffb7
> dso_cache__free
> /home/acme/git/perf/tools/perf/util/dso.c:713
> 
> 
> And that is because of that union:
> 
> +       union {
> +               /* dso data file */
> +               struct {
> +                       struct rb_root   cache;
> +                       int              fd;
> +                       int              status;
> +                       u32              status_seen;
> +                       size_t           file_size;
> +                       struct list_head open_entry;
> +                       u64              debug_frame_offset;
> +                       u64              eh_frame_hdr_offset;
> +               } data;
> +               /* bpf prog information */
> +               struct {
> +                       u32             id;
> +                       u32             sub_id;
> +                       struct perf_env *env;
> +               } bpf_prog;
> +       };
> 
> 
> On the dso exit path, it is trying to traverse the data.cache rbtree,
> when what is that is that bpf_prog.id, etc, I'll just remove the union
> for now, later we can do the data.cache access or bpf_prog based on some
> other test.

One more on 32-bit arches, a uintptr_t case for the jited_ksyms on the
BPF annotate patch, will fix.

- Arnaldo
diff mbox series

Patch

diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 61e46d54a67c..8d3864b061f3 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -66,7 +66,8 @@  FEATURE_TESTS_BASIC :=                  \
         sched_getcpu			\
         sdt				\
         setns				\
-        libaio
+        libaio				\
+        disassembler-four-args
 
 # FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
 # of all feature tests
@@ -118,7 +119,8 @@  FEATURE_DISPLAY ?=              \
          lzma                   \
          get_cpuid              \
          bpf			\
-         libaio
+         libaio			\
+         disassembler-four-args
 
 # Set FEATURE_CHECK_(C|LD)FLAGS-all for all FEATURE_TESTS features.
 # If in the future we need per-feature checks/flags for features not
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index df4ad45599ca..c51b59e43dcc 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -808,6 +808,10 @@  ifdef HAVE_KVM_STAT_SUPPORT
     CFLAGS += -DHAVE_KVM_STAT_SUPPORT
 endif
 
+ifeq ($(feature-disassembler-four-args), 1)
+    CFLAGS += -DDISASM_FOUR_ARGS_SIGNATURE
+endif
+
 ifeq (${IS_64_BIT}, 1)
   ifndef NO_PERF_READ_VDSO32
     $(call feature_check,compile-32)
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 5f6dbbf5d749..e492b19a157c 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -10,6 +10,10 @@ 
 #include <errno.h>
 #include <inttypes.h>
 #include <libgen.h>
+#include <bpf/bpf.h>
+#include <bpf/btf.h>
+#include <bpf/libbpf.h>
+#include <linux/btf.h>
 #include "util.h"
 #include "ui/ui.h"
 #include "sort.h"
@@ -24,6 +28,7 @@ 
 #include "annotate.h"
 #include "evsel.h"
 #include "evlist.h"
+#include "bpf-event.h"
 #include "block-range.h"
 #include "string2.h"
 #include "arch/common.h"
@@ -31,6 +36,9 @@ 
 #include <pthread.h>
 #include <linux/bitops.h>
 #include <linux/kernel.h>
+#include <bfd.h>
+#include <dis-asm.h>
+#include <bpf/libbpf.h>
 
 /* FIXME: For the HE_COLORSET */
 #include "ui/browser.h"
@@ -1674,6 +1682,144 @@  static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil
 	return 0;
 }
 
+static int symbol__disassemble_bpf(struct symbol *sym,
+				   struct annotate_args *args)
+{
+	struct annotation *notes = symbol__annotation(sym);
+	struct annotation_options *opts = args->options;
+	struct bpf_prog_info_linear *info_linear;
+	struct bpf_prog_linfo *prog_linfo = NULL;
+	struct bpf_prog_info_node *info_node;
+	int len = sym->end - sym->start;
+	disassembler_ftype disassemble;
+	struct map *map = args->ms.map;
+	struct disassemble_info info;
+	struct dso *dso = map->dso;
+	int pc = 0, count, sub_id;
+	struct btf *btf = NULL;
+	char tpath[PATH_MAX];
+	size_t buf_size;
+	int nr_skip = 0;
+	int ret = -1;
+	char *buf;
+	bfd *bfdf;
+	FILE *s;
+
+	if (dso->binary_type != DSO_BINARY_TYPE__BPF_PROG_INFO)
+		return -1;
+
+	pr_debug("%s: handling sym %s addr %lx len %lx\n", __func__,
+		 sym->name, sym->start, sym->end - sym->start);
+
+	memset(tpath, 0, sizeof(tpath));
+	perf_exe(tpath, sizeof(tpath));
+
+	bfdf = bfd_openr(tpath, NULL);
+	assert(bfdf);
+	assert(bfd_check_format(bfdf, bfd_object));
+
+	s = open_memstream(&buf, &buf_size);
+	if (!s)
+		goto out;
+	init_disassemble_info(&info, s,
+			      (fprintf_ftype) fprintf);
+
+	info.arch = bfd_get_arch(bfdf);
+	info.mach = bfd_get_mach(bfdf);
+
+	info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env,
+						 dso->bpf_prog.id);
+	if (!info_node)
+		goto out;
+	info_linear = info_node->info_linear;
+	sub_id = dso->bpf_prog.sub_id;
+
+	info.buffer = (void *)(info_linear->info.jited_prog_insns);
+	info.buffer_length = info_linear->info.jited_prog_len;
+
+	if (info_linear->info.nr_line_info)
+		prog_linfo = bpf_prog_linfo__new(&info_linear->info);
+
+	if (info_linear->info.btf_id) {
+		struct btf_node *node;
+
+		node = perf_env__find_btf(dso->bpf_prog.env,
+					  info_linear->info.btf_id);
+		if (node)
+			btf = btf__new((__u8 *)(node->data),
+				       node->data_size);
+	}
+
+	disassemble_init_for_target(&info);
+
+#ifdef DISASM_FOUR_ARGS_SIGNATURE
+	disassemble = disassembler(info.arch,
+				   bfd_big_endian(bfdf),
+				   info.mach,
+				   bfdf);
+#else
+	disassemble = disassembler(bfdf);
+#endif
+	assert(disassemble);
+
+	fflush(s);
+	do {
+		const struct bpf_line_info *linfo = NULL;
+		struct disasm_line *dl;
+		size_t prev_buf_size;
+		const char *srcline;
+		u64 addr;
+
+		addr = pc + ((u64 *)(info_linear->info.jited_ksyms))[sub_id];
+		count = disassemble(pc, &info);
+
+		if (prog_linfo)
+			linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo,
+								addr, sub_id,
+								nr_skip);
+
+		if (linfo && btf) {
+			srcline = btf__name_by_offset(btf, linfo->line_off);
+			nr_skip++;
+		} else
+			srcline = NULL;
+
+		fprintf(s, "\n");
+		prev_buf_size = buf_size;
+		fflush(s);
+
+		if (!opts->hide_src_code && srcline) {
+			args->offset = -1;
+			args->line = strdup(srcline);
+			args->line_nr = 0;
+			args->ms.sym  = sym;
+			dl = disasm_line__new(args);
+			if (dl) {
+				annotation_line__add(&dl->al,
+						     &notes->src->source);
+			}
+		}
+
+		args->offset = pc;
+		args->line = buf + prev_buf_size;
+		args->line_nr = 0;
+		args->ms.sym  = sym;
+		dl = disasm_line__new(args);
+		if (dl)
+			annotation_line__add(&dl->al, &notes->src->source);
+
+		pc += count;
+	} while (count > 0 && pc < len);
+
+	ret = 0;
+out:
+	free(prog_linfo);
+	free(btf);
+	fclose(s);
+	bfd_close(bfdf);
+	return ret;
+}
+
 static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 {
 	struct annotation_options *opts = args->options;
@@ -1701,7 +1847,9 @@  static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
 	pr_debug("annotating [%p] %30s : [%p] %30s\n",
 		 dso, dso->long_name, sym, sym->name);
 
-	if (dso__is_kcore(dso)) {
+	if (dso->binary_type == DSO_BINARY_TYPE__BPF_PROG_INFO) {
+		return symbol__disassemble_bpf(sym, args);
+	} else if (dso__is_kcore(dso)) {
 		kce.kcore_filename = symfs_filename;
 		kce.addr = map__rip_2objdump(map, sym->start);
 		kce.offs = sym->start;
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index ba58ba603b69..58547c468c65 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -184,6 +184,7 @@  int dso__read_binary_type_filename(const struct dso *dso,
 	case DSO_BINARY_TYPE__KALLSYMS:
 	case DSO_BINARY_TYPE__GUEST_KALLSYMS:
 	case DSO_BINARY_TYPE__JAVA_JIT:
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
 	case DSO_BINARY_TYPE__NOT_FOUND:
 		ret = -1;
 		break;
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index bb417c54c25a..c274b5aa839d 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -14,6 +14,7 @@ 
 
 struct machine;
 struct map;
+struct perf_env;
 
 enum dso_binary_type {
 	DSO_BINARY_TYPE__KALLSYMS = 0,
@@ -35,6 +36,7 @@  enum dso_binary_type {
 	DSO_BINARY_TYPE__KCORE,
 	DSO_BINARY_TYPE__GUEST_KCORE,
 	DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO,
+	DSO_BINARY_TYPE__BPF_PROG_INFO,
 	DSO_BINARY_TYPE__NOT_FOUND,
 };
 
@@ -178,17 +180,25 @@  struct dso {
 	struct auxtrace_cache *auxtrace_cache;
 	int		 comp;
 
-	/* dso data file */
-	struct {
-		struct rb_root	 cache;
-		int		 fd;
-		int		 status;
-		u32		 status_seen;
-		size_t		 file_size;
-		struct list_head open_entry;
-		u64		 debug_frame_offset;
-		u64		 eh_frame_hdr_offset;
-	} data;
+	union {
+		/* dso data file */
+		struct {
+			struct rb_root	 cache;
+			int		 fd;
+			int		 status;
+			u32		 status_seen;
+			size_t		 file_size;
+			struct list_head open_entry;
+			u64		 debug_frame_offset;
+			u64		 eh_frame_hdr_offset;
+		} data;
+		/* bpf prog information */
+		struct {
+			u32		id;
+			u32		sub_id;
+			struct perf_env	*env;
+		} bpf_prog;
+	};
 
 	union { /* Tool specific area */
 		void	 *priv;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 758bf5f74e6e..4e2e304d4037 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1451,6 +1451,7 @@  static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
 	case DSO_BINARY_TYPE__BUILD_ID_CACHE_DEBUGINFO:
 		return true;
 
+	case DSO_BINARY_TYPE__BPF_PROG_INFO:
 	case DSO_BINARY_TYPE__NOT_FOUND:
 	default:
 		return false;