aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c109
1 files changed, 72 insertions, 37 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 4b91d8cf00ec..31f2e597800c 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -94,6 +94,7 @@ struct source_line {
94 94
95static char *sym_filter = NULL; 95static char *sym_filter = NULL;
96struct sym_entry *sym_filter_entry = NULL; 96struct sym_entry *sym_filter_entry = NULL;
97struct sym_entry *sym_filter_entry_sched = NULL;
97static int sym_pcnt_filter = 5; 98static int sym_pcnt_filter = 5;
98static int sym_counter = 0; 99static int sym_counter = 0;
99static int display_weighted = -1; 100static int display_weighted = -1;
@@ -201,10 +202,9 @@ static void parse_source(struct sym_entry *syme)
201 len = sym->end - sym->start; 202 len = sym->end - sym->start;
202 203
203 sprintf(command, 204 sprintf(command,
204 "objdump --start-address=0x%016Lx " 205 "objdump --start-address=%#0*Lx --stop-address=%#0*Lx -dS %s",
205 "--stop-address=0x%016Lx -dS %s", 206 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->start),
206 map->unmap_ip(map, sym->start), 207 BITS_PER_LONG / 4, map__rip_2objdump(map, sym->end), path);
207 map->unmap_ip(map, sym->end), path);
208 208
209 file = popen(command, "r"); 209 file = popen(command, "r");
210 if (!file) 210 if (!file)
@@ -215,7 +215,7 @@ static void parse_source(struct sym_entry *syme)
215 while (!feof(file)) { 215 while (!feof(file)) {
216 struct source_line *src; 216 struct source_line *src;
217 size_t dummy = 0; 217 size_t dummy = 0;
218 char *c; 218 char *c, *sep;
219 219
220 src = malloc(sizeof(struct source_line)); 220 src = malloc(sizeof(struct source_line));
221 assert(src != NULL); 221 assert(src != NULL);
@@ -234,14 +234,11 @@ static void parse_source(struct sym_entry *syme)
234 *source->lines_tail = src; 234 *source->lines_tail = src;
235 source->lines_tail = &src->next; 235 source->lines_tail = &src->next;
236 236
237 if (strlen(src->line)>8 && src->line[8] == ':') { 237 src->eip = strtoull(src->line, &sep, 16);
238 src->eip = strtoull(src->line, NULL, 16); 238 if (*sep == ':')
239 src->eip = map->unmap_ip(map, src->eip); 239 src->eip = map__objdump_2ip(map, src->eip);
240 } 240 else /* this line has no ip info (e.g. source line) */
241 if (strlen(src->line)>8 && src->line[16] == ':') { 241 src->eip = 0;
242 src->eip = strtoull(src->line, NULL, 16);
243 src->eip = map->unmap_ip(map, src->eip);
244 }
245 } 242 }
246 pclose(file); 243 pclose(file);
247out_assign: 244out_assign:
@@ -276,6 +273,9 @@ static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
276 goto out_unlock; 273 goto out_unlock;
277 274
278 for (line = syme->src->lines; line; line = line->next) { 275 for (line = syme->src->lines; line; line = line->next) {
276 /* skip lines without IP info */
277 if (line->eip == 0)
278 continue;
279 if (line->eip == ip) { 279 if (line->eip == ip) {
280 line->count[counter]++; 280 line->count[counter]++;
281 break; 281 break;
@@ -287,17 +287,20 @@ out_unlock:
287 pthread_mutex_unlock(&syme->src->lock); 287 pthread_mutex_unlock(&syme->src->lock);
288} 288}
289 289
290#define PATTERN_LEN (BITS_PER_LONG / 4 + 2)
291
290static void lookup_sym_source(struct sym_entry *syme) 292static void lookup_sym_source(struct sym_entry *syme)
291{ 293{
292 struct symbol *symbol = sym_entry__symbol(syme); 294 struct symbol *symbol = sym_entry__symbol(syme);
293 struct source_line *line; 295 struct source_line *line;
294 char pattern[PATH_MAX]; 296 char pattern[PATTERN_LEN + 1];
295 297
296 sprintf(pattern, "<%s>:", symbol->name); 298 sprintf(pattern, "%0*Lx <", BITS_PER_LONG / 4,
299 map__rip_2objdump(syme->map, symbol->start));
297 300
298 pthread_mutex_lock(&syme->src->lock); 301 pthread_mutex_lock(&syme->src->lock);
299 for (line = syme->src->lines; line; line = line->next) { 302 for (line = syme->src->lines; line; line = line->next) {
300 if (strstr(line->line, pattern)) { 303 if (memcmp(line->line, pattern, PATTERN_LEN) == 0) {
301 syme->src->source = line; 304 syme->src->source = line;
302 break; 305 break;
303 } 306 }
@@ -667,7 +670,7 @@ static void prompt_symbol(struct sym_entry **target, const char *msg)
667 } 670 }
668 671
669 if (!found) { 672 if (!found) {
670 fprintf(stderr, "Sorry, %s is not active.\n", sym_filter); 673 fprintf(stderr, "Sorry, %s is not active.\n", buf);
671 sleep(1); 674 sleep(1);
672 return; 675 return;
673 } else 676 } else
@@ -695,11 +698,9 @@ static void print_mapped_keys(void)
695 698
696 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 699 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
697 700
698 if (symbol_conf.vmlinux_name) { 701 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); 702 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
700 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 703 fprintf(stdout, "\t[S] stop annotation.\n");
701 fprintf(stdout, "\t[S] stop annotation.\n");
702 }
703 704
704 if (nr_counters > 1) 705 if (nr_counters > 1)
705 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 706 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
@@ -725,14 +726,13 @@ static int key_mapped(int c)
725 case 'Q': 726 case 'Q':
726 case 'K': 727 case 'K':
727 case 'U': 728 case 'U':
729 case 'F':
730 case 's':
731 case 'S':
728 return 1; 732 return 1;
729 case 'E': 733 case 'E':
730 case 'w': 734 case 'w':
731 return nr_counters > 1 ? 1 : 0; 735 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: 736 default:
737 break; 737 break;
738 } 738 }
@@ -910,8 +910,12 @@ static int symbol_filter(struct map *map, struct symbol *sym)
910 syme = symbol__priv(sym); 910 syme = symbol__priv(sym);
911 syme->map = map; 911 syme->map = map;
912 syme->src = NULL; 912 syme->src = NULL;
913 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 913
914 sym_filter_entry = syme; 914 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) {
915 /* schedule initial sym_filter_entry setup */
916 sym_filter_entry_sched = syme;
917 sym_filter = NULL;
918 }
915 919
916 for (i = 0; skip_symbols[i]; i++) { 920 for (i = 0; skip_symbols[i]; i++) {
917 if (!strcmp(skip_symbols[i], name)) { 921 if (!strcmp(skip_symbols[i], name)) {
@@ -934,8 +938,11 @@ static void event__process_sample(const event_t *self,
934 struct addr_location al; 938 struct addr_location al;
935 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 939 u8 origin = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
936 940
941 ++samples;
942
937 switch (origin) { 943 switch (origin) {
938 case PERF_RECORD_MISC_USER: 944 case PERF_RECORD_MISC_USER:
945 ++userspace_samples;
939 if (hide_user_symbols) 946 if (hide_user_symbols)
940 return; 947 return;
941 break; 948 break;
@@ -948,9 +955,38 @@ static void event__process_sample(const event_t *self,
948 } 955 }
949 956
950 if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 || 957 if (event__preprocess_sample(self, session, &al, symbol_filter) < 0 ||
951 al.sym == NULL || al.filtered) 958 al.filtered)
952 return; 959 return;
953 960
961 if (al.sym == NULL) {
962 /*
963 * As we do lazy loading of symtabs we only will know if the
964 * specified vmlinux file is invalid when we actually have a
965 * hit in kernel space and then try to load it. So if we get
966 * here and there are _no_ symbols in the DSO backing the
967 * kernel map, bail out.
968 *
969 * We may never get here, for instance, if we use -K/
970 * --hide-kernel-symbols, even if the user specifies an
971 * invalid --vmlinux ;-)
972 */
973 if (al.map == session->vmlinux_maps[MAP__FUNCTION] &&
974 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
975 pr_err("The %s file can't be used\n",
976 symbol_conf.vmlinux_name);
977 exit(1);
978 }
979
980 return;
981 }
982
983 /* let's see, whether we need to install initial sym_filter_entry */
984 if (sym_filter_entry_sched) {
985 sym_filter_entry = sym_filter_entry_sched;
986 sym_filter_entry_sched = NULL;
987 parse_source(sym_filter_entry);
988 }
989
954 syme = symbol__priv(al.sym); 990 syme = symbol__priv(al.sym);
955 if (!syme->skip) { 991 if (!syme->skip) {
956 syme->count[counter]++; 992 syme->count[counter]++;
@@ -960,9 +996,6 @@ static void event__process_sample(const event_t *self,
960 if (list_empty(&syme->node) || !syme->node.next) 996 if (list_empty(&syme->node) || !syme->node.next)
961 __list_insert_active_sym(syme); 997 __list_insert_active_sym(syme);
962 pthread_mutex_unlock(&active_symbols_lock); 998 pthread_mutex_unlock(&active_symbols_lock);
963 if (origin == PERF_RECORD_MISC_USER)
964 ++userspace_samples;
965 ++samples;
966 } 999 }
967} 1000}
968 1001
@@ -975,6 +1008,10 @@ static int event__process(event_t *event, struct perf_session *session)
975 case PERF_RECORD_MMAP: 1008 case PERF_RECORD_MMAP:
976 event__process_mmap(event, session); 1009 event__process_mmap(event, session);
977 break; 1010 break;
1011 case PERF_RECORD_FORK:
1012 case PERF_RECORD_EXIT:
1013 event__process_task(event, session);
1014 break;
978 default: 1015 default:
979 break; 1016 break;
980 } 1017 }
@@ -1244,7 +1281,7 @@ static const struct option options[] = {
1244 OPT_BOOLEAN('i', "inherit", &inherit, 1281 OPT_BOOLEAN('i', "inherit", &inherit,
1245 "child tasks inherit counters"), 1282 "child tasks inherit counters"),
1246 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name", 1283 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
1247 "symbol to annotate - requires -k option"), 1284 "symbol to annotate"),
1248 OPT_BOOLEAN('z', "zero", &zero, 1285 OPT_BOOLEAN('z', "zero", &zero,
1249 "zero history across updates"), 1286 "zero history across updates"),
1250 OPT_INTEGER('F', "freq", &freq, 1287 OPT_INTEGER('F', "freq", &freq,
@@ -1280,16 +1317,14 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1280 1317
1281 symbol_conf.priv_size = (sizeof(struct sym_entry) + 1318 symbol_conf.priv_size = (sizeof(struct sym_entry) +
1282 (nr_counters + 1) * sizeof(unsigned long)); 1319 (nr_counters + 1) * sizeof(unsigned long));
1283 if (symbol_conf.vmlinux_name == NULL) 1320
1284 symbol_conf.try_vmlinux_path = true; 1321 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1285 if (symbol__init() < 0) 1322 if (symbol__init() < 0)
1286 return -1; 1323 return -1;
1287 1324
1288 if (delay_secs < 1) 1325 if (delay_secs < 1)
1289 delay_secs = 1; 1326 delay_secs = 1;
1290 1327
1291 parse_source(sym_filter_entry);
1292
1293 /* 1328 /*
1294 * User specified count overrides default frequency. 1329 * User specified count overrides default frequency.
1295 */ 1330 */