aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2016-11-17 10:31:51 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-11-17 15:31:59 -0500
commit763d8960a17126e73e7d9cd6b66e390196f48894 (patch)
tree5f05bd89b967cd7d1f29f80cd0a410cc205a8cdd /tools/perf/util/annotate.c
parent9c2fb451bda0aa60127e63e44993401818326e91 (diff)
perf annotate: Add per arch instructions annotate handlers
Another step in supporting cross annotation. The arch specific tables are put in: tools/perf/arch/$ARCH/annotation/instructions.c which, so far, just plug instructions to a bunch of parsers/formatters, but may have more as the need arises. This is an alternative implementation to a previous attempt made by Ravi Bangoria. Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Chris Riyder <chris.ryder@arm.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Kim Phillips <kim.phillips@arm.com> Cc: Markus Trippelsdorf <markus@trippelsdorf.de> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Cc: Pawel Moll <pawel.moll@arm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> Cc: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Taeung Song <treeze.taeung@gmail.com> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/n/tip-g3wt282lfa51j4qd0813e3az@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/annotate.c')
-rw-r--r--tools/perf/util/annotate.c136
1 files changed, 30 insertions, 106 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 72769762ece9..095d90a9077f 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -28,20 +28,36 @@ const char *disassembler_style;
28const char *objdump_path; 28const char *objdump_path;
29static regex_t file_lineno; 29static regex_t file_lineno;
30 30
31static struct ins *ins__find(const char *name); 31static struct ins *ins__find(struct arch *arch, const char *name);
32static int disasm_line__parse(char *line, char **namep, char **rawp); 32static int disasm_line__parse(char *line, char **namep, char **rawp);
33 33
34struct arch { 34struct arch {
35 const char *name; 35 const char *name;
36 struct ins *instructions;
37 size_t nr_instructions;
38 bool sorted_instructions;
36 struct { 39 struct {
37 char comment_char; 40 char comment_char;
38 char skip_functions_char; 41 char skip_functions_char;
39 } objdump; 42 } objdump;
40}; 43};
41 44
45static struct ins_ops call_ops;
46static struct ins_ops dec_ops;
47static struct ins_ops jump_ops;
48static struct ins_ops mov_ops;
49static struct ins_ops nop_ops;
50static struct ins_ops lock_ops;
51static struct ins_ops ret_ops;
52
53#include "arch/arm/annotate/instructions.c"
54#include "arch/x86/annotate/instructions.c"
55
42static struct arch architectures[] = { 56static struct arch architectures[] = {
43 { 57 {
44 .name = "arm", 58 .name = "arm",
59 .instructions = arm__instructions,
60 .nr_instructions = ARRAY_SIZE(arm__instructions),
45 .objdump = { 61 .objdump = {
46 .comment_char = ';', 62 .comment_char = ';',
47 .skip_functions_char = '+', 63 .skip_functions_char = '+',
@@ -49,6 +65,8 @@ static struct arch architectures[] = {
49 }, 65 },
50 { 66 {
51 .name = "x86", 67 .name = "x86",
68 .instructions = x86__instructions,
69 .nr_instructions = ARRAY_SIZE(x86__instructions),
52 .objdump = { 70 .objdump = {
53 .comment_char = '#', 71 .comment_char = '#',
54 }, 72 },
@@ -209,7 +227,7 @@ static int lock__parse(struct arch *arch, struct ins_operands *ops, struct map *
209 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0) 227 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
210 goto out_free_ops; 228 goto out_free_ops;
211 229
212 ops->locked.ins = ins__find(name); 230 ops->locked.ins = ins__find(arch, name);
213 free(name); 231 free(name);
214 232
215 if (ops->locked.ins == NULL) 233 if (ops->locked.ins == NULL)
@@ -385,99 +403,6 @@ bool ins__is_ret(const struct ins *ins)
385 return ins->ops == &ret_ops; 403 return ins->ops == &ret_ops;
386} 404}
387 405
388static struct ins instructions[] = {
389 { .name = "add", .ops = &mov_ops, },
390 { .name = "addl", .ops = &mov_ops, },
391 { .name = "addq", .ops = &mov_ops, },
392 { .name = "addw", .ops = &mov_ops, },
393 { .name = "and", .ops = &mov_ops, },
394#ifdef __arm__
395 { .name = "b", .ops = &jump_ops, }, // might also be a call
396 { .name = "bcc", .ops = &jump_ops, },
397 { .name = "bcs", .ops = &jump_ops, },
398 { .name = "beq", .ops = &jump_ops, },
399 { .name = "bge", .ops = &jump_ops, },
400 { .name = "bgt", .ops = &jump_ops, },
401 { .name = "bhi", .ops = &jump_ops, },
402 { .name = "bl", .ops = &call_ops, },
403 { .name = "bls", .ops = &jump_ops, },
404 { .name = "blt", .ops = &jump_ops, },
405 { .name = "blx", .ops = &call_ops, },
406 { .name = "bne", .ops = &jump_ops, },
407#endif
408 { .name = "bts", .ops = &mov_ops, },
409 { .name = "call", .ops = &call_ops, },
410 { .name = "callq", .ops = &call_ops, },
411 { .name = "cmp", .ops = &mov_ops, },
412 { .name = "cmpb", .ops = &mov_ops, },
413 { .name = "cmpl", .ops = &mov_ops, },
414 { .name = "cmpq", .ops = &mov_ops, },
415 { .name = "cmpw", .ops = &mov_ops, },
416 { .name = "cmpxch", .ops = &mov_ops, },
417 { .name = "dec", .ops = &dec_ops, },
418 { .name = "decl", .ops = &dec_ops, },
419 { .name = "imul", .ops = &mov_ops, },
420 { .name = "inc", .ops = &dec_ops, },
421 { .name = "incl", .ops = &dec_ops, },
422 { .name = "ja", .ops = &jump_ops, },
423 { .name = "jae", .ops = &jump_ops, },
424 { .name = "jb", .ops = &jump_ops, },
425 { .name = "jbe", .ops = &jump_ops, },
426 { .name = "jc", .ops = &jump_ops, },
427 { .name = "jcxz", .ops = &jump_ops, },
428 { .name = "je", .ops = &jump_ops, },
429 { .name = "jecxz", .ops = &jump_ops, },
430 { .name = "jg", .ops = &jump_ops, },
431 { .name = "jge", .ops = &jump_ops, },
432 { .name = "jl", .ops = &jump_ops, },
433 { .name = "jle", .ops = &jump_ops, },
434 { .name = "jmp", .ops = &jump_ops, },
435 { .name = "jmpq", .ops = &jump_ops, },
436 { .name = "jna", .ops = &jump_ops, },
437 { .name = "jnae", .ops = &jump_ops, },
438 { .name = "jnb", .ops = &jump_ops, },
439 { .name = "jnbe", .ops = &jump_ops, },
440 { .name = "jnc", .ops = &jump_ops, },
441 { .name = "jne", .ops = &jump_ops, },
442 { .name = "jng", .ops = &jump_ops, },
443 { .name = "jnge", .ops = &jump_ops, },
444 { .name = "jnl", .ops = &jump_ops, },
445 { .name = "jnle", .ops = &jump_ops, },
446 { .name = "jno", .ops = &jump_ops, },
447 { .name = "jnp", .ops = &jump_ops, },
448 { .name = "jns", .ops = &jump_ops, },
449 { .name = "jnz", .ops = &jump_ops, },
450 { .name = "jo", .ops = &jump_ops, },
451 { .name = "jp", .ops = &jump_ops, },
452 { .name = "jpe", .ops = &jump_ops, },
453 { .name = "jpo", .ops = &jump_ops, },
454 { .name = "jrcxz", .ops = &jump_ops, },
455 { .name = "js", .ops = &jump_ops, },
456 { .name = "jz", .ops = &jump_ops, },
457 { .name = "lea", .ops = &mov_ops, },
458 { .name = "lock", .ops = &lock_ops, },
459 { .name = "mov", .ops = &mov_ops, },
460 { .name = "movb", .ops = &mov_ops, },
461 { .name = "movdqa",.ops = &mov_ops, },
462 { .name = "movl", .ops = &mov_ops, },
463 { .name = "movq", .ops = &mov_ops, },
464 { .name = "movslq", .ops = &mov_ops, },
465 { .name = "movzbl", .ops = &mov_ops, },
466 { .name = "movzwl", .ops = &mov_ops, },
467 { .name = "nop", .ops = &nop_ops, },
468 { .name = "nopl", .ops = &nop_ops, },
469 { .name = "nopw", .ops = &nop_ops, },
470 { .name = "or", .ops = &mov_ops, },
471 { .name = "orl", .ops = &mov_ops, },
472 { .name = "test", .ops = &mov_ops, },
473 { .name = "testb", .ops = &mov_ops, },
474 { .name = "testl", .ops = &mov_ops, },
475 { .name = "xadd", .ops = &mov_ops, },
476 { .name = "xbeginl", .ops = &jump_ops, },
477 { .name = "xbeginq", .ops = &jump_ops, },
478 { .name = "retq", .ops = &ret_ops, },
479};
480
481static int ins__key_cmp(const void *name, const void *insp) 406static int ins__key_cmp(const void *name, const void *insp)
482{ 407{
483 const struct ins *ins = insp; 408 const struct ins *ins = insp;
@@ -493,24 +418,23 @@ static int ins__cmp(const void *a, const void *b)
493 return strcmp(ia->name, ib->name); 418 return strcmp(ia->name, ib->name);
494} 419}
495 420
496static void ins__sort(void) 421static void ins__sort(struct arch *arch)
497{ 422{
498 const int nmemb = ARRAY_SIZE(instructions); 423 const int nmemb = arch->nr_instructions;
499 424
500 qsort(instructions, nmemb, sizeof(struct ins), ins__cmp); 425 qsort(arch->instructions, nmemb, sizeof(struct ins), ins__cmp);
501} 426}
502 427
503static struct ins *ins__find(const char *name) 428static struct ins *ins__find(struct arch *arch, const char *name)
504{ 429{
505 const int nmemb = ARRAY_SIZE(instructions); 430 const int nmemb = arch->nr_instructions;
506 static bool sorted;
507 431
508 if (!sorted) { 432 if (!arch->sorted_instructions) {
509 ins__sort(); 433 ins__sort(arch);
510 sorted = true; 434 arch->sorted_instructions = true;
511 } 435 }
512 436
513 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp); 437 return bsearch(name, arch->instructions, nmemb, sizeof(struct ins), ins__key_cmp);
514} 438}
515 439
516static int arch__key_cmp(const void *name, const void *archp) 440static int arch__key_cmp(const void *name, const void *archp)
@@ -767,7 +691,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
767 691
768static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map) 692static void disasm_line__init_ins(struct disasm_line *dl, struct arch *arch, struct map *map)
769{ 693{
770 dl->ins = ins__find(dl->name); 694 dl->ins = ins__find(arch, dl->name);
771 695
772 if (dl->ins == NULL) 696 if (dl->ins == NULL)
773 return; 697 return;