aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-top.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-10-02 02:29:58 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-02 04:48:42 -0400
commit439d473b4777de510e1322168ac6f2f377ecd5bc (patch)
treef33622a0b98c2b0ce16637322d48542eb93e2fa3 /tools/perf/builtin-top.c
parent2ccdc450e658053681202d42ac64b3638f22dc1a (diff)
perf tools: Rewrite and improve support for kernel modules
Representing modules as struct map entries, backed by a DSO, etc, using /proc/modules to find where the module is loaded. DSOs now can have a short and long name, so that in verbose mode we can show exactly which .ko or vmlinux image was used. As kernel modules now are a DSO separate from the kernel, we can ask for just the hits for a particular set of kernel modules, just like we can do with shared libraries: [root@doppio linux-2.6-tip]# perf report -n --vmlinux /home/acme/git/build/tip-recvmmsg/vmlinux --modules --dsos \[drm\] | head -15 84.58% 13266 Xorg [k] drm_clflush_pages 4.02% 630 Xorg [k] trace_kmalloc.clone.0 3.95% 619 Xorg [k] drm_ioctl 2.07% 324 Xorg [k] drm_addbufs 1.68% 263 Xorg [k] drm_gem_close_ioctl 0.77% 120 Xorg [k] drm_setmaster_ioctl 0.70% 110 Xorg [k] drm_lastclose 0.68% 106 Xorg [k] drm_open 0.54% 85 Xorg [k] drm_mm_search_free [root@doppio linux-2.6-tip]# Specifying --dsos /lib/modules/2.6.31-tip/kernel/drivers/gpu/drm/drm.ko would have the same effect. Allowing specifying just 'drm.ko' is left for another patch. Processing kallsyms so that per kernel module struct map are instantiated was also left for another patch. That will allow removing the module name from each of its symbols. struct symbol was reduced by removing the ->module backpointer and moving it (well now the map) to struct symbol_entry in perf top, that is its only user right now. The total linecount went down by ~500 lines. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Avi Kivity <avi@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-top.c')
-rw-r--r--tools/perf/builtin-top.c74
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 {
116static void parse_source(struct sym_entry *syme) 118static 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
787static int symbol_filter(struct dso *self, struct symbol *sym) 767static 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
840out_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 */
849static void record_ip(u64 ip, int counter) 822static 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]++;