diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index d77896a9957025c18f23c98e7d442f36b56bb96c..c02fb437ac8e9bb59b833bfd579b1e6c88168b3e 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -384,6 +384,15 @@ static int sym_title(struct symbol *sym, struct map *map, char *title, return snprintf(title, sz, "%s %s", sym->name, map->dso->long_name); } +/* + * This can be called from external jumps, i.e. jumps from one functon + * to another, like from the kernel's entry_SYSCALL_64 function to the + * swapgs_restore_regs_and_return_to_usermode() function. + * + * So all we check here is that dl->ops.target.sym is set, if it is, just + * go to that function and when exiting from its disassembly, come back + * to the calling function. + */ static bool annotate_browser__callq(struct annotate_browser *browser, struct perf_evsel *evsel, struct hist_browser_timer *hbt) @@ -393,9 +402,6 @@ static bool annotate_browser__callq(struct annotate_browser *browser, struct annotation *notes; char title[SYM_TITLE_MAX_SIZE]; - if (!ins__is_call(&dl->ins)) - return false; - if (!dl->ops.target.sym) { ui_helpline__puts("The called function was not found."); return true; @@ -436,7 +442,9 @@ struct disasm_line *annotate_browser__find_offset(struct annotate_browser *brows return NULL; } -static bool annotate_browser__jump(struct annotate_browser *browser) +static bool annotate_browser__jump(struct annotate_browser *browser, + struct perf_evsel *evsel, + struct hist_browser_timer *hbt) { struct disasm_line *dl = disasm_line(browser->selection); u64 offset; @@ -445,6 +453,11 @@ static bool annotate_browser__jump(struct annotate_browser *browser) if (!ins__is_jump(&dl->ins)) return false; + if (dl->ops.target.outside) { + annotate_browser__callq(browser, evsel, hbt); + return true; + } + offset = dl->ops.target.offset; dl = annotate_browser__find_offset(browser, offset, &idx); if (dl == NULL) { @@ -731,7 +744,7 @@ static int annotate_browser__run(struct annotate_browser *browser, goto show_sup_ins; else if (ins__is_ret(&dl->ins)) goto out; - else if (!(annotate_browser__jump(browser) || + else if (!(annotate_browser__jump(browser, evsel, hbt) || annotate_browser__callq(browser, evsel, hbt))) { show_sup_ins: ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions."); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 9524f322f597766ff77030dff5cb0b77197f0f0c..5fa270b24eeabd829a53c60ce631cd8572baa8a2 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -332,11 +332,10 @@ static int jump__parse(struct arch *arch __maybe_unused, struct ins_operands *op * * Actual navigation will come next, with further understanding of how * the symbol searching and disassembly should be done. - + */ if (map_groups__find_ams(&target) == 0 && map__rip_2objdump(target.map, map->map_ip(target.map, target.addr)) == ops->target.addr) ops->target.sym = target.sym; - */ if (s++ != NULL) { ops->target.offset = strtoull(s, NULL, 16); @@ -356,6 +355,9 @@ static int jump__scnprintf(struct ins *ins, char *bf, size_t size, if (!ops->target.addr || ops->target.offset < 0) return ins__raw_scnprintf(ins, bf, size, ops); + if (ops->target.outside && ops->target.sym != NULL) + return scnprintf(bf, size, "%-6s %s", ins->name, ops->target.sym->name); + if (c != NULL) { const char *c2 = strchr(c + 1, ',');