Skip to content

Commit

Permalink
perf annotate: Disassembler instruction parsing
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Arnaldo Carvalho de Melo committed Apr 18, 2012
1 parent 657bcaf commit 4f9d032
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 16 deletions.
19 changes: 3 additions & 16 deletions tools/perf/ui/browsers/annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,26 +315,13 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows

static bool annotate_browser__jump(struct annotate_browser *browser)
{
const char *jumps[] = { "je", "jne", "ja", "jmpq", "js", "jmp", NULL };
struct disasm_line *dl = browser->selection;
s64 idx, offset;
char *s;
int i = 0;

while (jumps[i] && strcmp(dl->name, jumps[i]))
++i;
s64 idx;

if (jumps[i] == NULL)
if (!dl->ins || !ins__is_jump(dl->ins))
return false;

s = strchr(dl->operands, '+');
if (s++ == NULL) {
ui_helpline__puts("Invallid jump instruction.");
return true;
}

offset = strtoll(s, NULL, 16);
dl = annotate_browser__find_offset(browser, offset, &idx);
dl = annotate_browser__find_offset(browser, dl->target, &idx);
if (dl == NULL) {
ui_helpline__puts("Invallid jump offset");
return true;
Expand Down
63 changes: 63 additions & 0 deletions tools/perf/util/annotate.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,53 @@

const char *disassembler_style;

static int jump_ops__parse_target(const char *operands, u64 *target)
{
const char *s = strchr(operands, '+');

if (s++ == NULL)
return -1;

*target = strtoll(s, NULL, 16);
return 0;
}

static struct ins_ops jump_ops = {
.parse_target = jump_ops__parse_target,
};

bool ins__is_jump(const struct ins *ins)
{
return ins->ops == &jump_ops;
}


/*
* Must be sorted by name!
*/
static struct ins instructions[] = {
{ .name = "ja", .ops = &jump_ops, },
{ .name = "je", .ops = &jump_ops, },
{ .name = "jmp", .ops = &jump_ops, },
{ .name = "jmpq", .ops = &jump_ops, },
{ .name = "jne", .ops = &jump_ops, },
{ .name = "js", .ops = &jump_ops, },
};

static int ins__cmp(const void *name, const void *insp)
{
const struct ins *ins = insp;

return strcmp(name, ins->name);
}

static struct ins *ins__find(const char *name)
{
const int nmemb = ARRAY_SIZE(instructions);

return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp);
}

int symbol__annotate_init(struct map *map __used, struct symbol *sym)
{
struct annotation *notes = symbol__annotation(sym);
Expand Down Expand Up @@ -78,6 +125,20 @@ int symbol__inc_addr_samples(struct symbol *sym, struct map *map,
return 0;
}

static void disasm_line__init_ins(struct disasm_line *dl)
{
dl->ins = ins__find(dl->name);

if (dl->ins == NULL)
return;

if (!dl->ins->ops)
return;

if (dl->ins->ops->parse_target)
dl->ins->ops->parse_target(dl->operands, &dl->target);
}

static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privsize)
{
struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
Expand Down Expand Up @@ -117,6 +178,8 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line, size_t privs
while (isspace(dl->operands[0]))
++dl->operands;
}

disasm_line__init_ins(dl);
}
}

Expand Down
13 changes: 13 additions & 0 deletions tools/perf/util/annotate.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,24 @@
#include <linux/list.h>
#include <linux/rbtree.h>

struct ins_ops {
int (*parse_target)(const char *operands, u64 *target);
};

struct ins {
const char *name;
struct ins_ops *ops;
};

bool ins__is_jump(const struct ins *ins);

struct disasm_line {
struct list_head node;
s64 offset;
u64 target;
char *line;
char *name;
struct ins *ins;
char *operands;
};

Expand Down

0 comments on commit 4f9d032

Please sign in to comment.