aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/annotate.c112
-rw-r--r--tools/perf/util/annotate.h8
2 files changed, 119 insertions, 1 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}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index bb0a9f27165b..066d31d696df 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -13,10 +13,16 @@ struct ins;
13struct ins_operands { 13struct ins_operands {
14 char *raw; 14 char *raw;
15 struct { 15 struct {
16 char *raw;
16 char *name; 17 char *name;
17 u64 offset;
18 u64 addr; 18 u64 addr;
19 u64 offset;
19 } target; 20 } target;
21 struct {
22 char *raw;
23 char *name;
24 u64 addr;
25 } source;
20}; 26};
21 27
22struct ins_ops { 28struct ins_ops {