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.c625
1 files changed, 554 insertions, 71 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index cf0d21f1ae10..7de28ce9ca26 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -23,7 +23,7 @@
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/util.h" 25#include "util/util.h"
26#include "util/rbtree.h" 26#include <linux/rbtree.h>
27#include "util/parse-options.h" 27#include "util/parse-options.h"
28#include "util/parse-events.h" 28#include "util/parse-events.h"
29 29
@@ -31,6 +31,8 @@
31#include <fcntl.h> 31#include <fcntl.h>
32 32
33#include <stdio.h> 33#include <stdio.h>
34#include <termios.h>
35#include <unistd.h>
34 36
35#include <errno.h> 37#include <errno.h>
36#include <time.h> 38#include <time.h>
@@ -54,10 +56,11 @@ static int system_wide = 0;
54 56
55static int default_interval = 100000; 57static int default_interval = 100000;
56 58
57static u64 count_filter = 5; 59static int count_filter = 5;
58static int print_entries = 15; 60static int print_entries = 15;
59 61
60static int target_pid = -1; 62static int target_pid = -1;
63static int inherit = 0;
61static int profile_cpu = -1; 64static int profile_cpu = -1;
62static int nr_cpus = 0; 65static int nr_cpus = 0;
63static unsigned int realtime_prio = 0; 66static unsigned int realtime_prio = 0;
@@ -66,16 +69,30 @@ static unsigned int page_size;
66static unsigned int mmap_pages = 16; 69static unsigned int mmap_pages = 16;
67static int freq = 0; 70static int freq = 0;
68static int verbose = 0; 71static int verbose = 0;
69 72static char *vmlinux = NULL;
70static char *sym_filter;
71static unsigned long filter_start;
72static unsigned long filter_end;
73 73
74static int delay_secs = 2; 74static int delay_secs = 2;
75static int zero; 75static int zero;
76static int dump_symtab; 76static int dump_symtab;
77 77
78/* 78/*
79 * Source
80 */
81
82struct source_line {
83 u64 eip;
84 unsigned long count[MAX_COUNTERS];
85 char *line;
86 struct source_line *next;
87};
88
89static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5;
92static int sym_counter = 0;
93static int display_weighted = -1;
94
95/*
79 * Symbols 96 * Symbols
80 */ 97 */
81 98
@@ -89,9 +106,237 @@ struct sym_entry {
89 unsigned long snap_count; 106 unsigned long snap_count;
90 double weight; 107 double weight;
91 int skip; 108 int skip;
109 struct source_line *source;
110 struct source_line *lines;
111 struct source_line **lines_tail;
112 pthread_mutex_t source_lock;
92}; 113};
93 114
94struct sym_entry *sym_filter_entry; 115/*
116 * Source functions
117 */
118
119static void parse_source(struct sym_entry *syme)
120{
121 struct symbol *sym;
122 struct module *module;
123 struct section *section = NULL;
124 FILE *file;
125 char command[PATH_MAX*2], *path = vmlinux;
126 u64 start, end, len;
127
128 if (!syme)
129 return;
130
131 if (syme->lines) {
132 pthread_mutex_lock(&syme->source_lock);
133 goto out_assign;
134 }
135
136 sym = (struct symbol *)(syme + 1);
137 module = sym->module;
138
139 if (module)
140 path = module->path;
141 if (!path)
142 return;
143
144 start = sym->obj_start;
145 if (!start)
146 start = sym->start;
147
148 if (module) {
149 section = module->sections->find_section(module->sections, ".text");
150 if (section)
151 start -= section->vma;
152 }
153
154 end = start + sym->end - sym->start + 1;
155 len = sym->end - sym->start;
156
157 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path);
158
159 file = popen(command, "r");
160 if (!file)
161 return;
162
163 pthread_mutex_lock(&syme->source_lock);
164 syme->lines_tail = &syme->lines;
165 while (!feof(file)) {
166 struct source_line *src;
167 size_t dummy = 0;
168 char *c;
169
170 src = malloc(sizeof(struct source_line));
171 assert(src != NULL);
172 memset(src, 0, sizeof(struct source_line));
173
174 if (getline(&src->line, &dummy, file) < 0)
175 break;
176 if (!src->line)
177 break;
178
179 c = strchr(src->line, '\n');
180 if (c)
181 *c = 0;
182
183 src->next = NULL;
184 *syme->lines_tail = src;
185 syme->lines_tail = &src->next;
186
187 if (strlen(src->line)>8 && src->line[8] == ':') {
188 src->eip = strtoull(src->line, NULL, 16);
189 if (section)
190 src->eip += section->vma;
191 }
192 if (strlen(src->line)>8 && src->line[16] == ':') {
193 src->eip = strtoull(src->line, NULL, 16);
194 if (section)
195 src->eip += section->vma;
196 }
197 }
198 pclose(file);
199out_assign:
200 sym_filter_entry = syme;
201 pthread_mutex_unlock(&syme->source_lock);
202}
203
204static void __zero_source_counters(struct sym_entry *syme)
205{
206 int i;
207 struct source_line *line;
208
209 line = syme->lines;
210 while (line) {
211 for (i = 0; i < nr_counters; i++)
212 line->count[i] = 0;
213 line = line->next;
214 }
215}
216
217static void record_precise_ip(struct sym_entry *syme, int counter, u64 ip)
218{
219 struct source_line *line;
220
221 if (syme != sym_filter_entry)
222 return;
223
224 if (pthread_mutex_trylock(&syme->source_lock))
225 return;
226
227 if (!syme->source)
228 goto out_unlock;
229
230 for (line = syme->lines; line; line = line->next) {
231 if (line->eip == ip) {
232 line->count[counter]++;
233 break;
234 }
235 if (line->eip > ip)
236 break;
237 }
238out_unlock:
239 pthread_mutex_unlock(&syme->source_lock);
240}
241
242static void lookup_sym_source(struct sym_entry *syme)
243{
244 struct symbol *symbol = (struct symbol *)(syme + 1);
245 struct source_line *line;
246 char pattern[PATH_MAX];
247 char *idx;
248
249 sprintf(pattern, "<%s>:", symbol->name);
250
251 if (symbol->module) {
252 idx = strstr(pattern, "\t");
253 if (idx)
254 *idx = 0;
255 }
256
257 pthread_mutex_lock(&syme->source_lock);
258 for (line = syme->lines; line; line = line->next) {
259 if (strstr(line->line, pattern)) {
260 syme->source = line;
261 break;
262 }
263 }
264 pthread_mutex_unlock(&syme->source_lock);
265}
266
267static void show_lines(struct source_line *queue, int count, int total)
268{
269 int i;
270 struct source_line *line;
271
272 line = queue;
273 for (i = 0; i < count; i++) {
274 float pcnt = 100.0*(float)line->count[sym_counter]/(float)total;
275
276 printf("%8li %4.1f%%\t%s\n", line->count[sym_counter], pcnt, line->line);
277 line = line->next;
278 }
279}
280
281#define TRACE_COUNT 3
282
283static void show_details(struct sym_entry *syme)
284{
285 struct symbol *symbol;
286 struct source_line *line;
287 struct source_line *line_queue = NULL;
288 int displayed = 0;
289 int line_queue_count = 0, total = 0, more = 0;
290
291 if (!syme)
292 return;
293
294 if (!syme->source)
295 lookup_sym_source(syme);
296
297 if (!syme->source)
298 return;
299
300 symbol = (struct symbol *)(syme + 1);
301 printf("Showing %s for %s\n", event_name(sym_counter), symbol->name);
302 printf(" Events Pcnt (>=%d%%)\n", sym_pcnt_filter);
303
304 pthread_mutex_lock(&syme->source_lock);
305 line = syme->source;
306 while (line) {
307 total += line->count[sym_counter];
308 line = line->next;
309 }
310
311 line = syme->source;
312 while (line) {
313 float pcnt = 0.0;
314
315 if (!line_queue_count)
316 line_queue = line;
317 line_queue_count++;
318
319 if (line->count[sym_counter])
320 pcnt = 100.0 * line->count[sym_counter] / (float)total;
321 if (pcnt >= (float)sym_pcnt_filter) {
322 if (displayed <= print_entries)
323 show_lines(line_queue, line_queue_count, total);
324 else more++;
325 displayed += line_queue_count;
326 line_queue_count = 0;
327 line_queue = NULL;
328 } else if (line_queue_count > TRACE_COUNT) {
329 line_queue = line_queue->next;
330 line_queue_count--;
331 }
332
333 line->count[sym_counter] = zero ? 0 : line->count[sym_counter] * 7 / 8;
334 line = line->next;
335 }
336 pthread_mutex_unlock(&syme->source_lock);
337 if (more)
338 printf("%d lines not displayed, maybe increase display entries [e]\n", more);
339}
95 340
96struct dso *kernel_dso; 341struct dso *kernel_dso;
97 342
@@ -110,6 +355,9 @@ static double sym_weight(const struct sym_entry *sym)
110 double weight = sym->snap_count; 355 double weight = sym->snap_count;
111 int counter; 356 int counter;
112 357
358 if (!display_weighted)
359 return weight;
360
113 for (counter = 1; counter < nr_counters-1; counter++) 361 for (counter = 1; counter < nr_counters-1; counter++)
114 weight *= sym->count[counter]; 362 weight *= sym->count[counter];
115 363
@@ -157,7 +405,7 @@ static void rb_insert_active_sym(struct rb_root *tree, struct sym_entry *se)
157static void print_sym_table(void) 405static void print_sym_table(void)
158{ 406{
159 int printed = 0, j; 407 int printed = 0, j;
160 int counter; 408 int counter, snap = !display_weighted ? sym_counter : 0;
161 float samples_per_sec = samples/delay_secs; 409 float samples_per_sec = samples/delay_secs;
162 float ksamples_per_sec = (samples-userspace_samples)/delay_secs; 410 float ksamples_per_sec = (samples-userspace_samples)/delay_secs;
163 float sum_ksamples = 0.0; 411 float sum_ksamples = 0.0;
@@ -173,7 +421,7 @@ static void print_sym_table(void)
173 pthread_mutex_unlock(&active_symbols_lock); 421 pthread_mutex_unlock(&active_symbols_lock);
174 422
175 list_for_each_entry_safe_from(syme, n, &active_symbols, node) { 423 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
176 syme->snap_count = syme->count[0]; 424 syme->snap_count = syme->count[snap];
177 if (syme->snap_count != 0) { 425 if (syme->snap_count != 0) {
178 syme->weight = sym_weight(syme); 426 syme->weight = sym_weight(syme);
179 rb_insert_active_sym(&tmp, syme); 427 rb_insert_active_sym(&tmp, syme);
@@ -193,7 +441,7 @@ static void print_sym_table(void)
193 samples_per_sec, 441 samples_per_sec,
194 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec))); 442 100.0 - (100.0*((samples_per_sec-ksamples_per_sec)/samples_per_sec)));
195 443
196 if (nr_counters == 1) { 444 if (nr_counters == 1 || !display_weighted) {
197 printf("%Ld", (u64)attrs[0].sample_period); 445 printf("%Ld", (u64)attrs[0].sample_period);
198 if (freq) 446 if (freq)
199 printf("Hz "); 447 printf("Hz ");
@@ -201,7 +449,9 @@ static void print_sym_table(void)
201 printf(" "); 449 printf(" ");
202 } 450 }
203 451
204 for (counter = 0; counter < nr_counters; counter++) { 452 if (!display_weighted)
453 printf("%s", event_name(sym_counter));
454 else for (counter = 0; counter < nr_counters; counter++) {
205 if (counter) 455 if (counter)
206 printf("/"); 456 printf("/");
207 457
@@ -226,6 +476,11 @@ static void print_sym_table(void)
226 476
227 printf("------------------------------------------------------------------------------\n\n"); 477 printf("------------------------------------------------------------------------------\n\n");
228 478
479 if (sym_filter_entry) {
480 show_details(sym_filter_entry);
481 return;
482 }
483
229 if (nr_counters == 1) 484 if (nr_counters == 1)
230 printf(" samples pcnt"); 485 printf(" samples pcnt");
231 else 486 else
@@ -238,59 +493,300 @@ static void print_sym_table(void)
238 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) { 493 for (nd = rb_first(&tmp); nd; nd = rb_next(nd)) {
239 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node); 494 struct sym_entry *syme = rb_entry(nd, struct sym_entry, rb_node);
240 struct symbol *sym = (struct symbol *)(syme + 1); 495 struct symbol *sym = (struct symbol *)(syme + 1);
241 char *color = PERF_COLOR_NORMAL;
242 double pcnt; 496 double pcnt;
243 497
244 if (++printed > print_entries || syme->snap_count < count_filter) 498 if (++printed > print_entries || (int)syme->snap_count < count_filter)
245 continue; 499 continue;
246 500
247 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) / 501 pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
248 sum_ksamples)); 502 sum_ksamples));
249 503
250 /* 504 if (nr_counters == 1 || !display_weighted)
251 * We color high-overhead entries in red, mid-overhead
252 * entries in green - and keep the low overhead places
253 * normal:
254 */
255 if (pcnt >= 5.0) {
256 color = PERF_COLOR_RED;
257 } else {
258 if (pcnt >= 0.5)
259 color = PERF_COLOR_GREEN;
260 }
261
262 if (nr_counters == 1)
263 printf("%20.2f - ", syme->weight); 505 printf("%20.2f - ", syme->weight);
264 else 506 else
265 printf("%9.1f %10ld - ", syme->weight, syme->snap_count); 507 printf("%9.1f %10ld - ", syme->weight, syme->snap_count);
266 508
267 color_fprintf(stdout, color, "%4.1f%%", pcnt); 509 percent_color_fprintf(stdout, "%4.1f%%", pcnt);
268 printf(" - %016llx : %s\n", sym->start, sym->name); 510 printf(" - %016llx : %s", sym->start, sym->name);
511 if (sym->module)
512 printf("\t[%s]", sym->module->name);
513 printf("\n");
514 }
515}
516
517static void prompt_integer(int *target, const char *msg)
518{
519 char *buf = malloc(0), *p;
520 size_t dummy = 0;
521 int tmp;
522
523 fprintf(stdout, "\n%s: ", msg);
524 if (getline(&buf, &dummy, stdin) < 0)
525 return;
526
527 p = strchr(buf, '\n');
528 if (p)
529 *p = 0;
530
531 p = buf;
532 while(*p) {
533 if (!isdigit(*p))
534 goto out_free;
535 p++;
536 }
537 tmp = strtoul(buf, NULL, 10);
538 *target = tmp;
539out_free:
540 free(buf);
541}
542
543static void prompt_percent(int *target, const char *msg)
544{
545 int tmp = 0;
546
547 prompt_integer(&tmp, msg);
548 if (tmp >= 0 && tmp <= 100)
549 *target = tmp;
550}
551
552static void prompt_symbol(struct sym_entry **target, const char *msg)
553{
554 char *buf = malloc(0), *p;
555 struct sym_entry *syme = *target, *n, *found = NULL;
556 size_t dummy = 0;
557
558 /* zero counters of active symbol */
559 if (syme) {
560 pthread_mutex_lock(&syme->source_lock);
561 __zero_source_counters(syme);
562 *target = NULL;
563 pthread_mutex_unlock(&syme->source_lock);
564 }
565
566 fprintf(stdout, "\n%s: ", msg);
567 if (getline(&buf, &dummy, stdin) < 0)
568 goto out_free;
569
570 p = strchr(buf, '\n');
571 if (p)
572 *p = 0;
573
574 pthread_mutex_lock(&active_symbols_lock);
575 syme = list_entry(active_symbols.next, struct sym_entry, node);
576 pthread_mutex_unlock(&active_symbols_lock);
577
578 list_for_each_entry_safe_from(syme, n, &active_symbols, node) {
579 struct symbol *sym = (struct symbol *)(syme + 1);
580
581 if (!strcmp(buf, sym->name)) {
582 found = syme;
583 break;
584 }
269 } 585 }
586
587 if (!found) {
588 fprintf(stderr, "Sorry, %s is not active.\n", sym_filter);
589 sleep(1);
590 return;
591 } else
592 parse_source(found);
593
594out_free:
595 free(buf);
270} 596}
271 597
272static void *display_thread(void *arg) 598static void print_mapped_keys(void)
599{
600 char *name = NULL;
601
602 if (sym_filter_entry) {
603 struct symbol *sym = (struct symbol *)(sym_filter_entry+1);
604 name = sym->name;
605 }
606
607 fprintf(stdout, "\nMapped keys:\n");
608 fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs);
609 fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
610
611 if (nr_counters > 1)
612 fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter));
613
614 fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
615
616 if (vmlinux) {
617 fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter);
618 fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
619 fprintf(stdout, "\t[S] stop annotation.\n");
620 }
621
622 if (nr_counters > 1)
623 fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
624
625 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0);
626 fprintf(stdout, "\t[qQ] quit.\n");
627}
628
629static int key_mapped(int c)
630{
631 switch (c) {
632 case 'd':
633 case 'e':
634 case 'f':
635 case 'z':
636 case 'q':
637 case 'Q':
638 return 1;
639 case 'E':
640 case 'w':
641 return nr_counters > 1 ? 1 : 0;
642 case 'F':
643 case 's':
644 case 'S':
645 return vmlinux ? 1 : 0;
646 }
647
648 return 0;
649}
650
651static void handle_keypress(int c)
652{
653 if (!key_mapped(c)) {
654 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
655 struct termios tc, save;
656
657 print_mapped_keys();
658 fprintf(stdout, "\nEnter selection, or unmapped key to continue: ");
659 fflush(stdout);
660
661 tcgetattr(0, &save);
662 tc = save;
663 tc.c_lflag &= ~(ICANON | ECHO);
664 tc.c_cc[VMIN] = 0;
665 tc.c_cc[VTIME] = 0;
666 tcsetattr(0, TCSANOW, &tc);
667
668 poll(&stdin_poll, 1, -1);
669 c = getc(stdin);
670
671 tcsetattr(0, TCSAFLUSH, &save);
672 if (!key_mapped(c))
673 return;
674 }
675
676 switch (c) {
677 case 'd':
678 prompt_integer(&delay_secs, "Enter display delay");
679 break;
680 case 'e':
681 prompt_integer(&print_entries, "Enter display entries (lines)");
682 break;
683 case 'E':
684 if (nr_counters > 1) {
685 int i;
686
687 fprintf(stderr, "\nAvailable events:");
688 for (i = 0; i < nr_counters; i++)
689 fprintf(stderr, "\n\t%d %s", i, event_name(i));
690
691 prompt_integer(&sym_counter, "Enter details event counter");
692
693 if (sym_counter >= nr_counters) {
694 fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(0));
695 sym_counter = 0;
696 sleep(1);
697 }
698 } else sym_counter = 0;
699 break;
700 case 'f':
701 prompt_integer(&count_filter, "Enter display event count filter");
702 break;
703 case 'F':
704 prompt_percent(&sym_pcnt_filter, "Enter details display event filter (percent)");
705 break;
706 case 'q':
707 case 'Q':
708 printf("exiting.\n");
709 exit(0);
710 case 's':
711 prompt_symbol(&sym_filter_entry, "Enter details symbol");
712 break;
713 case 'S':
714 if (!sym_filter_entry)
715 break;
716 else {
717 struct sym_entry *syme = sym_filter_entry;
718
719 pthread_mutex_lock(&syme->source_lock);
720 sym_filter_entry = NULL;
721 __zero_source_counters(syme);
722 pthread_mutex_unlock(&syme->source_lock);
723 }
724 break;
725 case 'w':
726 display_weighted = ~display_weighted;
727 break;
728 case 'z':
729 zero = ~zero;
730 break;
731 }
732}
733
734static void *display_thread(void *arg __used)
273{ 735{
274 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 736 struct pollfd stdin_poll = { .fd = 0, .events = POLLIN };
275 int delay_msecs = delay_secs * 1000; 737 struct termios tc, save;
738 int delay_msecs, c;
276 739
277 printf("PerfTop refresh period: %d seconds\n", delay_secs); 740 tcgetattr(0, &save);
741 tc = save;
742 tc.c_lflag &= ~(ICANON | ECHO);
743 tc.c_cc[VMIN] = 0;
744 tc.c_cc[VTIME] = 0;
745
746repeat:
747 delay_msecs = delay_secs * 1000;
748 tcsetattr(0, TCSANOW, &tc);
749 /* trash return*/
750 getc(stdin);
278 751
279 do { 752 do {
280 print_sym_table(); 753 print_sym_table();
281 } while (!poll(&stdin_poll, 1, delay_msecs) == 1); 754 } while (!poll(&stdin_poll, 1, delay_msecs) == 1);
282 755
283 printf("key pressed - exiting.\n"); 756 c = getc(stdin);
284 exit(0); 757 tcsetattr(0, TCSAFLUSH, &save);
758
759 handle_keypress(c);
760 goto repeat;
285 761
286 return NULL; 762 return NULL;
287} 763}
288 764
765/* Tag samples to be skipped. */
766static const char *skip_symbols[] = {
767 "default_idle",
768 "cpu_idle",
769 "enter_idle",
770 "exit_idle",
771 "mwait_idle",
772 "mwait_idle_with_hints",
773 "ppc64_runlatch_off",
774 "pseries_dedicated_idle_sleep",
775 NULL
776};
777
289static int symbol_filter(struct dso *self, struct symbol *sym) 778static int symbol_filter(struct dso *self, struct symbol *sym)
290{ 779{
291 static int filter_match;
292 struct sym_entry *syme; 780 struct sym_entry *syme;
293 const char *name = sym->name; 781 const char *name = sym->name;
782 int i;
783
784 /*
785 * ppc64 uses function descriptors and appends a '.' to the
786 * start of every instruction address. Remove it.
787 */
788 if (name[0] == '.')
789 name++;
294 790
295 if (!strcmp(name, "_text") || 791 if (!strcmp(name, "_text") ||
296 !strcmp(name, "_etext") || 792 !strcmp(name, "_etext") ||
@@ -302,37 +798,17 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
302 return 1; 798 return 1;
303 799
304 syme = dso__sym_priv(self, sym); 800 syme = dso__sym_priv(self, sym);
305 /* Tag samples to be skipped. */ 801 pthread_mutex_init(&syme->source_lock, NULL);
306 if (!strcmp("default_idle", name) || 802 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
307 !strcmp("cpu_idle", name) || 803 sym_filter_entry = syme;
308 !strcmp("enter_idle", name) || 804
309 !strcmp("exit_idle", name) || 805 for (i = 0; skip_symbols[i]; i++) {
310 !strcmp("mwait_idle", name)) 806 if (!strcmp(skip_symbols[i], name)) {
311 syme->skip = 1; 807 syme->skip = 1;
312 808 break;
313 if (filter_match == 1) {
314 filter_end = sym->start;
315 filter_match = -1;
316 if (filter_end - filter_start > 10000) {
317 fprintf(stderr,
318 "hm, too large filter symbol <%s> - skipping.\n",
319 sym_filter);
320 fprintf(stderr, "symbol filter start: %016lx\n",
321 filter_start);
322 fprintf(stderr, " end: %016lx\n",
323 filter_end);
324 filter_end = filter_start = 0;
325 sym_filter = NULL;
326 sleep(1);
327 } 809 }
328 } 810 }
329 811
330 if (filter_match == 0 && sym_filter && !strcmp(name, sym_filter)) {
331 filter_match = 1;
332 filter_start = sym->start;
333 }
334
335
336 return 0; 812 return 0;
337} 813}
338 814
@@ -340,12 +816,13 @@ static int parse_symbols(void)
340{ 816{
341 struct rb_node *node; 817 struct rb_node *node;
342 struct symbol *sym; 818 struct symbol *sym;
819 int modules = vmlinux ? 1 : 0;
343 820
344 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); 821 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
345 if (kernel_dso == NULL) 822 if (kernel_dso == NULL)
346 return -1; 823 return -1;
347 824
348 if (dso__load_kernel(kernel_dso, NULL, symbol_filter, 1) != 0) 825 if (dso__load_kernel(kernel_dso, vmlinux, symbol_filter, verbose, modules) <= 0)
349 goto out_delete_dso; 826 goto out_delete_dso;
350 827
351 node = rb_first(&kernel_dso->syms); 828 node = rb_first(&kernel_dso->syms);
@@ -367,8 +844,6 @@ out_delete_dso:
367 return -1; 844 return -1;
368} 845}
369 846
370#define TRACE_COUNT 3
371
372/* 847/*
373 * Binary search in the histogram table and record the hit: 848 * Binary search in the histogram table and record the hit:
374 */ 849 */
@@ -381,6 +856,7 @@ static void record_ip(u64 ip, int counter)
381 856
382 if (!syme->skip) { 857 if (!syme->skip) {
383 syme->count[counter]++; 858 syme->count[counter]++;
859 record_precise_ip(syme, counter, ip);
384 pthread_mutex_lock(&active_symbols_lock); 860 pthread_mutex_lock(&active_symbols_lock);
385 if (list_empty(&syme->node) || !syme->node.next) 861 if (list_empty(&syme->node) || !syme->node.next)
386 __list_insert_active_sym(syme); 862 __list_insert_active_sym(syme);
@@ -407,7 +883,7 @@ static void process_event(u64 ip, int counter, int user)
407struct mmap_data { 883struct mmap_data {
408 int counter; 884 int counter;
409 void *base; 885 void *base;
410 unsigned int mask; 886 int mask;
411 unsigned int prev; 887 unsigned int prev;
412}; 888};
413 889
@@ -538,7 +1014,7 @@ int group_fd;
538static void start_counter(int i, int counter) 1014static void start_counter(int i, int counter)
539{ 1015{
540 struct perf_counter_attr *attr; 1016 struct perf_counter_attr *attr;
541 unsigned int cpu; 1017 int cpu;
542 1018
543 cpu = profile_cpu; 1019 cpu = profile_cpu;
544 if (target_pid == -1 && profile_cpu == -1) 1020 if (target_pid == -1 && profile_cpu == -1)
@@ -548,6 +1024,7 @@ static void start_counter(int i, int counter)
548 1024
549 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 1025 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
550 attr->freq = freq; 1026 attr->freq = freq;
1027 attr->inherit = (cpu < 0) && inherit;
551 1028
552try_again: 1029try_again:
553 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0); 1030 fd[i][counter] = sys_perf_counter_open(attr, target_pid, cpu, group_fd, 0);
@@ -661,6 +1138,7 @@ static const struct option options[] = {
661 "system-wide collection from all CPUs"), 1138 "system-wide collection from all CPUs"),
662 OPT_INTEGER('C', "CPU", &profile_cpu, 1139 OPT_INTEGER('C', "CPU", &profile_cpu,
663 "CPU to profile on"), 1140 "CPU to profile on"),
1141 OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
664 OPT_INTEGER('m', "mmap-pages", &mmap_pages, 1142 OPT_INTEGER('m', "mmap-pages", &mmap_pages,
665 "number of mmap data pages"), 1143 "number of mmap data pages"),
666 OPT_INTEGER('r', "realtime", &realtime_prio, 1144 OPT_INTEGER('r', "realtime", &realtime_prio,
@@ -673,9 +1151,11 @@ static const struct option options[] = {
673 "only display functions with more events than this"), 1151 "only display functions with more events than this"),
674 OPT_BOOLEAN('g', "group", &group, 1152 OPT_BOOLEAN('g', "group", &group,
675 "put the counters into a counter group"), 1153 "put the counters into a counter group"),
676 OPT_STRING('s', "sym-filter", &sym_filter, "pattern", 1154 OPT_BOOLEAN('i', "inherit", &inherit,
677 "only display symbols matchig this pattern"), 1155 "child tasks inherit counters"),
678 OPT_BOOLEAN('z', "zero", &group, 1156 OPT_STRING('s', "sym-annotate", &sym_filter, "symbol name",
1157 "symbol to annotate - requires -k option"),
1158 OPT_BOOLEAN('z', "zero", &zero,
679 "zero history across updates"), 1159 "zero history across updates"),
680 OPT_INTEGER('F', "freq", &freq, 1160 OPT_INTEGER('F', "freq", &freq,
681 "profile at this frequency"), 1161 "profile at this frequency"),
@@ -686,10 +1166,12 @@ static const struct option options[] = {
686 OPT_END() 1166 OPT_END()
687}; 1167};
688 1168
689int cmd_top(int argc, const char **argv, const char *prefix) 1169int cmd_top(int argc, const char **argv, const char *prefix __used)
690{ 1170{
691 int counter; 1171 int counter;
692 1172
1173 symbol__init();
1174
693 page_size = sysconf(_SC_PAGE_SIZE); 1175 page_size = sysconf(_SC_PAGE_SIZE);
694 1176
695 argc = parse_options(argc, argv, options, top_usage, 0); 1177 argc = parse_options(argc, argv, options, top_usage, 0);
@@ -715,6 +1197,7 @@ int cmd_top(int argc, const char **argv, const char *prefix)
715 delay_secs = 1; 1197 delay_secs = 1;
716 1198
717 parse_symbols(); 1199 parse_symbols();
1200 parse_source(sym_filter_entry);
718 1201
719 /* 1202 /*
720 * Fill in the ones not specifically initialized via -c: 1203 * Fill in the ones not specifically initialized via -c: