diff options
-rw-r--r-- | tools/perf/util/ui/browsers/annotate.c | 63 |
1 files changed, 61 insertions, 2 deletions
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c index c52543c69ae0..752d8d0e480c 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c | |||
@@ -168,6 +168,9 @@ static void annotate_browser__set_top(struct annotate_browser *self, | |||
168 | while (self->b.top_idx != 0 && back != 0) { | 168 | while (self->b.top_idx != 0 && back != 0) { |
169 | pos = list_entry(pos->node.prev, struct objdump_line, node); | 169 | pos = list_entry(pos->node.prev, struct objdump_line, node); |
170 | 170 | ||
171 | if (objdump_line__filter(&self->b, &pos->node)) | ||
172 | continue; | ||
173 | |||
171 | --self->b.top_idx; | 174 | --self->b.top_idx; |
172 | --back; | 175 | --back; |
173 | } | 176 | } |
@@ -296,6 +299,61 @@ static bool annotate_browser__callq(struct annotate_browser *browser, | |||
296 | return true; | 299 | return true; |
297 | } | 300 | } |
298 | 301 | ||
302 | static struct objdump_line * | ||
303 | annotate_browser__find_offset(struct annotate_browser *browser, | ||
304 | s64 offset, s64 *idx) | ||
305 | { | ||
306 | struct map_symbol *ms = browser->b.priv; | ||
307 | struct symbol *sym = ms->sym; | ||
308 | struct annotation *notes = symbol__annotation(sym); | ||
309 | struct objdump_line *pos; | ||
310 | |||
311 | *idx = 0; | ||
312 | list_for_each_entry(pos, ¬es->src->source, node) { | ||
313 | if (pos->offset == offset) | ||
314 | return pos; | ||
315 | if (!objdump_line__filter(&browser->b, &pos->node)) | ||
316 | ++*idx; | ||
317 | } | ||
318 | |||
319 | return NULL; | ||
320 | } | ||
321 | |||
322 | static bool annotate_browser__jump(struct annotate_browser *browser) | ||
323 | { | ||
324 | const char *jumps[] = { "je ", "jne ", "ja ", "jmpq ", "js ", "jmp ", NULL }; | ||
325 | struct objdump_line *line; | ||
326 | s64 idx, offset; | ||
327 | char *s = NULL; | ||
328 | int i = 0; | ||
329 | |||
330 | while (jumps[i]) { | ||
331 | s = strstr(browser->selection->line, jumps[i++]); | ||
332 | if (s) | ||
333 | break; | ||
334 | } | ||
335 | |||
336 | if (s == NULL) | ||
337 | return false; | ||
338 | |||
339 | s = strchr(s, '+'); | ||
340 | if (s++ == NULL) { | ||
341 | ui_helpline__puts("Invallid jump instruction."); | ||
342 | return true; | ||
343 | } | ||
344 | |||
345 | offset = strtoll(s, NULL, 16); | ||
346 | line = annotate_browser__find_offset(browser, offset, &idx); | ||
347 | if (line == NULL) { | ||
348 | ui_helpline__puts("Invallid jump offset"); | ||
349 | return true; | ||
350 | } | ||
351 | |||
352 | annotate_browser__set_top(browser, line, idx); | ||
353 | |||
354 | return true; | ||
355 | } | ||
356 | |||
299 | static int annotate_browser__run(struct annotate_browser *self, int evidx, | 357 | static int annotate_browser__run(struct annotate_browser *self, int evidx, |
300 | void(*timer)(void *arg), | 358 | void(*timer)(void *arg), |
301 | void *arg, int delay_secs) | 359 | void *arg, int delay_secs) |
@@ -376,8 +434,9 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx, | |||
376 | ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); | 434 | ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); |
377 | else if (self->selection->offset == -1) | 435 | else if (self->selection->offset == -1) |
378 | ui_helpline__puts("Actions are only available for assembly lines."); | 436 | ui_helpline__puts("Actions are only available for assembly lines."); |
379 | else if (!annotate_browser__callq(self, evidx, timer, arg, delay_secs)) | 437 | else if (!(annotate_browser__jump(self) || |
380 | ui_helpline__puts("Actions are only available for the 'callq' instruction."); | 438 | annotate_browser__callq(self, evidx, timer, arg, delay_secs))) |
439 | ui_helpline__puts("Actions are only available for the 'callq' and jump instructions."); | ||
381 | continue; | 440 | continue; |
382 | case K_LEFT: | 441 | case K_LEFT: |
383 | case K_ESC: | 442 | case K_ESC: |