Em Wed, Sep 21, 2016 at 09:17:51PM +0530, Ravi Bangoria escreveu: > Change current data structures and function to enable cross arch > annotate. > > Current perf implementation does not support cross arch annotate. > To make it truly cross arch, instruction table of all arch should > be present in perf binary. And use appropriate table based on arch > where perf.data was recorded. > > Record on arm: > $ ./perf record -a > > Report -> Annotate on x86: > $ ./perf report -i perf.data.arm --vmlinux vmlinux.arm > > Signed-off-by: Ravi Bangoria <ravi.bango...@linux.vnet.ibm.com> > --- > Changes in v7: > - Make norm_arch as global var instead of passing them to each parser. > - Address other review comments. > > tools/perf/builtin-top.c | 2 +- > tools/perf/ui/browsers/annotate.c | 3 +- > tools/perf/ui/gtk/annotate.c | 2 +- > tools/perf/util/annotate.c | 151 > ++++++++++++++++++++++++++++++++------ > tools/perf/util/annotate.h | 3 +- > 5 files changed, 134 insertions(+), 27 deletions(-) > > diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c > index 4007857..41ecdd6 100644 > --- a/tools/perf/builtin-top.c > +++ b/tools/perf/builtin-top.c > @@ -129,7 +129,7 @@ static int perf_top__parse_source(struct perf_top *top, > struct hist_entry *he) > return err; > } > > - err = symbol__disassemble(sym, map, 0); > + err = symbol__disassemble(sym, map, 0, NULL); > if (err == 0) { > out_assign: > top->sym_filter_entry = he; > diff --git a/tools/perf/ui/browsers/annotate.c > b/tools/perf/ui/browsers/annotate.c > index 4c18271..214a14a 100644 > --- a/tools/perf/ui/browsers/annotate.c > +++ b/tools/perf/ui/browsers/annotate.c > @@ -1050,7 +1050,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map > *map, > (nr_pcnt - 1); > } > > - err = symbol__disassemble(sym, map, sizeof_bdl); > + err = symbol__disassemble(sym, map, sizeof_bdl, > + perf_evsel__env_arch(evsel)); > if (err) { > char msg[BUFSIZ]; > symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); > diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c > index 42d3199..c127aba 100644 > --- a/tools/perf/ui/gtk/annotate.c > +++ b/tools/perf/ui/gtk/annotate.c > @@ -167,7 +167,7 @@ static int symbol__gtk_annotate(struct symbol *sym, > struct map *map, > if (map->dso->annotate_warned) > return -1; > > - err = symbol__disassemble(sym, map, 0); > + err = symbol__disassemble(sym, map, 0, perf_evsel__env_arch(evsel)); > if (err) { > char msg[BUFSIZ]; > symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); > diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c > index aeb5a44..816aa2c 100644 > --- a/tools/perf/util/annotate.c > +++ b/tools/perf/util/annotate.c > @@ -21,10 +21,13 @@ > #include <regex.h> > #include <pthread.h> > #include <linux/bitops.h> > +#include <sys/utsname.h> > +#include "../arch/common.h" > > const char *disassembler_style; > const char *objdump_path; > static regex_t file_lineno; > +static char *norm_arch; > > static struct ins *ins__find(const char *name); > static int disasm_line__parse(char *line, char **namep, char **rawp); > @@ -66,10 +69,8 @@ static int call__parse(struct ins_operands *ops, struct > map *map) > > name++; > > -#ifdef __arm__ > - if (strchr(name, '+')) > + if (!strcmp(norm_arch, "arm") && strchr(name, '+')) > return -1; > -#endif > > tok = strchr(name, '>'); > if (tok == NULL) > @@ -252,16 +253,12 @@ static int mov__parse(struct ins_operands *ops, struct > map *map __maybe_unused) > return -1; > > target = ++s; > -#ifdef __arm__ > + > comment = strchr(s, ';'); > -#else > - comment = strchr(s, '#'); > -#endif > + if (comment == NULL) > + comment = strchr(s, '#'); > > - if (comment != NULL) > - s = comment - 1; > - else > - s = strchr(s, '\0') - 1; > + s = (comment != NULL) ? comment - 1 : strchr(s, '\0') - 1;
Why have you touched the above 4 lines? The code you provided is equivalent, i.e. has no value for this patch you're working on, just a distraction for reviewers, please don't do that. I'll remove it and continue processing the patchkit. > > while (s > target && isspace(s[0])) > --s; > @@ -364,14 +361,92 @@ bool ins__is_ret(const struct ins *ins) > return ins->ops == &ret_ops; > } > > -static struct ins instructions[] = { > +static struct ins instructions_x86[] = { > { .name = "add", .ops = &mov_ops, }, > { .name = "addl", .ops = &mov_ops, }, > { .name = "addq", .ops = &mov_ops, }, > { .name = "addw", .ops = &mov_ops, }, > { .name = "and", .ops = &mov_ops, }, > -#ifdef __arm__ > - { .name = "b", .ops = &jump_ops, }, // might also be a call > + { .name = "bts", .ops = &mov_ops, }, > + { .name = "call", .ops = &call_ops, }, > + { .name = "callq", .ops = &call_ops, }, > + { .name = "cmp", .ops = &mov_ops, }, > + { .name = "cmpb", .ops = &mov_ops, }, > + { .name = "cmpl", .ops = &mov_ops, }, > + { .name = "cmpq", .ops = &mov_ops, }, > + { .name = "cmpw", .ops = &mov_ops, }, > + { .name = "cmpxch", .ops = &mov_ops, }, > + { .name = "dec", .ops = &dec_ops, }, > + { .name = "decl", .ops = &dec_ops, }, > + { .name = "imul", .ops = &mov_ops, }, > + { .name = "inc", .ops = &dec_ops, }, > + { .name = "incl", .ops = &dec_ops, }, > + { .name = "ja", .ops = &jump_ops, }, > + { .name = "jae", .ops = &jump_ops, }, > + { .name = "jb", .ops = &jump_ops, }, > + { .name = "jbe", .ops = &jump_ops, }, > + { .name = "jc", .ops = &jump_ops, }, > + { .name = "jcxz", .ops = &jump_ops, }, > + { .name = "je", .ops = &jump_ops, }, > + { .name = "jecxz", .ops = &jump_ops, }, > + { .name = "jg", .ops = &jump_ops, }, > + { .name = "jge", .ops = &jump_ops, }, > + { .name = "jl", .ops = &jump_ops, }, > + { .name = "jle", .ops = &jump_ops, }, > + { .name = "jmp", .ops = &jump_ops, }, > + { .name = "jmpq", .ops = &jump_ops, }, > + { .name = "jna", .ops = &jump_ops, }, > + { .name = "jnae", .ops = &jump_ops, }, > + { .name = "jnb", .ops = &jump_ops, }, > + { .name = "jnbe", .ops = &jump_ops, }, > + { .name = "jnc", .ops = &jump_ops, }, > + { .name = "jne", .ops = &jump_ops, }, > + { .name = "jng", .ops = &jump_ops, }, > + { .name = "jnge", .ops = &jump_ops, }, > + { .name = "jnl", .ops = &jump_ops, }, > + { .name = "jnle", .ops = &jump_ops, }, > + { .name = "jno", .ops = &jump_ops, }, > + { .name = "jnp", .ops = &jump_ops, }, > + { .name = "jns", .ops = &jump_ops, }, > + { .name = "jnz", .ops = &jump_ops, }, > + { .name = "jo", .ops = &jump_ops, }, > + { .name = "jp", .ops = &jump_ops, }, > + { .name = "jpe", .ops = &jump_ops, }, > + { .name = "jpo", .ops = &jump_ops, }, > + { .name = "jrcxz", .ops = &jump_ops, }, > + { .name = "js", .ops = &jump_ops, }, > + { .name = "jz", .ops = &jump_ops, }, > + { .name = "lea", .ops = &mov_ops, }, > + { .name = "lock", .ops = &lock_ops, }, > + { .name = "mov", .ops = &mov_ops, }, > + { .name = "movb", .ops = &mov_ops, }, > + { .name = "movdqa", .ops = &mov_ops, }, > + { .name = "movl", .ops = &mov_ops, }, > + { .name = "movq", .ops = &mov_ops, }, > + { .name = "movslq", .ops = &mov_ops, }, > + { .name = "movzbl", .ops = &mov_ops, }, > + { .name = "movzwl", .ops = &mov_ops, }, > + { .name = "nop", .ops = &nop_ops, }, > + { .name = "nopl", .ops = &nop_ops, }, > + { .name = "nopw", .ops = &nop_ops, }, > + { .name = "or", .ops = &mov_ops, }, > + { .name = "orl", .ops = &mov_ops, }, > + { .name = "test", .ops = &mov_ops, }, > + { .name = "testb", .ops = &mov_ops, }, > + { .name = "testl", .ops = &mov_ops, }, > + { .name = "xadd", .ops = &mov_ops, }, > + { .name = "xbeginl", .ops = &jump_ops, }, > + { .name = "xbeginq", .ops = &jump_ops, }, > + { .name = "retq", .ops = &ret_ops, }, > +}; > + > +static struct ins instructions_arm[] = { > + { .name = "add", .ops = &mov_ops, }, > + { .name = "addl", .ops = &mov_ops, }, > + { .name = "addq", .ops = &mov_ops, }, > + { .name = "addw", .ops = &mov_ops, }, > + { .name = "and", .ops = &mov_ops, }, > + { .name = "b", .ops = &jump_ops, }, /* might also be a call */ > { .name = "bcc", .ops = &jump_ops, }, > { .name = "bcs", .ops = &jump_ops, }, > { .name = "beq", .ops = &jump_ops, }, > @@ -383,7 +458,6 @@ static struct ins instructions[] = { > { .name = "blt", .ops = &jump_ops, }, > { .name = "blx", .ops = &call_ops, }, > { .name = "bne", .ops = &jump_ops, }, > -#endif > { .name = "bts", .ops = &mov_ops, }, > { .name = "call", .ops = &call_ops, }, > { .name = "callq", .ops = &call_ops, }, > @@ -472,24 +546,48 @@ static int ins__cmp(const void *a, const void *b) > return strcmp(ia->name, ib->name); > } > > -static void ins__sort(void) > +static void ins__sort(struct ins *instructions, int nmemb) > { > - const int nmemb = ARRAY_SIZE(instructions); > - > qsort(instructions, nmemb, sizeof(struct ins), ins__cmp); > } > > +static const char *annotate__norm_arch(char *arch) > +{ > + struct utsname uts; > + > + if (!arch) { /* Assume we are annotating locally. */ > + if (uname(&uts) < 0) > + return NULL; > + arch = uts.machine; > + } > + return normalize_arch(arch); > +} > + > static struct ins *ins__find(const char *name) > { > - const int nmemb = ARRAY_SIZE(instructions); > static bool sorted; > + struct ins *instructions; > + int nmemb; > > if (!sorted) { > - ins__sort(); > + ins__sort(instructions_x86, ARRAY_SIZE(instructions_x86)); > + ins__sort(instructions_arm, ARRAY_SIZE(instructions_arm)); > sorted = true; > } > > - return bsearch(name, instructions, nmemb, sizeof(struct ins), > ins__key_cmp); > + if (!strcmp(norm_arch, "x86")) { > + instructions = instructions_x86; > + nmemb = ARRAY_SIZE(instructions_x86); > + } else if (!strcmp(norm_arch, "arm")) { > + instructions = instructions_arm; > + nmemb = ARRAY_SIZE(instructions_arm); > + } else { > + pr_err("perf annotate not supported by %s arch\n", norm_arch); > + return NULL; > + } > + > + return bsearch(name, instructions, nmemb, sizeof(struct ins), > + ins__key_cmp); > } > > int symbol__alloc_hist(struct symbol *sym) > @@ -1280,7 +1378,8 @@ fallback: > return 0; > } > > -int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize) > +int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize, > + char *arch) > { > struct dso *dso = map->dso; > char command[PATH_MAX * 2]; > @@ -1297,6 +1396,12 @@ int symbol__disassemble(struct symbol *sym, struct map > *map, size_t privsize) > if (err) > return err; > > + norm_arch = (char *) annotate__norm_arch(arch); > + if (!norm_arch) { > + pr_err("Can not annotate. Could not determine architecture."); > + return -1; > + } > + > pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 > "\n", __func__, > symfs_filename, sym->name, map->unmap_ip(map, sym->start), > map->unmap_ip(map, sym->end)); > @@ -1793,7 +1898,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map > *map, > struct rb_root source_line = RB_ROOT; > u64 len; > > - if (symbol__disassemble(sym, map, 0) < 0) > + if (symbol__disassemble(sym, map, 0, perf_evsel__env_arch(evsel)) < 0) > return -1; > > len = symbol__size(sym); > diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h > index 5bbcec1..4400269 100644 > --- a/tools/perf/util/annotate.h > +++ b/tools/perf/util/annotate.h > @@ -156,7 +156,8 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, > int evidx, u64 addr); > int symbol__alloc_hist(struct symbol *sym); > void symbol__annotate_zero_histograms(struct symbol *sym); > > -int symbol__disassemble(struct symbol *sym, struct map *map, size_t > privsize); > +int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize, > + char *arch); > > enum symbol_disassemble_errno { > SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0, > -- > 2.5.5