Commit a68c2c58 authored by Stephane Eranian's avatar Stephane Eranian Committed by Ingo Molnar

perf report: Enable TUI in branch view mode

This patch updates perf report to support TUI mode
when the perf.data file contains samples with branch
stacks.

For each row in the report, it is possible to annotate
either the source or target of each branch.
Signed-off-by: default avatarStephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: asharma@fb.com
Cc: ravitillo@lbl.gov
Cc: vweaver1@eecs.utk.edu
Cc: khandual@linux.vnet.ibm.com
Cc: dsahern@gmail.com
Link: http://lkml.kernel.org/r/1331246868-19905-5-git-send-email-eranian@google.comSigned-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 993ac88d
...@@ -64,7 +64,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, ...@@ -64,7 +64,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
int err = 0; int err = 0;
unsigned i; unsigned i;
struct hist_entry *he; struct hist_entry *he;
struct branch_info *bi; struct branch_info *bi, *bx;
if ((sort__has_parent || symbol_conf.use_callchain) if ((sort__has_parent || symbol_conf.use_callchain)
&& sample->callchain) { && sample->callchain) {
...@@ -89,11 +89,43 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, ...@@ -89,11 +89,43 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
he = __hists__add_branch_entry(&evsel->hists, al, parent, he = __hists__add_branch_entry(&evsel->hists, al, parent,
&bi[i], 1); &bi[i], 1);
if (he) { if (he) {
struct annotation *notes;
err = -ENOMEM;
bx = he->branch_info;
if (bx->from.sym && use_browser > 0) {
notes = symbol__annotation(bx->from.sym);
if (!notes->src
&& symbol__alloc_hist(bx->from.sym) < 0)
goto out;
err = symbol__inc_addr_samples(bx->from.sym,
bx->from.map,
evsel->idx,
bx->from.al_addr);
if (err)
goto out;
}
if (bx->to.sym && use_browser > 0) {
notes = symbol__annotation(bx->to.sym);
if (!notes->src
&& symbol__alloc_hist(bx->to.sym) < 0)
goto out;
err = symbol__inc_addr_samples(bx->to.sym,
bx->to.map,
evsel->idx,
bx->to.al_addr);
if (err)
goto out;
}
evsel->hists.stats.total_period += 1; evsel->hists.stats.total_period += 1;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
err = 0;
} else } else
return -ENOMEM; return -ENOMEM;
} }
out:
return err; return err;
} }
...@@ -615,32 +647,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) ...@@ -615,32 +647,19 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (sort__branch_mode == -1 && has_br_stack) if (sort__branch_mode == -1 && has_br_stack)
sort__branch_mode = 1; sort__branch_mode = 1;
/* sort__branch_mode could be 0 if --no-branch-stack */
if (sort__branch_mode == 1) { if (sort__branch_mode == 1) {
if (use_browser)
fprintf(stderr, "Warning: TUI interface not supported"
" in branch mode\n");
if (symbol_conf.dso_list_str != NULL)
fprintf(stderr, "Warning: dso filtering not supported"
" in branch mode\n");
if (symbol_conf.sym_list_str != NULL)
fprintf(stderr, "Warning: symbol filtering not"
" supported in branch mode\n");
report.use_stdio = true;
use_browser = 0;
setup_browser(true);
symbol_conf.dso_list_str = NULL;
symbol_conf.sym_list_str = NULL;
/* /*
* if no sort_order is provided, then specify branch-mode * if no sort_order is provided, then specify
* specific order * branch-mode specific order
*/ */
if (sort_order == default_sort_order) if (sort_order == default_sort_order)
sort_order = "comm,dso_from,symbol_from," sort_order = "comm,dso_from,symbol_from,"
"dso_to,symbol_to"; "dso_to,symbol_to";
} else if (strcmp(report.input_name, "-") != 0) { }
if (strcmp(report.input_name, "-") != 0) {
setup_browser(true); setup_browser(true);
} else { } else {
use_browser = 0; use_browser = 0;
...@@ -696,9 +715,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) ...@@ -696,9 +715,17 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
if (argc) if (argc)
usage_with_options(report_usage, options); usage_with_options(report_usage, options);
sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout); sort_entry__setup_elide(&sort_comm, symbol_conf.comm_list, "comm", stdout);
if (sort__branch_mode == 1) {
sort_entry__setup_elide(&sort_dso_from, symbol_conf.dso_from_list, "dso_from", stdout);
sort_entry__setup_elide(&sort_dso_to, symbol_conf.dso_to_list, "dso_to", stdout);
sort_entry__setup_elide(&sort_sym_from, symbol_conf.sym_from_list, "sym_from", stdout);
sort_entry__setup_elide(&sort_sym_to, symbol_conf.sym_to_list, "sym_to", stdout);
} else {
sort_entry__setup_elide(&sort_dso, symbol_conf.dso_list, "dso", stdout);
sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout); sort_entry__setup_elide(&sort_sym, symbol_conf.sym_list, "symbol", stdout);
}
ret = __cmd_report(&report); ret = __cmd_report(&report);
error: error:
......
...@@ -263,6 +263,7 @@ static void ip__resolve_ams(struct machine *self, struct thread *thread, ...@@ -263,6 +263,7 @@ static void ip__resolve_ams(struct machine *self, struct thread *thread,
} }
found: found:
ams->addr = ip; ams->addr = ip;
ams->al_addr = al.addr;
ams->sym = al.sym; ams->sym = al.sym;
ams->map = al.map; ams->map = al.map;
} }
......
...@@ -37,8 +37,10 @@ extern struct sort_entry sort_comm; ...@@ -37,8 +37,10 @@ extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso; extern struct sort_entry sort_dso;
extern struct sort_entry sort_sym; extern struct sort_entry sort_sym;
extern struct sort_entry sort_parent; extern struct sort_entry sort_parent;
extern struct sort_entry sort_lbr_dso; extern struct sort_entry sort_dso_from;
extern struct sort_entry sort_lbr_sym; extern struct sort_entry sort_dso_to;
extern struct sort_entry sort_sym_from;
extern struct sort_entry sort_sym_to;
extern enum sort_type sort__first_dimension; extern enum sort_type sort__first_dimension;
/** /**
......
...@@ -97,7 +97,11 @@ struct symbol_conf { ...@@ -97,7 +97,11 @@ struct symbol_conf {
*col_width_list_str; *col_width_list_str;
struct strlist *dso_list, struct strlist *dso_list,
*comm_list, *comm_list,
*sym_list; *sym_list,
*dso_from_list,
*dso_to_list,
*sym_from_list,
*sym_to_list;
const char *symfs; const char *symfs;
}; };
...@@ -125,6 +129,7 @@ struct addr_map_symbol { ...@@ -125,6 +129,7 @@ struct addr_map_symbol {
struct map *map; struct map *map;
struct symbol *sym; struct symbol *sym;
u64 addr; u64 addr;
u64 al_addr;
}; };
struct branch_info { struct branch_info {
......
...@@ -805,7 +805,10 @@ static struct hist_browser *hist_browser__new(struct hists *hists) ...@@ -805,7 +805,10 @@ static struct hist_browser *hist_browser__new(struct hists *hists)
self->hists = hists; self->hists = hists;
self->b.refresh = hist_browser__refresh; self->b.refresh = hist_browser__refresh;
self->b.seek = ui_browser__hists_seek; self->b.seek = ui_browser__hists_seek;
self->b.use_navkeypressed = true, self->b.use_navkeypressed = true;
if (sort__branch_mode == 1)
self->has_symbols = sort_sym_from.list.next != NULL;
else
self->has_symbols = sort_sym.list.next != NULL; self->has_symbols = sort_sym.list.next != NULL;
} }
...@@ -861,6 +864,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -861,6 +864,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
{ {
struct hists *self = &evsel->hists; struct hists *self = &evsel->hists;
struct hist_browser *browser = hist_browser__new(self); struct hist_browser *browser = hist_browser__new(self);
struct branch_info *bi;
struct pstack *fstack; struct pstack *fstack;
int key = -1; int key = -1;
...@@ -879,7 +883,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -879,7 +883,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
char *options[16]; char *options[16];
int nr_options = 0, choice = 0, i, int nr_options = 0, choice = 0, i,
annotate = -2, zoom_dso = -2, zoom_thread = -2, annotate = -2, zoom_dso = -2, zoom_thread = -2,
browse_map = -2; annotate_f = -2, annotate_t = -2, browse_map = -2;
key = hist_browser__run(browser, ev_name, timer, arg, delay_secs); key = hist_browser__run(browser, ev_name, timer, arg, delay_secs);
...@@ -887,7 +891,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -887,7 +891,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
thread = hist_browser__selected_thread(browser); thread = hist_browser__selected_thread(browser);
dso = browser->selection->map ? browser->selection->map->dso : NULL; dso = browser->selection->map ? browser->selection->map->dso : NULL;
} }
switch (key) { switch (key) {
case K_TAB: case K_TAB:
case K_UNTAB: case K_UNTAB:
...@@ -902,7 +905,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -902,7 +905,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols) { if (!browser->has_symbols) {
ui_browser__warning(&browser->b, delay_secs * 2, ui_browser__warning(&browser->b, delay_secs * 2,
"Annotation is only available for symbolic views, " "Annotation is only available for symbolic views, "
"include \"sym\" in --sort to use it."); "include \"sym*\" in --sort to use it.");
continue; continue;
} }
...@@ -972,12 +975,32 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -972,12 +975,32 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (!browser->has_symbols) if (!browser->has_symbols)
goto add_exit_option; goto add_exit_option;
if (sort__branch_mode == 1) {
bi = browser->he_selection->branch_info;
if (browser->selection != NULL &&
bi &&
bi->from.sym != NULL &&
!bi->from.map->dso->annotate_warned &&
asprintf(&options[nr_options], "Annotate %s",
bi->from.sym->name) > 0)
annotate_f = nr_options++;
if (browser->selection != NULL &&
bi &&
bi->to.sym != NULL &&
!bi->to.map->dso->annotate_warned &&
asprintf(&options[nr_options], "Annotate %s",
bi->to.sym->name) > 0)
annotate_t = nr_options++;
} else {
if (browser->selection != NULL && if (browser->selection != NULL &&
browser->selection->sym != NULL && browser->selection->sym != NULL &&
!browser->selection->map->dso->annotate_warned && !browser->selection->map->dso->annotate_warned &&
asprintf(&options[nr_options], "Annotate %s", asprintf(&options[nr_options], "Annotate %s",
browser->selection->sym->name) > 0) browser->selection->sym->name) > 0)
annotate = nr_options++; annotate = nr_options++;
}
if (thread != NULL && if (thread != NULL &&
asprintf(&options[nr_options], "Zoom %s %s(%d) thread", asprintf(&options[nr_options], "Zoom %s %s(%d) thread",
...@@ -1010,13 +1033,28 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, ...@@ -1010,13 +1033,28 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (choice == -1) if (choice == -1)
continue; continue;
if (choice == annotate) { if (choice == annotate || choice == annotate_t || choice == annotate_f) {
struct hist_entry *he; struct hist_entry *he;
int err; int err;
do_annotate: do_annotate:
he = hist_browser__selected_entry(browser); he = hist_browser__selected_entry(browser);
if (he == NULL) if (he == NULL)
continue; continue;
/*
* we stash the branch_info symbol + map into the
* the ms so we don't have to rewrite all the annotation
* code to use branch_info.
* in branch mode, the ms struct is not used
*/
if (choice == annotate_f) {
he->ms.sym = he->branch_info->from.sym;
he->ms.map = he->branch_info->from.map;
} else if (choice == annotate_t) {
he->ms.sym = he->branch_info->to.sym;
he->ms.map = he->branch_info->to.map;
}
/* /*
* Don't let this be freed, say, by hists__decay_entry. * Don't let this be freed, say, by hists__decay_entry.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment