From bb848c14f80d93059cb10b1e1446cc6823d77142 Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Tue, 27 Feb 2018 17:38:47 +0800 Subject: perf annotate: Support to display the IPC/Cycle in TUI mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unlike the perf report interactive annotate mode, the perf annotate doesn't display the IPC/Cycle even if branch info is recorded in perf data file. perf record -b ... perf annotate function It should show IPC/cycle, but it doesn't. This patch lets perf annotate support the displaying of IPC/Cycle if branch info is in perf data. For example, perf annotate compute_flag Percent│ IPC Cycle │ │ │ Disassembly of section .text: │ │ 0000000000400640 : │ compute_flag(): │ volatile int count; │ static unsigned int s_randseed; │ │ __attribute__((noinline)) │ int compute_flag() │ { 22.96 │1.18 584 sub $0x8,%rsp │ int i; │ │ i = rand() % 2; 23.02 │1.18 1 → callq rand@plt │ │ return i; 27.05 │3.37 mov %eax,%edx │ } │3.37 add $0x8,%rsp │ { │ int i; │ │ i = rand() % 2; │ │ return i; │3.37 shr $0x1f,%edx │3.37 add %edx,%eax │3.37 and $0x1,%eax │3.37 sub %edx,%eax │ } 26.97 │3.37 2 ← retq Note that, this patch only supports TUI mode. For stdio, now it just keeps original behavior. Will support it in a follow-up patch. $ perf annotate compute_flag --stdio Percent | Source code & Disassembly of div for cycles:ppp (7993 samples) ------------------------------------------------------------------------------ : : : : Disassembly of section .text: : : 0000000000400640 : : compute_flag(): : volatile int count; : static unsigned int s_randseed; : : __attribute__((noinline)) : int compute_flag() : { 0.29 : 400640: sub $0x8,%rsp # +100.00% : int i; : : i = rand() % 2; 42.93 : 400644: callq 400490 # -100.00% (p:100.00%) : : return i; 0.10 : 400649: mov %eax,%edx # +100.00% : } 0.94 : 40064b: add $0x8,%rsp : { : int i; : : i = rand() % 2; : : return i; 27.02 : 40064f: shr $0x1f,%edx 0.15 : 400652: add %edx,%eax 1.24 : 400654: and $0x1,%eax 2.08 : 400657: sub %edx,%eax : } 25.26 : 400659: retq # -100.00% (p:100.00%) Signed-off-by: Jin Yao Acked-by: Andi Kleen Link: http://lkml.kernel.org/r/20180223170210.GC7045@tassilo.jf.intel.com Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1519724327-7773-1-git-send-email-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 88 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index f15731a3d438..ead6ae4549e5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -44,6 +44,7 @@ struct perf_annotate { bool full_paths; bool print_line; bool skip_missing; + bool has_br_stack; const char *sym_hist_filter; const char *cpu_list; DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); @@ -146,16 +147,73 @@ static void process_branch_stack(struct branch_stack *bs, struct addr_location * free(bi); } +static int hist_iter__branch_callback(struct hist_entry_iter *iter, + struct addr_location *al __maybe_unused, + bool single __maybe_unused, + void *arg __maybe_unused) +{ + struct hist_entry *he = iter->he; + struct branch_info *bi; + struct perf_sample *sample = iter->sample; + struct perf_evsel *evsel = iter->evsel; + int err; + + hist__account_cycles(sample->branch_stack, al, sample, false); + + bi = he->branch_info; + err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx); + + if (err) + goto out; + + err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx); + +out: + return err; +} + +static int process_branch_callback(struct perf_evsel *evsel, + struct perf_sample *sample, + struct addr_location *al __maybe_unused, + struct perf_annotate *ann, + struct machine *machine) +{ + struct hist_entry_iter iter = { + .evsel = evsel, + .sample = sample, + .add_entry_cb = hist_iter__branch_callback, + .hide_unresolved = symbol_conf.hide_unresolved, + .ops = &hist_iter_branch, + }; + + struct addr_location a; + int ret; + + if (machine__resolve(machine, &a, sample) < 0) + return -1; + + if (a.sym == NULL) + return 0; + + if (a.map != NULL) + a.map->dso->hit = 1; + + ret = hist_entry_iter__add(&iter, &a, PERF_MAX_STACK_DEPTH, ann); + return ret; +} + static int perf_evsel__add_sample(struct perf_evsel *evsel, struct perf_sample *sample, struct addr_location *al, - struct perf_annotate *ann) + struct perf_annotate *ann, + struct machine *machine) { struct hists *hists = evsel__hists(evsel); struct hist_entry *he; int ret; - if (ann->sym_hist_filter != NULL && + if ((!ann->has_br_stack || !ui__has_annotation()) && + ann->sym_hist_filter != NULL && (al->sym == NULL || strcmp(ann->sym_hist_filter, al->sym->name) != 0)) { /* We're only interested in a symbol named sym_hist_filter */ @@ -178,6 +236,9 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, */ process_branch_stack(sample->branch_stack, al, sample); + if (ann->has_br_stack && ui__has_annotation()) + return process_branch_callback(evsel, sample, al, ann, machine); + he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); if (he == NULL) return -ENOMEM; @@ -206,7 +267,8 @@ static int process_sample_event(struct perf_tool *tool, if (ann->cpu_list && !test_bit(sample->cpu, ann->cpu_bitmap)) goto out_put; - if (!al.filtered && perf_evsel__add_sample(evsel, sample, &al, ann)) { + if (!al.filtered && + perf_evsel__add_sample(evsel, sample, &al, ann, machine)) { pr_warning("problem incrementing symbol count, " "skipping event\n"); ret = -1; @@ -238,6 +300,10 @@ static void hists__find_annotations(struct hists *hists, if (he->ms.sym == NULL || he->ms.map->dso->annotate_warned) goto find_next; + if (ann->sym_hist_filter && + (strcmp(he->ms.sym->name, ann->sym_hist_filter) != 0)) + goto find_next; + notes = symbol__annotation(he->ms.sym); if (notes->src == NULL) { find_next: @@ -269,6 +335,7 @@ find_next: nd = rb_next(nd); } else if (use_browser == 1) { key = hist_entry__tui_annotate(he, evsel, NULL); + switch (key) { case -1: if (!ann->skip_missing) @@ -489,6 +556,9 @@ int cmd_annotate(int argc, const char **argv) if (annotate.session == NULL) return -1; + annotate.has_br_stack = perf_header__has_feat(&annotate.session->header, + HEADER_BRANCH_STACK); + ret = symbol__annotation_init(); if (ret < 0) goto out_delete; @@ -499,9 +569,6 @@ int cmd_annotate(int argc, const char **argv) if (ret < 0) goto out_delete; - if (setup_sorting(NULL) < 0) - usage_with_options(annotate_usage, options); - if (annotate.use_stdio) use_browser = 0; else if (annotate.use_tui) @@ -511,6 +578,15 @@ int cmd_annotate(int argc, const char **argv) setup_browser(true); + if (use_browser == 1 && annotate.has_br_stack) { + sort__mode = SORT_MODE__BRANCH; + if (setup_sorting(annotate.session->evlist) < 0) + usage_with_options(annotate_usage, options); + } else { + if (setup_sorting(NULL) < 0) + usage_with_options(annotate_usage, options); + } + ret = __cmd_annotate(&annotate); out_delete: -- cgit v1.2.3 From befd2a38a632b1f27ad652fea67c8cf97ce59409 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Thu, 15 Mar 2018 23:44:34 -0300 Subject: perf annotate: Introduce the --stdio2 output mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This uses the TUI augmented formatting routines, modulo interactivity. # perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave _raw_spin_lock_irqsave() /proc/kcore Event: cycles:ppp Percent Disassembly of section load0: ffffffff9a8734b0 : nop push %rbx 50.00 pushfq pop %rax nop mov %rax,%rbx cli nop xor %eax,%eax mov $0x1,%edx 50.00 lock cmpxchg %edx,(%rdi) test %eax,%eax ↓ jne 2b mov %rbx,%rax pop %rbx ← retq 2b: mov %eax,%esi → callq queued_spin_lock_slowpath mov %rbx,%rax pop %rbx ← retq Tested-by: Jin Yao Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-6cte5o8z84mbivbvqlg14uh1@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-annotate.txt | 2 + tools/perf/builtin-annotate.c | 23 +++++--- tools/perf/util/annotate.c | 92 ++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 5 ++ 4 files changed, 115 insertions(+), 7 deletions(-) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index 292809c3c0ca..c29c7fc93023 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -69,6 +69,8 @@ OPTIONS --stdio:: Use the stdio interface. +--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting. + --stdio-color=:: 'always', 'never' or 'auto', allowing configuring color output via the command line, in addition to via "color.ui" .perfconfig. diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ead6ae4549e5..e03f9bea9303 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -40,7 +40,7 @@ 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; @@ -202,6 +202,11 @@ static int process_branch_callback(struct perf_evsel *evsel, 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, @@ -212,7 +217,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, 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)) { @@ -236,7 +241,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, */ 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); @@ -282,8 +287,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he, 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, @@ -487,6 +495,7 @@ int cmd_annotate(int argc, const char **argv) 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, @@ -569,7 +578,7 @@ int cmd_annotate(int argc, const char **argv) 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; @@ -578,7 +587,7 @@ int cmd_annotate(int argc, const char **argv) 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); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 11ad73211538..98cf3e5380bc 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -1965,6 +1965,72 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map, 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); @@ -2165,6 +2231,32 @@ static void symbol__calc_lines(struct symbol *sym, struct map *map, 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) diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index 165845de1243..cf32cbc87930 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -281,6 +281,7 @@ int symbol__strerror_disassemble(struct symbol *sym, struct map *map, 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); @@ -291,6 +292,10 @@ 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__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, -- cgit v1.2.3 From 7f0b6fde3111aec82487662ccef5a4ebecb93381 Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 16 Mar 2018 14:33:38 -0300 Subject: perf annotate: Move the default annotate options to the library One more thing that goes from the TUI code to be used more widely, for instance it'll affect the default options used by: perf annotate --stdio2 Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-0nsz0dm0akdbo30vgja2a10e@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-annotate.c | 2 ++ tools/perf/builtin-report.c | 1 + tools/perf/builtin-top.c | 2 ++ tools/perf/ui/browser.c | 2 -- tools/perf/ui/browser.h | 1 - tools/perf/ui/browsers/annotate.c | 67 +-------------------------------------- tools/perf/util/annotate.c | 62 ++++++++++++++++++++++++++++++++++++ tools/perf/util/annotate.h | 4 +++ 8 files changed, 72 insertions(+), 69 deletions(-) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index e03f9bea9303..fd5aac3fd949 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -572,6 +572,8 @@ int cmd_annotate(int argc, const char **argv) if (ret < 0) goto out_delete; + annotation_config__init(); + symbol_conf.try_vmlinux_path = true; ret = symbol__init(&annotate.session->header.env); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 91da12975642..1a82f38671a8 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -1340,6 +1340,7 @@ repeat: symbol_conf.priv_size += sizeof(u32); symbol_conf.sort_by_name = true; } + annotation_config__init(); } if (symbol__init(&session->header.env) < 0) diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 113c298ed38b..f39bd60d2708 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -1493,6 +1493,8 @@ int cmd_top(int argc, const char **argv) if (status < 0) goto out_delete_evlist; + annotation_config__init(); + symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); if (symbol__init(NULL) < 0) return -1; diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c index 33c30325885f..9f6ce29b83b4 100644 --- a/tools/perf/ui/browser.c +++ b/tools/perf/ui/browser.c @@ -784,6 +784,4 @@ void ui_browser__init(void) struct ui_browser_colorset *c = &ui_browser__colorsets[i++]; sltt_set_color(c->colorset, c->name, c->fg, c->bg); } - - annotate_browser__init(); } diff --git a/tools/perf/ui/browser.h b/tools/perf/ui/browser.h index 9e69c6a43514..70057178ee34 100644 --- a/tools/perf/ui/browser.h +++ b/tools/perf/ui/browser.h @@ -79,5 +79,4 @@ void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int wh unsigned int ui_browser__list_head_refresh(struct ui_browser *browser); void ui_browser__init(void); -void annotate_browser__init(void); #endif /* _PERF_UI_BROWSER_H_ */ diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 74a26f4e9b06..916f237c1df8 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -9,7 +9,6 @@ #include "../../util/sort.h" #include "../../util/symbol.h" #include "../../util/evsel.h" -#include "../../util/config.h" #include "../../util/evlist.h" #include #include @@ -22,11 +21,6 @@ struct disasm_line_samples { struct sym_hist_entry he; }; -static struct annotation_options annotate_browser__opts = { - .use_offset = true, - .jump_arrows = true, -}; - struct arch; struct annotate_browser { @@ -773,12 +767,6 @@ out: int map_symbol__tui_annotate(struct map_symbol *ms, struct perf_evsel *evsel, struct hist_browser_timer *hbt) { - /* Set default value for show_total_period and show_nr_samples */ - annotate_browser__opts.show_total_period = - symbol_conf.show_total_period; - annotate_browser__opts.show_nr_samples = - symbol_conf.show_nr_samples; - return symbol__tui_annotate(ms->sym, ms->map, evsel, hbt); } @@ -819,7 +807,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, if (map->dso->annotate_warned) return -1; - err = symbol__annotate2(sym, map, evsel, &annotate_browser__opts, &browser.arch); + err = symbol__annotate2(sym, map, evsel, &annotation__default_options, &browser.arch); if (err) { char msg[BUFSIZ]; symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg)); @@ -845,56 +833,3 @@ out_free_offsets: zfree(¬es->offsets); return ret; } - -#define ANNOTATE_CFG(n) \ - { .name = #n, .value = &annotate_browser__opts.n, } - -/* - * Keep the entries sorted, they are bsearch'ed - */ -static struct annotate_config { - const char *name; - bool *value; -} annotate__configs[] = { - ANNOTATE_CFG(hide_src_code), - ANNOTATE_CFG(jump_arrows), - ANNOTATE_CFG(show_linenr), - ANNOTATE_CFG(show_nr_jumps), - ANNOTATE_CFG(show_nr_samples), - ANNOTATE_CFG(show_total_period), - ANNOTATE_CFG(use_offset), -}; - -#undef ANNOTATE_CFG - -static int annotate_config__cmp(const void *name, const void *cfgp) -{ - const struct annotate_config *cfg = cfgp; - - return strcmp(name, cfg->name); -} - -static int annotate__config(const char *var, const char *value, - void *data __maybe_unused) -{ - struct annotate_config *cfg; - const char *name; - - if (!strstarts(var, "annotate.")) - return 0; - - name = var + 9; - cfg = bsearch(name, annotate__configs, ARRAY_SIZE(annotate__configs), - sizeof(struct annotate_config), annotate_config__cmp); - - if (cfg == NULL) - ui__warning("%s variable unknown, ignoring...", var); - else - *cfg->value = perf_config_bool(name, value); - return 0; -} - -void annotate_browser__init(void) -{ - perf_config(annotate__config, NULL); -} diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 98cf3e5380bc..cfa641bc1df6 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -14,6 +14,7 @@ #include "sort.h" #include "build-id.h" #include "color.h" +#include "config.h" #include "cache.h" #include "symbol.h" #include "debug.h" @@ -41,6 +42,11 @@ #include "sane_ctype.h" +struct annotation_options annotation__default_options = { + .use_offset = true, + .jump_arrows = true, +}; + const char *disassembler_style; const char *objdump_path; static regex_t file_lineno; @@ -2500,3 +2506,59 @@ out_free_offsets: zfree(¬es->offsets); return -1; } + +#define ANNOTATION__CFG(n) \ + { .name = #n, .value = &annotation__default_options.n, } + +/* + * Keep the entries sorted, they are bsearch'ed + */ +static struct annotation_config { + const char *name; + bool *value; +} annotation__configs[] = { + ANNOTATION__CFG(hide_src_code), + ANNOTATION__CFG(jump_arrows), + ANNOTATION__CFG(show_linenr), + ANNOTATION__CFG(show_nr_jumps), + ANNOTATION__CFG(show_nr_samples), + ANNOTATION__CFG(show_total_period), + ANNOTATION__CFG(use_offset), +}; + +#undef ANNOTATION__CFG + +static int annotation_config__cmp(const void *name, const void *cfgp) +{ + const struct annotation_config *cfg = cfgp; + + return strcmp(name, cfg->name); +} + +static int annotation__config(const char *var, const char *value, + void *data __maybe_unused) +{ + struct annotation_config *cfg; + const char *name; + + if (!strstarts(var, "annotate.")) + return 0; + + name = var + 9; + cfg = bsearch(name, annotation__configs, ARRAY_SIZE(annotation__configs), + sizeof(struct annotation_config), annotation_config__cmp); + + if (cfg == NULL) + pr_debug("%s variable unknown, ignoring...", var); + else + *cfg->value = perf_config_bool(name, value); + return 0; +} + +void annotation_config__init(void) +{ + perf_config(annotation__config, NULL); + + annotation__default_options.show_total_period = symbol_conf.show_total_period; + annotation__default_options.show_nr_samples = symbol_conf.show_nr_samples; +} diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index cf32cbc87930..3faa58045b22 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -71,6 +71,8 @@ struct annotation_options { show_total_period; }; +extern struct annotation_options annotation__default_options; + struct annotation; struct sym_hist_entry { @@ -313,4 +315,6 @@ static inline int symbol__tui_annotate(struct symbol *sym __maybe_unused, extern const char *disassembler_style; +void annotation_config__init(void); + #endif /* __PERF_ANNOTATE_H */ -- cgit v1.2.3 From be316409e9819423fc965e11486e6631734520ba Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Fri, 16 Mar 2018 15:58:35 -0300 Subject: perf annotate: Introduce --ignore-vmlinux command line option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is already present in 'perf top', albeit undocumented (will fix), and is useful to use /proc/kcore instead of vmlinux and then get what is really in place, not what the kernel starts with, before alternatives, ftrace .text patching, etc, see the differences: # perf annotate --stdio2 _raw_spin_lock_irqsave _raw_spin_lock_irqsave() /lib/modules/4.16.0-rc4/build/vmlinux Event: anon group { cycles, instructions } 0.00 3.17 → callq __fentry__ 0.00 7.94 push %rbx 7.69 36.51 → callq __page_file_index mov %rax,%rbx 7.69 3.17 → callq *ffffffff82225cd0 xor %eax,%eax mov $0x1,%edx 80.77 49.21 lock cmpxchg %edx,(%rdi) test %eax,%eax ↓ jne 2b 3.85 0.00 mov %rbx,%rax pop %rbx ← retq 2b: mov %eax,%esi → callq queued_spin_lock_slowpath mov %rbx,%rax pop %rbx ← retq [root@jouet ~]# perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave _raw_spin_lock_irqsave() /proc/kcore Event: anon group { cycles, instructions } 0.00 3.17 nop 0.00 7.94 push %rbx 0.00 23.81 pushfq 7.69 12.70 pop %rax nop mov %rax,%rbx 7.69 3.17 cli nop xor %eax,%eax mov $0x1,%edx 80.77 49.21 lock cmpxchg %edx,(%rdi) test %eax,%eax ↓ jne 2b 3.85 0.00 mov %rbx,%rax pop %rbx ← retq 2b: mov %eax,%esi → callq *ffffffff820e96b0 mov %rbx,%rax pop %rbx ← retq # Diff of the output of those commands: # perf annotate --stdio2 _raw_spin_lock_irqsave > /tmp/vmlinux # perf annotate --ignore-vmlinux --stdio2 _raw_spin_lock_irqsave > /tmp/kcore # diff -y /tmp/vmlinux /tmp/kcore _raw_spin_lock_irqsave() vmlinux | _raw_spin_lock_irqsave() /proc/kcore Event: anon group { cycles, instructions } Event: anon group { cycles, instructions } 0.00 3.17 → callq __fentry__ | 0.00 3.17 nop 0.00 7.94 push %rbx 0.00 7.94 push %rbx 7.69 36.51 → callq __page_file_index | 0.00 23.81 pushfq > 7.69 12.70 pop %rax > nop mov %rax,%rbx mov %rax,%rbx 7.69 3.17 → callq *ffffffff82225cd0 | 7.69 3.17 cli > nop xor %eax,%eax xor %eax,%eax mov $0x1,%edx mov $0x1,%edx 80.77 49.21 lock cmpxchg %edx,(%rdi) 80.77 49.21 lock cmpxchg %edx,(%rdi) test %eax,%eax test %eax,%eax ↓ jne 2b ↓ jne 2b 3.85 0.00 mov %rbx,%rax 3.85 0.00 mov %rbx,%rax pop %rbx pop %rbx ← retq ← retq 2b: mov %eax,%esi 2b: mov %eax,%esi → callq queued_spin_lock_slowpath| → callq *ffffffff820e96b0 mov %rbx,%rax mov %rbx,%rax pop %rbx pop %rbx ← retq ← retq # This should be further streamlined by doing both annotations and allowing the TUI to toggle initial/current, and show the patched instructions in a slightly different color. Cc: Adrian Hunter Cc: Andi Kleen Cc: David Ahern Cc: Jin Yao Cc: Jiri Olsa Cc: Namhyung Kim Cc: Wang Nan Link: https://lkml.kernel.org/n/tip-wz8d269hxkcwaczr0r4rhyjg@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/Documentation/perf-annotate.txt | 3 +++ tools/perf/builtin-annotate.c | 2 ++ 2 files changed, 5 insertions(+) (limited to 'tools/perf/builtin-annotate.c') diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt index c29c7fc93023..749cc6055dac 100644 --- a/tools/perf/Documentation/perf-annotate.txt +++ b/tools/perf/Documentation/perf-annotate.txt @@ -55,6 +55,9 @@ OPTIONS --vmlinux=:: vmlinux pathname. +--ignore-vmlinux:: + Ignore vmlinux files. + -m:: --modules:: Load module symbols. WARNING: use only with -k and LIVE kernel. diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index fd5aac3fd949..51709a961496 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -496,6 +496,8 @@ int cmd_annotate(int argc, const char **argv) 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_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux, + "don't load vmlinux even if found"), OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, "file", "vmlinux pathname"), OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules, -- cgit v1.2.3