diff options
author | Kirill Smelkov <kirr@landau.phys.spbu.ru> | 2010-02-03 13:52:08 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-02-04 03:33:28 -0500 |
commit | 6cff0e8dbaa4d5d822a814e5028683d7e71c3291 (patch) | |
tree | c18d3d87b33b0d22b73990e0f7168b40149c00c5 /tools/perf/builtin-top.c | |
parent | 7a2b6209863626cf8362e5ff4653491558f91e67 (diff) |
perf top: Teach it to autolocate vmlinux
By relying on logic in dso__load_kernel_sym(), we can
automatically load vmlinux.
The only thing which needs to be adjusted, is how --sym-annotate
option is handled - now we can't rely on vmlinux been loaded
until full successful pass of dso__load_vmlinux(), but that's
not the case if we'll do sym_filter_entry setup in
symbol_filter().
So move this step right after event__process_sample() where we
know the whole dso__load_kernel_sym() pass is done.
By the way, though conceptually similar `perf top` still can't
annotate userspace - see next patches with fixes.
Signed-off-by: Kirill Smelkov <kirr@landau.phys.spbu.ru>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <1265223128-11786-9-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 1fc018e048e1..83c09c8f28ed 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -94,6 +94,7 @@ struct source_line { | |||
94 | 94 | ||
95 | static char *sym_filter = NULL; | 95 | static char *sym_filter = NULL; |
96 | struct sym_entry *sym_filter_entry = NULL; | 96 | struct sym_entry *sym_filter_entry = NULL; |
97 | struct sym_entry *sym_filter_entry_sched = NULL; | ||
97 | static int sym_pcnt_filter = 5; | 98 | static int sym_pcnt_filter = 5; |
98 | static int sym_counter = 0; | 99 | static int sym_counter = 0; |
99 | static int display_weighted = -1; | 100 | static int display_weighted = -1; |
@@ -695,11 +696,9 @@ static void print_mapped_keys(void) | |||
695 | 696 | ||
696 | fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); | 697 | fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); |
697 | 698 | ||
698 | if (symbol_conf.vmlinux_name) { | 699 | fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); |
699 | fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); | 700 | fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); |
700 | fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); | 701 | fprintf(stdout, "\t[S] stop annotation.\n"); |
701 | fprintf(stdout, "\t[S] stop annotation.\n"); | ||
702 | } | ||
703 | 702 | ||
704 | if (nr_counters > 1) | 703 | if (nr_counters > 1) |
705 | fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); | 704 | fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); |
@@ -725,14 +724,13 @@ static int key_mapped(int c) | |||
725 | case 'Q': | 724 | case 'Q': |
726 | case 'K': | 725 | case 'K': |
727 | case 'U': | 726 | case 'U': |
727 | case 'F': | ||
728 | case 's': | ||
729 | case 'S': | ||
728 | return 1; | 730 | return 1; |
729 | case 'E': | 731 | case 'E': |
730 | case 'w': | 732 | case 'w': |
731 | return nr_counters > 1 ? 1 : 0; | 733 | return nr_counters > 1 ? 1 : 0; |
732 | case 'F': | ||
733 | case 's': | ||
734 | case 'S': | ||
735 | return symbol_conf.vmlinux_name ? 1 : 0; | ||
736 | default: | 734 | default: |
737 | break; | 735 | break; |
738 | } | 736 | } |
@@ -910,8 +908,12 @@ static int symbol_filter(struct map *map, struct symbol *sym) | |||
910 | syme = symbol__priv(sym); | 908 | syme = symbol__priv(sym); |
911 | syme->map = map; | 909 | syme->map = map; |
912 | syme->src = NULL; | 910 | syme->src = NULL; |
913 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) | 911 | |
914 | sym_filter_entry = syme; | 912 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) { |
913 | /* schedule initial sym_filter_entry setup */ | ||
914 | sym_filter_entry_sched = syme; | ||
915 | sym_filter = NULL; | ||
916 | } | ||
915 | 917 | ||
916 | for (i = 0; skip_symbols[i]; i++) { | 918 | for (i = 0; skip_symbols[i]; i++) { |
917 | if (!strcmp(skip_symbols[i], name)) { | 919 | if (!strcmp(skip_symbols[i], name)) { |
@@ -976,6 +978,13 @@ static void event__process_sample(const event_t *self, | |||
976 | return; | 978 | return; |
977 | } | 979 | } |
978 | 980 | ||
981 | /* let's see, whether we need to install initial sym_filter_entry */ | ||
982 | if (sym_filter_entry_sched) { | ||
983 | sym_filter_entry = sym_filter_entry_sched; | ||
984 | sym_filter_entry_sched = NULL; | ||
985 | parse_source(sym_filter_entry); | ||
986 | } | ||
987 | |||
979 | syme = symbol__priv(al.sym); | 988 | syme = symbol__priv(al.sym); |
980 | if (!syme->skip) { | 989 | if (!syme->skip) { |
981 | syme->count[counter]++; | 990 | syme->count[counter]++; |
@@ -1270,7 +1279,7 @@ static const struct option options[] = { | |||
1270 | OPT_BOOLEAN('i', "inherit", &inherit, | 1279 | OPT_BOOLEAN('i', "inherit", &inherit, |
1271 | "child tasks inherit counters"), | 1280 | "child tasks inherit counters"), |
1272 | OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", | 1281 | OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", |
1273 | "symbol to annotate - requires -k option"), | 1282 | "symbol to annotate"), |
1274 | OPT_BOOLEAN('z', "zero", &zero, | 1283 | OPT_BOOLEAN('z', "zero", &zero, |
1275 | "zero history across updates"), | 1284 | "zero history across updates"), |
1276 | OPT_INTEGER('F', "freq", &freq, | 1285 | OPT_INTEGER('F', "freq", &freq, |
@@ -1306,16 +1315,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1306 | 1315 | ||
1307 | symbol_conf.priv_size = (sizeof(struct sym_entry) + | 1316 | symbol_conf.priv_size = (sizeof(struct sym_entry) + |
1308 | (nr_counters + 1) * sizeof(unsigned long)); | 1317 | (nr_counters + 1) * sizeof(unsigned long)); |
1309 | if (symbol_conf.vmlinux_name == NULL) | 1318 | |
1310 | symbol_conf.try_vmlinux_path = true; | 1319 | symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); |
1311 | if (symbol__init() < 0) | 1320 | if (symbol__init() < 0) |
1312 | return -1; | 1321 | return -1; |
1313 | 1322 | ||
1314 | if (delay_secs < 1) | 1323 | if (delay_secs < 1) |
1315 | delay_secs = 1; | 1324 | delay_secs = 1; |
1316 | 1325 | ||
1317 | parse_source(sym_filter_entry); | ||
1318 | |||
1319 | /* | 1326 | /* |
1320 | * User specified count overrides default frequency. | 1327 | * User specified count overrides default frequency. |
1321 | */ | 1328 | */ |