aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-05-12 12:15:34 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-05-12 12:15:34 -0400
commit7a997fe4019f556a81530d3a737d817a2b0d622f (patch)
treec924fdfc826a52755f1c2662a831dc82d3f94330 /tools/perf/util
parenta43712c4720c8df4bad7d3760c67086168553b05 (diff)
perf annotate: Augment lock instruction output
It just chops off the 'lock' and uses the ins__find, etc machinery to call instruction specific parsers/beautifiers. 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-4913ba2dzakz5rivgumosqbh@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/annotate.c127
-rw-r--r--tools/perf/util/annotate.h16
2 files changed, 109 insertions, 34 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index a6109dc3a81e..1dce09874d93 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -18,6 +18,9 @@
18 18
19const char *disassembler_style; 19const char *disassembler_style;
20 20
21static struct ins *ins__find(const char *name);
22static int disasm_line__parse(char *line, char **namep, char **rawp);
23
21static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size, 24static int ins__raw_scnprintf(struct ins *ins, char *bf, size_t size,
22 struct ins_operands *ops) 25 struct ins_operands *ops)
23{ 26{
@@ -147,6 +150,53 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
147 return 0; 150 return 0;
148} 151}
149 152
153static int lock__parse(struct ins_operands *ops)
154{
155 char *name;
156
157 ops->locked.ops = zalloc(sizeof(*ops->locked.ops));
158 if (ops->locked.ops == NULL)
159 return 0;
160
161 if (disasm_line__parse(ops->raw, &name, &ops->locked.ops->raw) < 0)
162 goto out_free_ops;
163
164 ops->locked.ins = ins__find(name);
165 if (ops->locked.ins == NULL)
166 goto out_free_ops;
167
168 if (!ops->locked.ins->ops)
169 return 0;
170
171 if (ops->locked.ins->ops->parse)
172 ops->locked.ins->ops->parse(ops->locked.ops);
173
174 return 0;
175
176out_free_ops:
177 free(ops->locked.ops);
178 ops->locked.ops = NULL;
179 return 0;
180}
181
182static int lock__scnprintf(struct ins *ins, char *bf, size_t size,
183 struct ins_operands *ops)
184{
185 int printed;
186
187 if (ops->locked.ins == NULL)
188 return ins__raw_scnprintf(ins, bf, size, ops);
189
190 printed = scnprintf(bf, size, "%-6.6s ", ins->name);
191 return printed + ins__scnprintf(ops->locked.ins, bf + printed,
192 size - printed, ops->locked.ops);
193}
194
195static struct ins_ops lock_ops = {
196 .parse = lock__parse,
197 .scnprintf = lock__scnprintf,
198};
199
150static int mov__parse(struct ins_operands *ops) 200static int mov__parse(struct ins_operands *ops)
151{ 201{
152 char *s = strchr(ops->raw, ','), *target, *comment, prev; 202 char *s = strchr(ops->raw, ','), *target, *comment, prev;
@@ -265,6 +315,7 @@ static struct ins instructions[] = {
265 { .name = "addq", .ops = &mov_ops, }, 315 { .name = "addq", .ops = &mov_ops, },
266 { .name = "addw", .ops = &mov_ops, }, 316 { .name = "addw", .ops = &mov_ops, },
267 { .name = "and", .ops = &mov_ops, }, 317 { .name = "and", .ops = &mov_ops, },
318 { .name = "bts", .ops = &mov_ops, },
268 { .name = "call", .ops = &call_ops, }, 319 { .name = "call", .ops = &call_ops, },
269 { .name = "callq", .ops = &call_ops, }, 320 { .name = "callq", .ops = &call_ops, },
270 { .name = "cmp", .ops = &mov_ops, }, 321 { .name = "cmp", .ops = &mov_ops, },
@@ -314,6 +365,7 @@ static struct ins instructions[] = {
314 { .name = "js", .ops = &jump_ops, }, 365 { .name = "js", .ops = &jump_ops, },
315 { .name = "jz", .ops = &jump_ops, }, 366 { .name = "jz", .ops = &jump_ops, },
316 { .name = "lea", .ops = &mov_ops, }, 367 { .name = "lea", .ops = &mov_ops, },
368 { .name = "lock", .ops = &lock_ops, },
317 { .name = "mov", .ops = &mov_ops, }, 369 { .name = "mov", .ops = &mov_ops, },
318 { .name = "movb", .ops = &mov_ops, }, 370 { .name = "movb", .ops = &mov_ops, },
319 { .name = "movdqa",.ops = &mov_ops, }, 371 { .name = "movdqa",.ops = &mov_ops, },
@@ -330,6 +382,7 @@ static struct ins instructions[] = {
330 { .name = "test", .ops = &mov_ops, }, 382 { .name = "test", .ops = &mov_ops, },
331 { .name = "testb", .ops = &mov_ops, }, 383 { .name = "testb", .ops = &mov_ops, },
332 { .name = "testl", .ops = &mov_ops, }, 384 { .name = "testl", .ops = &mov_ops, },
385 { .name = "xadd", .ops = &mov_ops, },
333}; 386};
334 387
335static int ins__cmp(const void *name, const void *insp) 388static int ins__cmp(const void *name, const void *insp)
@@ -420,6 +473,44 @@ static void disasm_line__init_ins(struct disasm_line *dl)
420 dl->ins->ops->parse(&dl->ops); 473 dl->ins->ops->parse(&dl->ops);
421} 474}
422 475
476static int disasm_line__parse(char *line, char **namep, char **rawp)
477{
478 char *name = line, tmp;
479
480 while (isspace(name[0]))
481 ++name;
482
483 if (name[0] == '\0')
484 return -1;
485
486 *rawp = name + 1;
487
488 while ((*rawp)[0] != '\0' && !isspace((*rawp)[0]))
489 ++*rawp;
490
491 tmp = (*rawp)[0];
492 (*rawp)[0] = '\0';
493 *namep = strdup(name);
494
495 if (*namep == NULL)
496 goto out_free_name;
497
498 (*rawp)[0] = tmp;
499
500 if ((*rawp)[0] != '\0') {
501 (*rawp)++;
502 while (isspace((*rawp)[0]))
503 ++(*rawp);
504 }
505
506 return 0;
507
508out_free_name:
509 free(*namep);
510 *namep = NULL;
511 return -1;
512}
513
423static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize) 514static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize)
424{ 515{
425 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 516 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
@@ -431,35 +522,9 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs
431 goto out_delete; 522 goto out_delete;
432 523
433 if (offset != -1) { 524 if (offset != -1) {
434 char *name = dl->line, tmp; 525 if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
435
436 while (isspace(name[0]))
437 ++name;
438
439 if (name[0] == '\0')
440 goto out_delete;
441
442 dl->ops.raw = name + 1;
443
444 while (dl->ops.raw[0] != '\0' &&
445 !isspace(dl->ops.raw[0]))
446 ++dl->ops.raw;
447
448 tmp = dl->ops.raw[0];
449 dl->ops.raw[0] = '\0';
450 dl->name = strdup(name);
451
452 if (dl->name == NULL)
453 goto out_free_line; 526 goto out_free_line;
454 527
455 dl->ops.raw[0] = tmp;
456
457 if (dl->ops.raw[0] != '\0') {
458 dl->ops.raw++;
459 while (isspace(dl->ops.raw[0]))
460 ++dl->ops.raw;
461 }
462
463 disasm_line__init_ins(dl); 528 disasm_line__init_ins(dl);
464 } 529 }
465 } 530 }
@@ -477,8 +542,12 @@ void disasm_line__free(struct disasm_line *dl)
477{ 542{
478 free(dl->line); 543 free(dl->line);
479 free(dl->name); 544 free(dl->name);
480 free(dl->ops.source.raw); 545 if (dl->ins && dl->ins->ops == &lock_ops) {
481 free(dl->ops.source.name); 546 free(dl->ops.locked.ops);
547 } else {
548 free(dl->ops.source.raw);
549 free(dl->ops.source.name);
550 }
482 free(dl->ops.target.raw); 551 free(dl->ops.target.raw);
483 free(dl->ops.target.name); 552 free(dl->ops.target.name);
484 free(dl); 553 free(dl);
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 066d31d696df..b79d3260647c 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -18,11 +18,17 @@ struct ins_operands {
18 u64 addr; 18 u64 addr;
19 u64 offset; 19 u64 offset;
20 } target; 20 } target;
21 struct { 21 union {
22 char *raw; 22 struct {
23 char *name; 23 char *raw;
24 u64 addr; 24 char *name;
25 } source; 25 u64 addr;
26 } source;
27 struct {
28 struct ins *ins;
29 struct ins_operands *ops;
30 } locked;
31 };
26}; 32};
27 33
28struct ins_ops { 34struct ins_ops {