aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/annotate.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-05-11 15:48:49 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-05-11 16:19:20 -0400
commit6de783b6f50f7f1db18a3fda0aa34b2e84b5771d (patch)
treeb5606aafa9e9703d433d8dff6ef931027832eb90 /tools/perf/util/annotate.c
parente8ea1561952b04276cf4c02500e363de76c142aa (diff)
perf annotate: Resolve symbols using objdump comment
This: mov 0x95bbb6(%rip),%ecx # ffffffff81ae8d04 <d_hash_shift> Becomes: mov d_hash_shift,%ecx Ditto for many more instructions that take two operands. Requested-by: Linus Torvalds <torvalds@linux-foundation.org> 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-i5opbyai2x6mn9e5yjmhx9k6@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.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 9a020d1e0180..82c7f630f8a8 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -122,6 +122,89 @@ bool ins__is_jump(const struct ins *ins)
122 return ins->ops == &jump_ops; 122 return ins->ops == &jump_ops;
123} 123}
124 124
125static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
126{
127 char *endptr, *name, *t;
128
129 if (strstr(raw, "(%rip)") == NULL)
130 return 0;
131
132 *addrp = strtoull(comment, &endptr, 16);
133 name = strchr(endptr, '<');
134 if (name == NULL)
135 return -1;
136
137 name++;
138
139 t = strchr(name, '>');
140 if (t == NULL)
141 return 0;
142
143 *t = '\0';
144 *namep = strdup(name);
145 *t = '>';
146
147 return 0;
148}
149
150static int mov__parse(struct ins_operands *ops)
151{
152 char *s = strchr(ops->raw, ','), *target, *comment, prev;
153
154 if (s == NULL)
155 return -1;
156
157 *s = '\0';
158 ops->source.raw = strdup(ops->raw);
159 *s = ',';
160
161 if (ops->source.raw == NULL)
162 return -1;
163
164 target = ++s;
165
166 while (s[0] != '\0' && !isspace(s[0]))
167 ++s;
168 prev = *s;
169 *s = '\0';
170
171 ops->target.raw = strdup(target);
172 *s = prev;
173
174 if (ops->target.raw == NULL)
175 goto out_free_source;
176
177 comment = strchr(s, '#');
178 if (comment == NULL)
179 return 0;
180
181 while (comment[0] != '\0' && isspace(comment[0]))
182 ++comment;
183
184 comment__symbol(ops->source.raw, comment, &ops->source.addr, &ops->source.name);
185 comment__symbol(ops->target.raw, comment, &ops->target.addr, &ops->target.name);
186
187 return 0;
188
189out_free_source:
190 free(ops->source.raw);
191 ops->source.raw = NULL;
192 return -1;
193}
194
195static int mov__scnprintf(struct ins *ins, char *bf, size_t size,
196 struct ins_operands *ops)
197{
198 return scnprintf(bf, size, "%-6.6s %s,%s", ins->name,
199 ops->source.name ?: ops->source.raw,
200 ops->target.name ?: ops->target.raw);
201}
202
203static struct ins_ops mov_ops = {
204 .parse = mov__parse,
205 .scnprintf = mov__scnprintf,
206};
207
125static int nop__scnprintf(struct ins *ins __used, char *bf, size_t size, 208static int nop__scnprintf(struct ins *ins __used, char *bf, size_t size,
126 struct ins_operands *ops __used) 209 struct ins_operands *ops __used)
127{ 210{
@@ -136,8 +219,20 @@ static struct ins_ops nop_ops = {
136 * Must be sorted by name! 219 * Must be sorted by name!
137 */ 220 */
138static struct ins instructions[] = { 221static struct ins instructions[] = {
222 { .name = "add", .ops = &mov_ops, },
223 { .name = "addl", .ops = &mov_ops, },
224 { .name = "addq", .ops = &mov_ops, },
225 { .name = "addw", .ops = &mov_ops, },
226 { .name = "and", .ops = &mov_ops, },
139 { .name = "call", .ops = &call_ops, }, 227 { .name = "call", .ops = &call_ops, },
140 { .name = "callq", .ops = &call_ops, }, 228 { .name = "callq", .ops = &call_ops, },
229 { .name = "cmp", .ops = &mov_ops, },
230 { .name = "cmpb", .ops = &mov_ops, },
231 { .name = "cmpl", .ops = &mov_ops, },
232 { .name = "cmpq", .ops = &mov_ops, },
233 { .name = "cmpw", .ops = &mov_ops, },
234 { .name = "cmpxch", .ops = &mov_ops, },
235 { .name = "imul", .ops = &mov_ops, },
141 { .name = "ja", .ops = &jump_ops, }, 236 { .name = "ja", .ops = &jump_ops, },
142 { .name = "jae", .ops = &jump_ops, }, 237 { .name = "jae", .ops = &jump_ops, },
143 { .name = "jb", .ops = &jump_ops, }, 238 { .name = "jb", .ops = &jump_ops, },
@@ -173,9 +268,23 @@ static struct ins instructions[] = {
173 { .name = "jrcxz", .ops = &jump_ops, }, 268 { .name = "jrcxz", .ops = &jump_ops, },
174 { .name = "js", .ops = &jump_ops, }, 269 { .name = "js", .ops = &jump_ops, },
175 { .name = "jz", .ops = &jump_ops, }, 270 { .name = "jz", .ops = &jump_ops, },
271 { .name = "lea", .ops = &mov_ops, },
272 { .name = "mov", .ops = &mov_ops, },
273 { .name = "movb", .ops = &mov_ops, },
274 { .name = "movdqa",.ops = &mov_ops, },
275 { .name = "movl", .ops = &mov_ops, },
276 { .name = "movq", .ops = &mov_ops, },
277 { .name = "movslq", .ops = &mov_ops, },
278 { .name = "movzbl", .ops = &mov_ops, },
279 { .name = "movzwl", .ops = &mov_ops, },
176 { .name = "nop", .ops = &nop_ops, }, 280 { .name = "nop", .ops = &nop_ops, },
177 { .name = "nopl", .ops = &nop_ops, }, 281 { .name = "nopl", .ops = &nop_ops, },
178 { .name = "nopw", .ops = &nop_ops, }, 282 { .name = "nopw", .ops = &nop_ops, },
283 { .name = "or", .ops = &mov_ops, },
284 { .name = "orl", .ops = &mov_ops, },
285 { .name = "test", .ops = &mov_ops, },
286 { .name = "testb", .ops = &mov_ops, },
287 { .name = "testl", .ops = &mov_ops, },
179}; 288};
180 289
181static int ins__cmp(const void *name, const void *insp) 290static int ins__cmp(const void *name, const void *insp)
@@ -323,6 +432,9 @@ void disasm_line__free(struct disasm_line *dl)
323{ 432{
324 free(dl->line); 433 free(dl->line);
325 free(dl->name); 434 free(dl->name);
435 free(dl->ops.source.raw);
436 free(dl->ops.source.name);
437 free(dl->ops.target.raw);
326 free(dl->ops.target.name); 438 free(dl->ops.target.name);
327 free(dl); 439 free(dl);
328} 440}