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 | |
| 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')
| -rw-r--r-- | tools/perf/Documentation/perf-top.txt | 2 | ||||
| -rw-r--r-- | tools/perf/builtin-top.c | 39 |
2 files changed, 24 insertions, 17 deletions
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index 4a7d558dc309..785b9fc32a46 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
| @@ -74,7 +74,7 @@ OPTIONS | |||
| 74 | 74 | ||
| 75 | -s <symbol>:: | 75 | -s <symbol>:: |
| 76 | --sym-annotate=<symbol>:: | 76 | --sym-annotate=<symbol>:: |
| 77 | Annotate this symbol. Requires -k option. | 77 | Annotate this symbol. |
| 78 | 78 | ||
| 79 | -v:: | 79 | -v:: |
| 80 | --verbose:: | 80 | --verbose:: |
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 | */ |
