diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-04-18 12:58:34 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-04-18 12:58:34 -0400 |
commit | 4f9d03251b9d202ebce805757360ef0fac5eb74e (patch) | |
tree | 828b5d690bcd1bb1b04a98d7c735a54545cc589e /tools | |
parent | 657bcaf5097e1aff53d724358deb24ce803f43a4 (diff) |
perf annotate: Disassembler instruction parsing
So that at disassembly time we parse targets, etc.
Supporting jump instructions initially, call functions are next.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-7vzlh66n5or46n27ji658cnl@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/ui/browsers/annotate.c | 19 | ||||
-rw-r--r-- | tools/perf/util/annotate.c | 63 | ||||
-rw-r--r-- | tools/perf/util/annotate.h | 13 |
3 files changed, 79 insertions, 16 deletions
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 0bc3e652b541..bdbb54fd05ae 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c | |||
@@ -315,26 +315,13 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows | |||
315 | 315 | ||
316 | static bool annotate_browser__jump(struct annotate_browser *browser) | 316 | static bool annotate_browser__jump(struct annotate_browser *browser) |
317 | { | 317 | { |
318 | const char *jumps[] = { "je", "jne", "ja", "jmpq", "js", "jmp", NULL }; | ||
319 | struct disasm_line *dl = browser->selection; | 318 | struct disasm_line *dl = browser->selection; |
320 | s64 idx, offset; | 319 | s64 idx; |
321 | char *s; | ||
322 | int i = 0; | ||
323 | |||
324 | while (jumps[i] && strcmp(dl->name, jumps[i])) | ||
325 | ++i; | ||
326 | 320 | ||
327 | if (jumps[i] == NULL) | 321 | if (!dl->ins || !ins__is_jump(dl->ins)) |
328 | return false; | 322 | return false; |
329 | 323 | ||
330 | s = strchr(dl->operands, '+'); | 324 | dl = annotate_browser__find_offset(browser, dl->target, &idx); |
331 | if (s++ == NULL) { | ||
332 | ui_helpline__puts("Invallid jump instruction."); | ||
333 | return true; | ||
334 | } | ||
335 | |||
336 | offset = strtoll(s, NULL, 16); | ||
337 | dl = annotate_browser__find_offset(browser, offset, &idx); | ||
338 | if (dl == NULL) { | 325 | if (dl == NULL) { |
339 | ui_helpline__puts("Invallid jump offset"); | 326 | ui_helpline__puts("Invallid jump offset"); |
340 | return true; | 327 | return true; |
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index a72585ab52e8..4ee2c07924bc 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c | |||
@@ -18,6 +18,53 @@ | |||
18 | 18 | ||
19 | const char *disassembler_style; | 19 | const char *disassembler_style; |
20 | 20 | ||
21 | static int jump_ops__parse_target(const char *operands, u64 *target) | ||
22 | { | ||
23 | const char *s = strchr(operands, '+'); | ||
24 | |||
25 | if (s++ == NULL) | ||
26 | return -1; | ||
27 | |||
28 | *target = strtoll(s, NULL, 16); | ||
29 | return 0; | ||
30 | } | ||
31 | |||
32 | static struct ins_ops jump_ops = { | ||
33 | .parse_target = jump_ops__parse_target, | ||
34 | }; | ||
35 | |||
36 | bool ins__is_jump(const struct ins *ins) | ||
37 | { | ||
38 | return ins->ops == &jump_ops; | ||
39 | } | ||
40 | |||
41 | |||
42 | /* | ||
43 | * Must be sorted by name! | ||
44 | */ | ||
45 | static struct ins instructions[] = { | ||
46 | { .name = "ja", .ops = &jump_ops, }, | ||
47 | { .name = "je", .ops = &jump_ops, }, | ||
48 | { .name = "jmp", .ops = &jump_ops, }, | ||
49 | { .name = "jmpq", .ops = &jump_ops, }, | ||
50 | { .name = "jne", .ops = &jump_ops, }, | ||
51 | { .name = "js", .ops = &jump_ops, }, | ||
52 | }; | ||
53 | |||
54 | static int ins__cmp(const void *name, const void *insp) | ||
55 | { | ||
56 | const struct ins *ins = insp; | ||
57 | |||
58 | return strcmp(name, ins->name); | ||
59 | } | ||
60 | |||
61 | static struct ins *ins__find(const char *name) | ||
62 | { | ||
63 | const int nmemb = ARRAY_SIZE(instructions); | ||
64 | |||
65 | return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); | ||
66 | } | ||
67 | |||
21 | int symbol__annotate_init(struct map *map __used, struct symbol *sym) | 68 | int symbol__annotate_init(struct map *map __used, struct symbol *sym) |
22 | { | 69 | { |
23 | struct annotation *notes = symbol__annotation(sym); | 70 | struct annotation *notes = symbol__annotation(sym); |
@@ -78,6 +125,20 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map, | |||
78 | return 0; | 125 | return 0; |
79 | } | 126 | } |
80 | 127 | ||
128 | static void disasm_line__init_ins(struct disasm_line *dl) | ||
129 | { | ||
130 | dl->ins = ins__find(dl->name); | ||
131 | |||
132 | if (dl->ins == NULL) | ||
133 | return; | ||
134 | |||
135 | if (!dl->ins->ops) | ||
136 | return; | ||
137 | |||
138 | if (dl->ins->ops->parse_target) | ||
139 | dl->ins->ops->parse_target(dl->operands, &dl->target); | ||
140 | } | ||
141 | |||
81 | static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) | 142 | static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) |
82 | { | 143 | { |
83 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); | 144 | struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); |
@@ -117,6 +178,8 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs | |||
117 | while (isspace(dl->operands[0])) | 178 | while (isspace(dl->operands[0])) |
118 | ++dl->operands; | 179 | ++dl->operands; |
119 | } | 180 | } |
181 | |||
182 | disasm_line__init_ins(dl); | ||
120 | } | 183 | } |
121 | } | 184 | } |
122 | 185 | ||
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index dd7636d24133..934c6fe3a91b 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h | |||
@@ -7,11 +7,24 @@ | |||
7 | #include <linux/list.h> | 7 | #include <linux/list.h> |
8 | #include <linux/rbtree.h> | 8 | #include <linux/rbtree.h> |
9 | 9 | ||
10 | struct ins_ops { | ||
11 | int (*parse_target)(const char *operands, u64 *target); | ||
12 | }; | ||
13 | |||
14 | struct ins { | ||
15 | const char *name; | ||
16 | struct ins_ops *ops; | ||
17 | }; | ||
18 | |||
19 | bool ins__is_jump(const struct ins *ins); | ||
20 | |||
10 | struct disasm_line { | 21 | struct disasm_line { |
11 | struct list_head node; | 22 | struct list_head node; |
12 | s64 offset; | 23 | s64 offset; |
24 | u64 target; | ||
13 | char *line; | 25 | char *line; |
14 | char *name; | 26 | char *name; |
27 | struct ins *ins; | ||
15 | char *operands; | 28 | char *operands; |
16 | }; | 29 | }; |
17 | 30 | ||