summaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/ui/browsers/annotate.c23
-rw-r--r--tools/perf/util/annotate.c6
2 files changed, 22 insertions, 7 deletions
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index d77896a99570..c02fb437ac8e 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 @@ show_help:
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 9524f322f597..5fa270b24eea 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, ',');