--stdio:: Use the stdio interface.
+--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
+
--stdio-color=<mode>::
'always', 'never' or 'auto', allowing configuring color output
via the command line, in addition to via "color.ui" .perfconfig.
struct perf_annotate {
struct perf_tool tool;
struct perf_session *session;
- bool use_tui, use_stdio, use_gtk;
+ bool use_tui, use_stdio, use_stdio2, use_gtk;
bool full_paths;
bool print_line;
bool skip_missing;
return ret;
}
+static bool has_annotation(struct perf_annotate *ann)
+{
+ return ui__has_annotation() || ann->use_stdio2;
+}
+
static int perf_evsel__add_sample(struct perf_evsel *evsel,
struct perf_sample *sample,
struct addr_location *al,
struct hist_entry *he;
int ret;
- if ((!ann->has_br_stack || !ui__has_annotation()) &&
+ if ((!ann->has_br_stack || !has_annotation(ann)) &&
ann->sym_hist_filter != NULL &&
(al->sym == NULL ||
strcmp(ann->sym_hist_filter, al->sym->name) != 0)) {
*/
process_branch_stack(sample->branch_stack, al, sample);
- if (ann->has_br_stack && ui__has_annotation())
+ if (ann->has_br_stack && has_annotation(ann))
return process_branch_callback(evsel, sample, al, ann, machine);
he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
struct perf_evsel *evsel,
struct perf_annotate *ann)
{
- return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
- ann->print_line, ann->full_paths, 0, 0);
+ if (!ann->use_stdio2)
+ return symbol__tty_annotate(he->ms.sym, he->ms.map, evsel,
+ ann->print_line, ann->full_paths, 0, 0);
+ return symbol__tty_annotate2(he->ms.sym, he->ms.map, evsel,
+ ann->print_line, ann->full_paths);
}
static void hists__find_annotations(struct hists *hists,
OPT_BOOLEAN(0, "gtk", &annotate.use_gtk, "Use the GTK interface"),
OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
+ OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
if (ret < 0)
goto out_delete;
- if (annotate.use_stdio)
+ if (annotate.use_stdio || annotate.use_stdio2)
use_browser = 0;
else if (annotate.use_tui)
use_browser = 1;
setup_browser(true);
- if (use_browser == 1 && annotate.has_br_stack) {
+ if ((use_browser == 1 || annotate.use_stdio2) && annotate.has_br_stack) {
sort__mode = SORT_MODE__BRANCH;
if (setup_sorting(annotate.session->evlist) < 0)
usage_with_options(annotate_usage, options);
return more;
}
+static void FILE__set_percent_color(void *fp __maybe_unused,
+ double percent __maybe_unused,
+ bool current __maybe_unused)
+{
+}
+
+static int FILE__set_jumps_percent_color(void *fp __maybe_unused,
+ int nr __maybe_unused, bool current __maybe_unused)
+{
+ return 0;
+}
+
+static int FILE__set_color(void *fp __maybe_unused, int color __maybe_unused)
+{
+ return 0;
+}
+
+static void FILE__printf(void *fp, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(fp, fmt, args);
+ va_end(args);
+}
+
+static void FILE__write_graph(void *fp, int graph)
+{
+ const char *s;
+ switch (graph) {
+
+ case DARROW_CHAR: s = "↓"; break;
+ case UARROW_CHAR: s = "↑"; break;
+ case LARROW_CHAR: s = "←"; break;
+ case RARROW_CHAR: s = "→"; break;
+ default: s = "?"; break;
+ }
+
+ fputs(s, fp);
+}
+
+int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp)
+{
+ struct annotation *notes = symbol__annotation(sym);
+ struct annotation_write_ops ops = {
+ .first_line = true,
+ .obj = fp,
+ .set_color = FILE__set_color,
+ .set_percent_color = FILE__set_percent_color,
+ .set_jumps_percent_color = FILE__set_jumps_percent_color,
+ .printf = FILE__printf,
+ .write_graph = FILE__write_graph,
+ };
+ struct annotation_line *al;
+
+ list_for_each_entry(al, ¬es->src->source, node) {
+ if (annotation_line__filter(al, notes))
+ continue;
+ annotation_line__write(al, notes, &ops);
+ fputc('\n', fp);
+ ops.first_line = false;
+ }
+
+ return 0;
+}
+
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx)
{
struct annotation *notes = symbol__annotation(sym);
annotation__calc_lines(notes, map, root, start);
}
+int symbol__tty_annotate2(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel, bool print_lines,
+ bool full_paths)
+{
+ struct dso *dso = map->dso;
+ struct rb_root source_line = RB_ROOT;
+ struct annotation_options opts = {
+ .use_offset = true,
+ };
+
+ if (symbol__annotate2(sym, map, evsel, &opts, NULL) < 0)
+ return -1;
+
+ if (print_lines) {
+ srcline_full_filename = full_paths;
+ symbol__calc_lines(sym, map, &source_line);
+ print_summary(&source_line, dso->long_name);
+ }
+
+ symbol__annotate_fprintf2(sym, stdout);
+
+ annotated_source__purge(symbol__annotation(sym)->src);
+
+ return 0;
+}
+
int symbol__tty_annotate(struct symbol *sym, struct map *map,
struct perf_evsel *evsel, bool print_lines,
bool full_paths, int min_pcnt, int max_lines)
int symbol__annotate_printf(struct symbol *sym, struct map *map,
struct perf_evsel *evsel, bool full_paths,
int min_pcnt, int max_lines, int context);
+int symbol__annotate_fprintf2(struct symbol *sym, FILE *fp);
void symbol__annotate_zero_histogram(struct symbol *sym, int evidx);
void symbol__annotate_decay_histogram(struct symbol *sym, int evidx);
void annotated_source__purge(struct annotated_source *as);
struct perf_evsel *evsel, bool print_lines,
bool full_paths, int min_pcnt, int max_lines);
+int symbol__tty_annotate2(struct symbol *sym, struct map *map,
+ struct perf_evsel *evsel, bool print_lines,
+ bool full_paths);
+
#ifdef HAVE_SLANG_SUPPORT
int symbol__tui_annotate(struct symbol *sym, struct map *map,
struct perf_evsel *evsel,