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.c155
1 files changed, 64 insertions, 91 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 37512e936235..c0f69e80b2cc 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,6 +22,7 @@
22 22
23#include "util/symbol.h" 23#include "util/symbol.h"
24#include "util/color.h" 24#include "util/color.h"
25#include "util/thread.h"
25#include "util/util.h" 26#include "util/util.h"
26#include <linux/rbtree.h> 27#include <linux/rbtree.h>
27#include "util/parse-options.h" 28#include "util/parse-options.h"
@@ -54,26 +55,26 @@
54 55
55static int fd[MAX_NR_CPUS][MAX_COUNTERS]; 56static int fd[MAX_NR_CPUS][MAX_COUNTERS];
56 57
57static int system_wide = 0; 58static int system_wide = 0;
58 59
59static int default_interval = 100000; 60static int default_interval = 0;
60 61
61static int count_filter = 5; 62static int count_filter = 5;
62static int print_entries = 15; 63static int print_entries = 15;
63 64
64static int target_pid = -1; 65static int target_pid = -1;
65static int inherit = 0; 66static int inherit = 0;
66static int profile_cpu = -1; 67static int profile_cpu = -1;
67static int nr_cpus = 0; 68static int nr_cpus = 0;
68static unsigned int realtime_prio = 0; 69static unsigned int realtime_prio = 0;
69static int group = 0; 70static int group = 0;
70static unsigned int page_size; 71static unsigned int page_size;
71static unsigned int mmap_pages = 16; 72static unsigned int mmap_pages = 16;
72static int freq = 0; 73static int freq = 1000; /* 1 KHz */
73 74
74static int delay_secs = 2; 75static int delay_secs = 2;
75static int zero; 76static int zero = 0;
76static int dump_symtab; 77static int dump_symtab = 0;
77 78
78/* 79/*
79 * Source 80 * Source
@@ -86,19 +87,16 @@ struct source_line {
86 struct source_line *next; 87 struct source_line *next;
87}; 88};
88 89
89static char *sym_filter = NULL; 90static char *sym_filter = NULL;
90struct sym_entry *sym_filter_entry = NULL; 91struct sym_entry *sym_filter_entry = NULL;
91static int sym_pcnt_filter = 5; 92static int sym_pcnt_filter = 5;
92static int sym_counter = 0; 93static int sym_counter = 0;
93static int display_weighted = -1; 94static int display_weighted = -1;
94 95
95/* 96/*
96 * Symbols 97 * Symbols
97 */ 98 */
98 99
99static u64 min_ip;
100static u64 max_ip = -1ll;
101
102struct sym_entry { 100struct sym_entry {
103 struct rb_node rb_node; 101 struct rb_node rb_node;
104 struct list_head node; 102 struct list_head node;
@@ -106,6 +104,7 @@ struct sym_entry {
106 unsigned long snap_count; 104 unsigned long snap_count;
107 double weight; 105 double weight;
108 int skip; 106 int skip;
107 struct map *map;
109 struct source_line *source; 108 struct source_line *source;
110 struct source_line *lines; 109 struct source_line *lines;
111 struct source_line **lines_tail; 110 struct source_line **lines_tail;
@@ -119,12 +118,11 @@ struct sym_entry {
119static void parse_source(struct sym_entry *syme) 118static void parse_source(struct sym_entry *syme)
120{ 119{
121 struct symbol *sym; 120 struct symbol *sym;
122 struct module *module; 121 struct map *map;
123 struct section *section = NULL;
124 FILE *file; 122 FILE *file;
125 char command[PATH_MAX*2]; 123 char command[PATH_MAX*2];
126 const char *path = vmlinux_name; 124 const char *path;
127 u64 start, end, len; 125 u64 len;
128 126
129 if (!syme) 127 if (!syme)
130 return; 128 return;
@@ -135,27 +133,15 @@ static void parse_source(struct sym_entry *syme)
135 } 133 }
136 134
137 sym = (struct symbol *)(syme + 1); 135 sym = (struct symbol *)(syme + 1);
138 module = sym->module; 136 map = syme->map;
139 137 path = map->dso->long_name;
140 if (module)
141 path = module->path;
142 if (!path)
143 return;
144
145 start = sym->obj_start;
146 if (!start)
147 start = sym->start;
148 138
149 if (module) {
150 section = module->sections->find_section(module->sections, ".text");
151 if (section)
152 start -= section->vma;
153 }
154
155 end = start + sym->end - sym->start + 1;
156 len = sym->end - sym->start; 139 len = sym->end - sym->start;
157 140
158 sprintf(command, "objdump --start-address=0x%016Lx --stop-address=0x%016Lx -dS %s", start, end, path); 141 sprintf(command,
142 "objdump --start-address=0x%016Lx "
143 "--stop-address=0x%016Lx -dS %s",
144 sym->start, sym->end, path);
159 145
160 file = popen(command, "r"); 146 file = popen(command, "r");
161 if (!file) 147 if (!file)
@@ -187,13 +173,11 @@ static void parse_source(struct sym_entry *syme)
187 173
188 if (strlen(src->line)>8 && src->line[8] == ':') { 174 if (strlen(src->line)>8 && src->line[8] == ':') {
189 src->eip = strtoull(src->line, NULL, 16); 175 src->eip = strtoull(src->line, NULL, 16);
190 if (section) 176 src->eip += map->start;
191 src->eip += section->vma;
192 } 177 }
193 if (strlen(src->line)>8 && src->line[16] == ':') { 178 if (strlen(src->line)>8 && src->line[16] == ':') {
194 src->eip = strtoull(src->line, NULL, 16); 179 src->eip = strtoull(src->line, NULL, 16);
195 if (section) 180 src->eip += map->start;
196 src->eip += section->vma;
197 } 181 }
198 } 182 }
199 pclose(file); 183 pclose(file);
@@ -245,16 +229,9 @@ static void lookup_sym_source(struct sym_entry *syme)
245 struct symbol *symbol = (struct symbol *)(syme + 1); 229 struct symbol *symbol = (struct symbol *)(syme + 1);
246 struct source_line *line; 230 struct source_line *line;
247 char pattern[PATH_MAX]; 231 char pattern[PATH_MAX];
248 char *idx;
249 232
250 sprintf(pattern, "<%s>:", symbol->name); 233 sprintf(pattern, "<%s>:", symbol->name);
251 234
252 if (symbol->module) {
253 idx = strstr(pattern, "\t");
254 if (idx)
255 *idx = 0;
256 }
257
258 pthread_mutex_lock(&syme->source_lock); 235 pthread_mutex_lock(&syme->source_lock);
259 for (line = syme->lines; line; line = line->next) { 236 for (line = syme->lines; line; line = line->next) {
260 if (strstr(line->line, pattern)) { 237 if (strstr(line->line, pattern)) {
@@ -516,8 +493,8 @@ static void print_sym_table(void)
516 if (verbose) 493 if (verbose)
517 printf(" - %016llx", sym->start); 494 printf(" - %016llx", sym->start);
518 printf(" : %s", sym->name); 495 printf(" : %s", sym->name);
519 if (sym->module) 496 if (syme->map->dso->name[0] == '[')
520 printf("\t[%s]", sym->module->name); 497 printf(" \t%s", syme->map->dso->name);
521 printf("\n"); 498 printf("\n");
522 } 499 }
523} 500}
@@ -788,7 +765,7 @@ static const char *skip_symbols[] = {
788 NULL 765 NULL
789}; 766};
790 767
791static int symbol_filter(struct dso *self, struct symbol *sym) 768static int symbol_filter(struct map *map, struct symbol *sym)
792{ 769{
793 struct sym_entry *syme; 770 struct sym_entry *syme;
794 const char *name = sym->name; 771 const char *name = sym->name;
@@ -810,7 +787,8 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
810 strstr(name, "_text_end")) 787 strstr(name, "_text_end"))
811 return 1; 788 return 1;
812 789
813 syme = dso__sym_priv(self, sym); 790 syme = dso__sym_priv(map->dso, sym);
791 syme->map = map;
814 pthread_mutex_init(&syme->source_lock, NULL); 792 pthread_mutex_init(&syme->source_lock, NULL);
815 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) 793 if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter))
816 sym_filter_entry = syme; 794 sym_filter_entry = syme;
@@ -827,34 +805,14 @@ static int symbol_filter(struct dso *self, struct symbol *sym)
827 805
828static int parse_symbols(void) 806static int parse_symbols(void)
829{ 807{
830 struct rb_node *node; 808 if (dsos__load_kernel(vmlinux_name, sizeof(struct sym_entry),
831 struct symbol *sym; 809 symbol_filter, verbose, 1) <= 0)
832 int use_modules = vmlinux_name ? 1 : 0;
833
834 kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry));
835 if (kernel_dso == NULL)
836 return -1; 810 return -1;
837 811
838 if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0)
839 goto out_delete_dso;
840
841 node = rb_first(&kernel_dso->syms);
842 sym = rb_entry(node, struct symbol, rb_node);
843 min_ip = sym->start;
844
845 node = rb_last(&kernel_dso->syms);
846 sym = rb_entry(node, struct symbol, rb_node);
847 max_ip = sym->end;
848
849 if (dump_symtab) 812 if (dump_symtab)
850 dso__fprintf(kernel_dso, stderr); 813 dsos__fprintf(stderr);
851 814
852 return 0; 815 return 0;
853
854out_delete_dso:
855 dso__delete(kernel_dso);
856 kernel_dso = NULL;
857 return -1;
858} 816}
859 817
860/* 818/*
@@ -862,10 +820,11 @@ out_delete_dso:
862 */ 820 */
863static void record_ip(u64 ip, int counter) 821static void record_ip(u64 ip, int counter)
864{ 822{
865 struct symbol *sym = dso__find_symbol(kernel_dso, ip); 823 struct map *map;
824 struct symbol *sym = kernel_maps__find_symbol(ip, &map);
866 825
867 if (sym != NULL) { 826 if (sym != NULL) {
868 struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); 827 struct sym_entry *syme = dso__sym_priv(map->dso, sym);
869 828
870 if (!syme->skip) { 829 if (!syme->skip) {
871 syme->count[counter]++; 830 syme->count[counter]++;
@@ -1016,7 +975,13 @@ static void start_counter(int i, int counter)
1016 attr = attrs + counter; 975 attr = attrs + counter;
1017 976
1018 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID; 977 attr->sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID;
1019 attr->freq = freq; 978
979 if (freq) {
980 attr->sample_type |= PERF_SAMPLE_PERIOD;
981 attr->freq = 1;
982 attr->sample_freq = freq;
983 }
984
1020 attr->inherit = (cpu < 0) && inherit; 985 attr->inherit = (cpu < 0) && inherit;
1021 986
1022try_again: 987try_again:
@@ -1171,11 +1136,6 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1171 if (argc) 1136 if (argc)
1172 usage_with_options(top_usage, options); 1137 usage_with_options(top_usage, options);
1173 1138
1174 if (freq) {
1175 default_interval = freq;
1176 freq = 1;
1177 }
1178
1179 /* CPU and PID are mutually exclusive */ 1139 /* CPU and PID are mutually exclusive */
1180 if (target_pid != -1 && profile_cpu != -1) { 1140 if (target_pid != -1 && profile_cpu != -1) {
1181 printf("WARNING: PID switch overriding CPU\n"); 1141 printf("WARNING: PID switch overriding CPU\n");
@@ -1192,6 +1152,19 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1192 parse_symbols(); 1152 parse_symbols();
1193 parse_source(sym_filter_entry); 1153 parse_source(sym_filter_entry);
1194 1154
1155
1156 /*
1157 * User specified count overrides default frequency.
1158 */
1159 if (default_interval)
1160 freq = 0;
1161 else if (freq) {
1162 default_interval = freq;
1163 } else {
1164 fprintf(stderr, "frequency and count are zero, aborting\n");
1165 exit(EXIT_FAILURE);
1166 }
1167
1195 /* 1168 /*
1196 * Fill in the ones not specifically initialized via -c: 1169 * Fill in the ones not specifically initialized via -c:
1197 */ 1170 */