Message ID | 20190215215354.3114006-11-songliubraving@fb.com |
---|---|
State | Changes Requested |
Delegated to: | BPF Maintainers |
Headers | show |
Series | perf annotation of BPF programs | expand |
On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote: SNIP > diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c > index 70de8f6b3aee..078017d31ca9 100644 > --- a/tools/perf/util/annotate.c > +++ b/tools/perf/util/annotate.c > @@ -22,6 +22,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" > @@ -29,6 +30,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" > @@ -1672,6 +1676,147 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil > return 0; > } > > +static void get_exec_path(char *tpath, size_t size) > +{ > + const char *path = "/proc/self/exe"; > + ssize_t len; > + > + len = readlink(path, tpath, size - 1); > + assert(len > 0); > + tpath[len] = 0; > +} this is also used in write_cmdline, could you please move it under util.c and use it in write_cmdline as well? thanks, jirka > + > +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; > + __u64 arrays; > + char *buf; > + bfd *bfdf; > + FILE *s; nice triangle ;-) SNIP
On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote: > 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/perf/Makefile.config | 6 +- > tools/perf/util/annotate.c | 149 +++++++++++++++++++++++++++++++++++- > tools/perf/util/bpf-event.c | 48 ++++++++++++ > tools/perf/util/bpf-event.h | 4 + > tools/perf/util/dso.c | 1 + > tools/perf/util/dso.h | 33 +++++--- > tools/perf/util/symbol.c | 1 + > 7 files changed, 229 insertions(+), 13 deletions(-) > > diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config > index b441c88cafa1..ab223239f1fb 100644 > --- a/tools/perf/Makefile.config > +++ b/tools/perf/Makefile.config > @@ -701,7 +701,7 @@ else > endif > > ifeq ($(feature-libbfd), 1) > - EXTLIBS += -lbfd > + EXTLIBS += -lbfd -lopcodes hum, what's this -lopcodes lib? please add it in a separate patch and explain why it's added and how it affects others it looks like it could break some distros without that lib jirka
On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote: SNIP > +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; > + __u64 arrays; > + 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)); > + get_exec_path(tpath, sizeof(tpath)); > + > + bfdf = bfd_openr(tpath, NULL); > + assert(bfdf); > + assert(bfd_check_format(bfdf, bfd_object)); > + > + s = open_memstream(&buf, &buf_size); what if open_memstream fails? > + init_disassemble_info(&info, s, > + (fprintf_ftype) fprintf); > + > + info.arch = bfd_get_arch(bfdf); > + info.mach = bfd_get_mach(bfdf); > + > + arrays = 1UL << BPF_PROG_INFO_JITED_INSNS; > + arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS; > + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; > + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; what's the arrays for? > + > + info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, > + dso->bpf_prog.id); > + if (!info_node) > + return -1; > + 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); > + prog_linfo = prog_linfo; > + > + 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); > + } what if btf__new fails? the btf__name_by_offset does not check btf != NULL > + > + 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); any chance this function could be split into some logical pieces/fucntions? thanks, jirka > + 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); > + > + linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, addr, sub_id, > + nr_skip); > + > + if (linfo) { > + 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); > + annotation_line__add(&dl->al, ¬es->src->source); > + } > + > + args->offset = pc; > + args->line = buf + prev_buf_size; > + args->line_nr = 0; > + args->ms.sym = sym; > + dl = disasm_line__new(args); > + annotation_line__add(&dl->al, ¬es->src->source); > + > + pc += count; > + } while (count > 0 && pc < len); > + > + bfd_close(bfdf); > + return 0; > +} SNIP
On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote: SNIP > int machine__process_bpf_event(struct machine *machine __maybe_unused, > union perf_event *event, > struct perf_sample *sample __maybe_unused) > { > if (dump_trace) > perf_event__fprintf_bpf_event(event, stdout); > + > + switch (event->bpf_event.type) { > + case PERF_BPF_EVENT_PROG_LOAD: > + return machine__process_bpf_event_load(machine, event, sample); > + > + case PERF_BPF_EVENT_PROG_UNLOAD: > + break; could we make a comment here, descriving why we dont remove bpf programs.. which I assume is intentional thanks, jirka
On Fri, Feb 15, 2019 at 01:53:53PM -0800, Song Liu wrote: SNIP > diff --git a/tools/perf/util/bpf-event.c b/tools/perf/util/bpf-event.c > index 52507435c464..6c363adc781a 100644 > --- a/tools/perf/util/bpf-event.c > +++ b/tools/perf/util/bpf-event.c > @@ -25,12 +25,60 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len) > return ret; > } > please move PERF_BPF_EVENT_PROG_LOAD/PERF_BPF_EVENT_PROG_UNLOAD handling code below into separate patch from the bpf disassembly code thanks, jirka > +static int machine__process_bpf_event_load(struct machine *machine __maybe_unused, > + union perf_event *event, > + struct perf_sample *sample __maybe_unused) > +{ > + struct bpf_prog_info_linear *info_linear; > + struct bpf_prog_info_node *info_node; > + struct perf_env *env = machine->env; > + int id = event->bpf_event.id; > + unsigned int i; > + > + /* perf-record, no need to handle bpf-event */ > + if (env == NULL) > + return 0; > + > + info_node = perf_env__find_bpf_prog_info(env, id); > + if (!info_node) > + return 0; > + info_linear = info_node->info_linear; > + > + for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) { > + u64 *addrs = (u64 *)(info_linear->info.jited_ksyms); > + u64 addr = addrs[i]; > + struct map *map; > + > + map = map_groups__find(&machine->kmaps, addr); > + > + if (map) { > + map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO; > + map->dso->bpf_prog.id = id; > + map->dso->bpf_prog.sub_id = i; > + map->dso->bpf_prog.env = env; > + } > + } > + return 0; > +} > + > int machine__process_bpf_event(struct machine *machine __maybe_unused, > union perf_event *event, > struct perf_sample *sample __maybe_unused) > { > if (dump_trace) > perf_event__fprintf_bpf_event(event, stdout); > + > + switch (event->bpf_event.type) { > + case PERF_BPF_EVENT_PROG_LOAD: > + return machine__process_bpf_event_load(machine, event, sample); > + > + case PERF_BPF_EVENT_PROG_UNLOAD: > + break; > + default: > + pr_debug("unexpected bpf_event type of %d\n", > + event->bpf_event.type); > + break; > + } > return 0; > } > > diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h > index b9ec394dc7c7..ab4a975b7e05 100644 > --- a/tools/perf/util/bpf-event.h > +++ b/tools/perf/util/bpf-event.h > @@ -2,6 +2,10 @@ > #ifndef __PERF_BPF_EVENT_H > #define __PERF_BPF_EVENT_H > > +#include <bpf/bpf.h> > +#include <bpf/btf.h> > +#include <bpf/libbpf.h> > +#include <linux/btf.h> > #include <linux/compiler.h> > #include <linux/rbtree.h> > #include "event.h" > diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c > index 62c8cf622607..1798192bf0f9 100644 > --- a/tools/perf/util/dso.c > +++ b/tools/perf/util/dso.c > @@ -181,6 +181,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 8c8a7abe809d..f20d319463f1 100644 > --- a/tools/perf/util/dso.h > +++ b/tools/perf/util/dso.h > @@ -14,6 +14,8 @@ > #include "namespaces.h" > #include "build-id.h" > > +struct perf_env; > + > enum dso_binary_type { > DSO_BINARY_TYPE__KALLSYMS = 0, > DSO_BINARY_TYPE__GUEST_KALLSYMS, > @@ -34,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, > }; > > @@ -177,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 48efad6d0f90..33ae59e89da2 100644 > --- a/tools/perf/util/symbol.c > +++ b/tools/perf/util/symbol.c > @@ -1441,6 +1441,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 >
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index b441c88cafa1..ab223239f1fb 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -701,7 +701,7 @@ else endif ifeq ($(feature-libbfd), 1) - EXTLIBS += -lbfd + EXTLIBS += -lbfd -lopcodes else # we are on a system that requires -liberty and (maybe) -lz # to link against -lbfd; test each case individually here @@ -796,6 +796,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 70de8f6b3aee..078017d31ca9 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -22,6 +22,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" @@ -29,6 +30,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" @@ -1672,6 +1676,147 @@ static int dso__disassemble_filename(struct dso *dso, char *filename, size_t fil return 0; } +static void get_exec_path(char *tpath, size_t size) +{ + const char *path = "/proc/self/exe"; + ssize_t len; + + len = readlink(path, tpath, size - 1); + assert(len > 0); + tpath[len] = 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; + __u64 arrays; + 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)); + get_exec_path(tpath, sizeof(tpath)); + + bfdf = bfd_openr(tpath, NULL); + assert(bfdf); + assert(bfd_check_format(bfdf, bfd_object)); + + s = open_memstream(&buf, &buf_size); + init_disassemble_info(&info, s, + (fprintf_ftype) fprintf); + + info.arch = bfd_get_arch(bfdf); + info.mach = bfd_get_mach(bfdf); + + arrays = 1UL << BPF_PROG_INFO_JITED_INSNS; + arrays |= 1UL << BPF_PROG_INFO_JITED_KSYMS; + arrays |= 1UL << BPF_PROG_INFO_LINE_INFO; + arrays |= 1UL << BPF_PROG_INFO_FUNC_INFO; + + info_node = perf_env__find_bpf_prog_info(dso->bpf_prog.env, + dso->bpf_prog.id); + if (!info_node) + return -1; + 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); + prog_linfo = prog_linfo; + + 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); + + linfo = bpf_prog_linfo__lfind_addr_func(prog_linfo, addr, sub_id, + nr_skip); + + if (linfo) { + 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); + annotation_line__add(&dl->al, ¬es->src->source); + } + + args->offset = pc; + args->line = buf + prev_buf_size; + args->line_nr = 0; + args->ms.sym = sym; + dl = disasm_line__new(args); + annotation_line__add(&dl->al, ¬es->src->source); + + pc += count; + } while (count > 0 && pc < len); + + bfd_close(bfdf); + return 0; +} + static int symbol__disassemble(struct symbol *sym, struct annotate_args *args) { struct annotation_options *opts = args->options; @@ -1699,7 +1844,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/bpf-event.c b/tools/perf/util/bpf-event.c index 52507435c464..6c363adc781a 100644 --- a/tools/perf/util/bpf-event.c +++ b/tools/perf/util/bpf-event.c @@ -25,12 +25,60 @@ static int snprintf_hex(char *buf, size_t size, unsigned char *data, size_t len) return ret; } +static int machine__process_bpf_event_load(struct machine *machine __maybe_unused, + union perf_event *event, + struct perf_sample *sample __maybe_unused) +{ + struct bpf_prog_info_linear *info_linear; + struct bpf_prog_info_node *info_node; + struct perf_env *env = machine->env; + int id = event->bpf_event.id; + unsigned int i; + + /* perf-record, no need to handle bpf-event */ + if (env == NULL) + return 0; + + info_node = perf_env__find_bpf_prog_info(env, id); + if (!info_node) + return 0; + info_linear = info_node->info_linear; + + for (i = 0; i < info_linear->info.nr_jited_ksyms; i++) { + u64 *addrs = (u64 *)(info_linear->info.jited_ksyms); + u64 addr = addrs[i]; + struct map *map; + + map = map_groups__find(&machine->kmaps, addr); + + if (map) { + map->dso->binary_type = DSO_BINARY_TYPE__BPF_PROG_INFO; + map->dso->bpf_prog.id = id; + map->dso->bpf_prog.sub_id = i; + map->dso->bpf_prog.env = env; + } + } + return 0; +} + int machine__process_bpf_event(struct machine *machine __maybe_unused, union perf_event *event, struct perf_sample *sample __maybe_unused) { if (dump_trace) perf_event__fprintf_bpf_event(event, stdout); + + switch (event->bpf_event.type) { + case PERF_BPF_EVENT_PROG_LOAD: + return machine__process_bpf_event_load(machine, event, sample); + + case PERF_BPF_EVENT_PROG_UNLOAD: + break; + default: + pr_debug("unexpected bpf_event type of %d\n", + event->bpf_event.type); + break; + } return 0; } diff --git a/tools/perf/util/bpf-event.h b/tools/perf/util/bpf-event.h index b9ec394dc7c7..ab4a975b7e05 100644 --- a/tools/perf/util/bpf-event.h +++ b/tools/perf/util/bpf-event.h @@ -2,6 +2,10 @@ #ifndef __PERF_BPF_EVENT_H #define __PERF_BPF_EVENT_H +#include <bpf/bpf.h> +#include <bpf/btf.h> +#include <bpf/libbpf.h> +#include <linux/btf.h> #include <linux/compiler.h> #include <linux/rbtree.h> #include "event.h" diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 62c8cf622607..1798192bf0f9 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -181,6 +181,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 8c8a7abe809d..f20d319463f1 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -14,6 +14,8 @@ #include "namespaces.h" #include "build-id.h" +struct perf_env; + enum dso_binary_type { DSO_BINARY_TYPE__KALLSYMS = 0, DSO_BINARY_TYPE__GUEST_KALLSYMS, @@ -34,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, }; @@ -177,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 48efad6d0f90..33ae59e89da2 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1441,6 +1441,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;
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/perf/Makefile.config | 6 +- tools/perf/util/annotate.c | 149 +++++++++++++++++++++++++++++++++++- tools/perf/util/bpf-event.c | 48 ++++++++++++ tools/perf/util/bpf-event.h | 4 + tools/perf/util/dso.c | 1 + tools/perf/util/dso.h | 33 +++++--- tools/perf/util/symbol.c | 1 + 7 files changed, 229 insertions(+), 13 deletions(-)