diff options
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r-- | tools/perf/builtin-top.c | 74 |
1 files changed, 24 insertions, 50 deletions
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index bf464ce7e3e2..befef842757e 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" |
@@ -103,6 +104,7 @@ struct sym_entry { | |||
103 | unsigned long snap_count; | 104 | unsigned long snap_count; |
104 | double weight; | 105 | double weight; |
105 | int skip; | 106 | int skip; |
107 | struct map *map; | ||
106 | struct source_line *source; | 108 | struct source_line *source; |
107 | struct source_line *lines; | 109 | struct source_line *lines; |
108 | struct source_line **lines_tail; | 110 | struct source_line **lines_tail; |
@@ -116,12 +118,11 @@ struct sym_entry { | |||
116 | static void parse_source(struct sym_entry *syme) | 118 | static void parse_source(struct sym_entry *syme) |
117 | { | 119 | { |
118 | struct symbol *sym; | 120 | struct symbol *sym; |
119 | struct module *module; | 121 | struct map *map; |
120 | struct section *section = NULL; | ||
121 | FILE *file; | 122 | FILE *file; |
122 | char command[PATH_MAX*2]; | 123 | char command[PATH_MAX*2]; |
123 | const char *path = vmlinux_name; | 124 | const char *path; |
124 | u64 start, end, len; | 125 | u64 len; |
125 | 126 | ||
126 | if (!syme) | 127 | if (!syme) |
127 | return; | 128 | return; |
@@ -132,27 +133,15 @@ static void parse_source(struct sym_entry *syme) | |||
132 | } | 133 | } |
133 | 134 | ||
134 | sym = (struct symbol *)(syme + 1); | 135 | sym = (struct symbol *)(syme + 1); |
135 | module = sym->module; | 136 | map = syme->map; |
137 | path = map->dso->long_name; | ||
136 | 138 | ||
137 | if (module) | ||
138 | path = module->path; | ||
139 | if (!path) | ||
140 | return; | ||
141 | |||
142 | start = sym->obj_start; | ||
143 | if (!start) | ||
144 | start = sym->start; | ||
145 | |||
146 | if (module) { | ||
147 | section = module->sections->find_section(module->sections, ".text"); | ||
148 | if (section) | ||
149 | start -= section->vma; | ||
150 | } | ||
151 | |||
152 | end = start + sym->end - sym->start + 1; | ||
153 | len = sym->end - sym->start; | 139 | len = sym->end - sym->start; |
154 | 140 | ||
155 | 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); | ||
156 | 145 | ||
157 | file = popen(command, "r"); | 146 | file = popen(command, "r"); |
158 | if (!file) | 147 | if (!file) |
@@ -184,13 +173,11 @@ static void parse_source(struct sym_entry *syme) | |||
184 | 173 | ||
185 | if (strlen(src->line)>8 && src->line[8] == ':') { | 174 | if (strlen(src->line)>8 && src->line[8] == ':') { |
186 | src->eip = strtoull(src->line, NULL, 16); | 175 | src->eip = strtoull(src->line, NULL, 16); |
187 | if (section) | 176 | src->eip += map->start; |
188 | src->eip += section->vma; | ||
189 | } | 177 | } |
190 | if (strlen(src->line)>8 && src->line[16] == ':') { | 178 | if (strlen(src->line)>8 && src->line[16] == ':') { |
191 | src->eip = strtoull(src->line, NULL, 16); | 179 | src->eip = strtoull(src->line, NULL, 16); |
192 | if (section) | 180 | src->eip += map->start; |
193 | src->eip += section->vma; | ||
194 | } | 181 | } |
195 | } | 182 | } |
196 | pclose(file); | 183 | pclose(file); |
@@ -242,16 +229,9 @@ static void lookup_sym_source(struct sym_entry *syme) | |||
242 | struct symbol *symbol = (struct symbol *)(syme + 1); | 229 | struct symbol *symbol = (struct symbol *)(syme + 1); |
243 | struct source_line *line; | 230 | struct source_line *line; |
244 | char pattern[PATH_MAX]; | 231 | char pattern[PATH_MAX]; |
245 | char *idx; | ||
246 | 232 | ||
247 | sprintf(pattern, "<%s>:", symbol->name); | 233 | sprintf(pattern, "<%s>:", symbol->name); |
248 | 234 | ||
249 | if (symbol->module) { | ||
250 | idx = strstr(pattern, "\t"); | ||
251 | if (idx) | ||
252 | *idx = 0; | ||
253 | } | ||
254 | |||
255 | pthread_mutex_lock(&syme->source_lock); | 235 | pthread_mutex_lock(&syme->source_lock); |
256 | for (line = syme->lines; line; line = line->next) { | 236 | for (line = syme->lines; line; line = line->next) { |
257 | if (strstr(line->line, pattern)) { | 237 | if (strstr(line->line, pattern)) { |
@@ -513,8 +493,8 @@ static void print_sym_table(void) | |||
513 | if (verbose) | 493 | if (verbose) |
514 | printf(" - %016llx", sym->start); | 494 | printf(" - %016llx", sym->start); |
515 | printf(" : %s", sym->name); | 495 | printf(" : %s", sym->name); |
516 | if (sym->module) | 496 | if (syme->map->dso->name[0] == '[') |
517 | printf("\t[%s]", sym->module->name); | 497 | printf(" \t%s", syme->map->dso->name); |
518 | printf("\n"); | 498 | printf("\n"); |
519 | } | 499 | } |
520 | } | 500 | } |
@@ -784,7 +764,7 @@ static const char *skip_symbols[] = { | |||
784 | NULL | 764 | NULL |
785 | }; | 765 | }; |
786 | 766 | ||
787 | static int symbol_filter(struct dso *self, struct symbol *sym) | 767 | static int symbol_filter(struct map *map, struct symbol *sym) |
788 | { | 768 | { |
789 | struct sym_entry *syme; | 769 | struct sym_entry *syme; |
790 | const char *name = sym->name; | 770 | const char *name = sym->name; |
@@ -806,7 +786,8 @@ static int symbol_filter(struct dso *self, struct symbol *sym) | |||
806 | strstr(name, "_text_end")) | 786 | strstr(name, "_text_end")) |
807 | return 1; | 787 | return 1; |
808 | 788 | ||
809 | syme = dso__sym_priv(self, sym); | 789 | syme = dso__sym_priv(map->dso, sym); |
790 | syme->map = map; | ||
810 | pthread_mutex_init(&syme->source_lock, NULL); | 791 | pthread_mutex_init(&syme->source_lock, NULL); |
811 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) | 792 | if (!sym_filter_entry && sym_filter && !strcmp(name, sym_filter)) |
812 | sym_filter_entry = syme; | 793 | sym_filter_entry = syme; |
@@ -825,22 +806,14 @@ static int parse_symbols(void) | |||
825 | { | 806 | { |
826 | int use_modules = vmlinux_name ? 1 : 0; | 807 | int use_modules = vmlinux_name ? 1 : 0; |
827 | 808 | ||
828 | kernel_dso = dso__new("[kernel]", sizeof(struct sym_entry)); | 809 | if (dsos__load_kernel(vmlinux_name, sizeof(struct sym_entry), |
829 | if (kernel_dso == NULL) | 810 | symbol_filter, verbose, use_modules) <= 0) |
830 | return -1; | 811 | return -1; |
831 | 812 | ||
832 | if (dso__load_kernel(kernel_dso, vmlinux_name, symbol_filter, verbose, use_modules) <= 0) | ||
833 | goto out_delete_dso; | ||
834 | |||
835 | if (dump_symtab) | 813 | if (dump_symtab) |
836 | dso__fprintf(kernel_dso, stderr); | 814 | dsos__fprintf(stderr); |
837 | 815 | ||
838 | return 0; | 816 | return 0; |
839 | |||
840 | out_delete_dso: | ||
841 | dso__delete(kernel_dso); | ||
842 | kernel_dso = NULL; | ||
843 | return -1; | ||
844 | } | 817 | } |
845 | 818 | ||
846 | /* | 819 | /* |
@@ -848,10 +821,11 @@ out_delete_dso: | |||
848 | */ | 821 | */ |
849 | static void record_ip(u64 ip, int counter) | 822 | static void record_ip(u64 ip, int counter) |
850 | { | 823 | { |
851 | struct symbol *sym = dso__find_symbol(kernel_dso, ip); | 824 | struct map *map; |
825 | struct symbol *sym = kernel_maps__find_symbol(ip, &map); | ||
852 | 826 | ||
853 | if (sym != NULL) { | 827 | if (sym != NULL) { |
854 | struct sym_entry *syme = dso__sym_priv(kernel_dso, sym); | 828 | struct sym_entry *syme = dso__sym_priv(map->dso, sym); |
855 | 829 | ||
856 | if (!syme->skip) { | 830 | if (!syme->skip) { |
857 | syme->count[counter]++; | 831 | syme->count[counter]++; |