aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-20 17:51:27 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-21 08:11:33 -0500
commitc338aee853db197e1855b393e6d6cc667784537f (patch)
treef97fea21c608a689144302b8dd78ef29bfaa5c88 /tools/perf
parent78075caad99dc36ec6ef5826b7a5273ea14295fc (diff)
perf symbols: Do lazy symtab loading for the kernel & modules too
Just like we do with the other DSOs. This also simplifies the kernel_maps setup process, now all that the tools need to do is to call kernel_maps__init and the maps for the modules and kernel will be created, then, later, when kernel_maps__find_symbol() is used, it will also call maps__find_symbol that already checks if the symtab was loaded, loading it if needed. Now if one does 'perf top --hide_kernel_symbols' we won't pay the price of loading the (many) symbols in /proc/kallsyms or vmlinux. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1258757489-5978-4-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/builtin-annotate.c8
-rw-r--r--tools/perf/builtin-report.c6
-rw-r--r--tools/perf/builtin-top.c35
-rw-r--r--tools/perf/util/data_map.c4
-rw-r--r--tools/perf/util/event.h3
-rw-r--r--tools/perf/util/header.c6
-rw-r--r--tools/perf/util/map.c23
-rw-r--r--tools/perf/util/symbol.c173
-rw-r--r--tools/perf/util/symbol.h9
-rw-r--r--tools/perf/util/thread.h3
10 files changed, 109 insertions, 161 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index b6da1476ab1b..203152729a68 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -157,7 +157,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
157 157
158 if (event->header.misc & PERF_RECORD_MISC_KERNEL) { 158 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
159 level = 'k'; 159 level = 'k';
160 sym = kernel_maps__find_symbol(ip, &map); 160 sym = kernel_maps__find_symbol(ip, &map, symbol_filter);
161 dump_printf(" ...... dso: %s\n", 161 dump_printf(" ...... dso: %s\n",
162 map ? map->dso->long_name : "<not found>"); 162 map ? map->dso->long_name : "<not found>");
163 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 163 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
@@ -637,9 +637,9 @@ static int __cmd_annotate(void)
637 exit(0); 637 exit(0);
638 } 638 }
639 639
640 if (load_kernel(symbol_filter, use_modules) < 0) { 640 if (kernel_maps__init(use_modules) < 0) {
641 perror("failed to load kernel symbols"); 641 pr_err("failed to create kernel maps for symbol resolution\b");
642 return EXIT_FAILURE; 642 return -1;
643 } 643 }
644 644
645remap: 645remap:
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 0af48401f089..0d39e805be2d 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -449,7 +449,7 @@ got_map:
449 * trick of looking in the whole kernel symbol list. 449 * trick of looking in the whole kernel symbol list.
450 */ 450 */
451 if ((long long)ip < 0) 451 if ((long long)ip < 0)
452 return kernel_maps__find_symbol(ip, mapp); 452 return kernel_maps__find_symbol(ip, mapp, NULL);
453 } 453 }
454 dump_printf(" ...... dso: %s\n", 454 dump_printf(" ...... dso: %s\n",
455 map ? map->dso->long_name : "<not found>"); 455 map ? map->dso->long_name : "<not found>");
@@ -496,7 +496,7 @@ static struct symbol **resolve_callchain(struct thread *thread, struct map *map,
496 case PERF_CONTEXT_HV: 496 case PERF_CONTEXT_HV:
497 break; 497 break;
498 case PERF_CONTEXT_KERNEL: 498 case PERF_CONTEXT_KERNEL:
499 sym = kernel_maps__find_symbol(ip, &map); 499 sym = kernel_maps__find_symbol(ip, &map, NULL);
500 break; 500 break;
501 default: 501 default:
502 sym = resolve_symbol(thread, &map, &ip); 502 sym = resolve_symbol(thread, &map, &ip);
@@ -716,7 +716,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
716 716
717 if (cpumode == PERF_RECORD_MISC_KERNEL) { 717 if (cpumode == PERF_RECORD_MISC_KERNEL) {
718 level = 'k'; 718 level = 'k';
719 sym = kernel_maps__find_symbol(ip, &map); 719 sym = kernel_maps__find_symbol(ip, &map, NULL);
720 dump_printf(" ...... dso: %s\n", 720 dump_printf(" ...... dso: %s\n",
721 map ? map->dso->long_name : "<not found>"); 721 map ? map->dso->long_name : "<not found>");
722 } else if (cpumode == PERF_RECORD_MISC_USER) { 722 } else if (cpumode == PERF_RECORD_MISC_USER) {
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 48cc1084bc30..ea49c2e9dda3 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -830,6 +830,8 @@ static void handle_keypress(int c)
830 case 'q': 830 case 'q':
831 case 'Q': 831 case 'Q':
832 printf("exiting.\n"); 832 printf("exiting.\n");
833 if (dump_symtab)
834 dsos__fprintf(stderr);
833 exit(0); 835 exit(0);
834 case 's': 836 case 's':
835 prompt_symbol(&sym_filter_entry, "Enter details symbol"); 837 prompt_symbol(&sym_filter_entry, "Enter details symbol");
@@ -946,30 +948,6 @@ static int symbol_filter(struct map *map, struct symbol *sym)
946 return 0; 948 return 0;
947} 949}
948 950
949static int parse_symbols(void)
950{
951 struct dso *kernel = dsos__load_kernel();
952
953 if (kernel == NULL)
954 return -1;
955
956 if (dsos__load_modules() < 0)
957 pr_debug("Couldn't read the complete list of modules, "
958 "continuing...\n");
959
960 if (dsos__load_modules_sym(symbol_filter) < 0)
961 pr_warning("Failed to read module symbols, continuing...\n");
962
963 if (dso__load_kernel_sym(kernel, symbol_filter, 1) <= 0)
964 pr_debug("Couldn't read the complete list of kernel symbols, "
965 "continuing...\n");
966
967 if (dump_symtab)
968 dsos__fprintf(stderr);
969
970 return 0;
971}
972
973static void event__process_sample(const event_t *self, int counter) 951static void event__process_sample(const event_t *self, int counter)
974{ 952{
975 u64 ip = self->ip.ip; 953 u64 ip = self->ip.ip;
@@ -1012,7 +990,7 @@ static void event__process_sample(const event_t *self, int counter)
1012 if (hide_kernel_symbols) 990 if (hide_kernel_symbols)
1013 return; 991 return;
1014 992
1015 sym = kernel_maps__find_symbol(ip, &map); 993 sym = kernel_maps__find_symbol(ip, &map, symbol_filter);
1016 if (sym == NULL) 994 if (sym == NULL)
1017 return; 995 return;
1018 break; 996 break;
@@ -1339,7 +1317,7 @@ static const struct option options[] = {
1339 1317
1340int cmd_top(int argc, const char **argv, const char *prefix __used) 1318int cmd_top(int argc, const char **argv, const char *prefix __used)
1341{ 1319{
1342 int counter; 1320 int counter, err;
1343 1321
1344 page_size = sysconf(_SC_PAGE_SIZE); 1322 page_size = sysconf(_SC_PAGE_SIZE);
1345 1323
@@ -1363,10 +1341,11 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
1363 if (delay_secs < 1) 1341 if (delay_secs < 1)
1364 delay_secs = 1; 1342 delay_secs = 1;
1365 1343
1366 parse_symbols(); 1344 err = kernel_maps__init(true);
1345 if (err < 0)
1346 return err;
1367 parse_source(sym_filter_entry); 1347 parse_source(sym_filter_entry);
1368 1348
1369
1370 /* 1349 /*
1371 * User specified count overrides default frequency. 1350 * User specified count overrides default frequency.
1372 */ 1351 */
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index a444a2645c85..e7b6c2bea3de 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -171,8 +171,8 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
171 goto out_delete; 171 goto out_delete;
172 172
173 err = -ENOMEM; 173 err = -ENOMEM;
174 if (load_kernel(NULL, 1) < 0) { 174 if (kernel_maps__init(true) < 0) {
175 pr_err("failed to load kernel symbols\n"); 175 pr_err("failed to setup the kernel maps to resolve symbols\n");
176 goto out_delete; 176 goto out_delete;
177 } 177 }
178 178
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 34c6fcb82d92..f1e392612652 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -115,10 +115,13 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
115void map__init(struct map *self, u64 start, u64 end, u64 pgoff, 115void map__init(struct map *self, u64 start, u64 end, u64 pgoff,
116 struct dso *dso); 116 struct dso *dso);
117struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen); 117struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen);
118void map__delete(struct map *self);
118struct map *map__clone(struct map *self); 119struct map *map__clone(struct map *self);
119int map__overlap(struct map *l, struct map *r); 120int map__overlap(struct map *l, struct map *r);
120size_t map__fprintf(struct map *self, FILE *fp); 121size_t map__fprintf(struct map *self, FILE *fp);
121struct symbol *map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter); 122struct symbol *map__find_symbol(struct map *self, u64 ip, symbol_filter_t filter);
123void map__fixup_start(struct map *self);
124void map__fixup_end(struct map *self);
122 125
123int event__synthesize_thread(pid_t pid, int (*process)(event_t *event)); 126int event__synthesize_thread(pid_t pid, int (*process)(event_t *event));
124void event__synthesize_threads(int (*process)(event_t *event)); 127void event__synthesize_threads(int (*process)(event_t *event));
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index d5c81ebc0a84..ac3410b8e9e3 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -253,11 +253,11 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
253 253
254 buildid_sec = &feat_sec[idx++]; 254 buildid_sec = &feat_sec[idx++];
255 255
256 dsos__load_kernel();
257 /* 256 /*
258 * Read the list of loaded modules with its build_ids 257 * Read the kernel buildid nad the list of loaded modules with
258 * its build_ids:
259 */ 259 */
260 dsos__load_modules(); 260 kernel_maps__init(true);
261 261
262 /* Write build-ids */ 262 /* Write build-ids */
263 buildid_sec->offset = lseek(fd, 0, SEEK_CUR); 263 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 94ca95073c40..09412321a80d 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -75,6 +75,29 @@ out_delete:
75 return NULL; 75 return NULL;
76} 76}
77 77
78void map__delete(struct map *self)
79{
80 free(self);
81}
82
83void map__fixup_start(struct map *self)
84{
85 struct rb_node *nd = rb_first(&self->dso->syms);
86 if (nd != NULL) {
87 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
88 self->start = sym->start;
89 }
90}
91
92void map__fixup_end(struct map *self)
93{
94 struct rb_node *nd = rb_last(&self->dso->syms);
95 if (nd != NULL) {
96 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
97 self->end = sym->end;
98 }
99}
100
78#define DSO__DELETED "(deleted)" 101#define DSO__DELETED "(deleted)"
79 102
80struct symbol * 103struct symbol *
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c324bdf8baba..cb086cbe6b10 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -27,6 +27,8 @@ static void dsos__add(struct dso *dso);
27static struct dso *dsos__find(const char *name); 27static struct dso *dsos__find(const char *name);
28static struct map *map__new2(u64 start, struct dso *dso); 28static struct map *map__new2(u64 start, struct dso *dso);
29static void kernel_maps__insert(struct map *map); 29static void kernel_maps__insert(struct map *map);
30static int dso__load_kernel_sym(struct dso *self, struct map *map,
31 symbol_filter_t filter);
30unsigned int symbol__priv_size; 32unsigned int symbol__priv_size;
31 33
32static struct rb_root kernel_maps; 34static struct rb_root kernel_maps;
@@ -69,12 +71,6 @@ static void kernel_maps__fixup_end(void)
69 curr = rb_entry(nd, struct map, rb_node); 71 curr = rb_entry(nd, struct map, rb_node);
70 prev->end = curr->start - 1; 72 prev->end = curr->start - 1;
71 } 73 }
72
73 nd = rb_last(&curr->dso->syms);
74 if (nd) {
75 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
76 curr->end = sym->end;
77 }
78} 74}
79 75
80static struct symbol *symbol__new(u64 start, u64 len, const char *name) 76static struct symbol *symbol__new(u64 start, u64 len, const char *name)
@@ -324,7 +320,7 @@ out_failure:
324 * kernel range is broken in several maps, named [kernel].N, as we don't have 320 * kernel range is broken in several maps, named [kernel].N, as we don't have
325 * the original ELF section names vmlinux have. 321 * the original ELF section names vmlinux have.
326 */ 322 */
327static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules) 323static int kernel_maps__split_kallsyms(symbol_filter_t filter)
328{ 324{
329 struct map *map = kernel_map; 325 struct map *map = kernel_map;
330 struct symbol *pos; 326 struct symbol *pos;
@@ -340,9 +336,6 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
340 336
341 module = strchr(pos->name, '\t'); 337 module = strchr(pos->name, '\t');
342 if (module) { 338 if (module) {
343 if (!use_modules)
344 goto delete_symbol;
345
346 *module++ = '\0'; 339 *module++ = '\0';
347 340
348 if (strcmp(map->dso->name, module)) { 341 if (strcmp(map->dso->name, module)) {
@@ -382,7 +375,6 @@ static int kernel_maps__split_kallsyms(symbol_filter_t filter, int use_modules)
382 } 375 }
383 376
384 if (filter && filter(map, pos)) { 377 if (filter && filter(map, pos)) {
385delete_symbol:
386 rb_erase(&pos->rb_node, &kernel_map->dso->syms); 378 rb_erase(&pos->rb_node, &kernel_map->dso->syms);
387 symbol__delete(pos); 379 symbol__delete(pos);
388 } else { 380 } else {
@@ -398,17 +390,18 @@ delete_symbol:
398} 390}
399 391
400 392
401static int kernel_maps__load_kallsyms(symbol_filter_t filter, int use_modules) 393static int kernel_maps__load_kallsyms(symbol_filter_t filter)
402{ 394{
403 if (kernel_maps__load_all_kallsyms()) 395 if (kernel_maps__load_all_kallsyms())
404 return -1; 396 return -1;
405 397
406 dso__fixup_sym_end(kernel_map->dso); 398 dso__fixup_sym_end(kernel_map->dso);
399 kernel_map->dso->origin = DSO__ORIG_KERNEL;
407 400
408 return kernel_maps__split_kallsyms(filter, use_modules); 401 return kernel_maps__split_kallsyms(filter);
409} 402}
410 403
411static size_t kernel_maps__fprintf(FILE *fp) 404size_t kernel_maps__fprintf(FILE *fp)
412{ 405{
413 size_t printed = fprintf(fp, "Kernel maps:\n"); 406 size_t printed = fprintf(fp, "Kernel maps:\n");
414 struct rb_node *nd; 407 struct rb_node *nd;
@@ -1042,13 +1035,17 @@ char dso__symtab_origin(const struct dso *self)
1042int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) 1035int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1043{ 1036{
1044 int size = PATH_MAX; 1037 int size = PATH_MAX;
1045 char *name = malloc(size); 1038 char *name;
1046 u8 build_id[BUILD_ID_SIZE]; 1039 u8 build_id[BUILD_ID_SIZE];
1047 int ret = -1; 1040 int ret = -1;
1048 int fd; 1041 int fd;
1049 1042
1050 self->loaded = 1; 1043 self->loaded = 1;
1051 1044
1045 if (self->kernel)
1046 return dso__load_kernel_sym(self, map, filter);
1047
1048 name = malloc(size);
1052 if (!name) 1049 if (!name)
1053 return -1; 1050 return -1;
1054 1051
@@ -1139,7 +1136,8 @@ static void kernel_maps__insert(struct map *map)
1139 maps__insert(&kernel_maps, map); 1136 maps__insert(&kernel_maps, map);
1140} 1137}
1141 1138
1142struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp) 1139struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp,
1140 symbol_filter_t filter)
1143{ 1141{
1144 struct map *map = maps__find(&kernel_maps, ip); 1142 struct map *map = maps__find(&kernel_maps, ip);
1145 1143
@@ -1148,7 +1146,7 @@ struct symbol *kernel_maps__find_symbol(u64 ip, struct map **mapp)
1148 1146
1149 if (map) { 1147 if (map) {
1150 ip = map->map_ip(map, ip); 1148 ip = map->map_ip(map, ip);
1151 return map->dso->find_symbol(map->dso, ip); 1149 return map__find_symbol(map, ip, filter);
1152 } 1150 }
1153 1151
1154 return NULL; 1152 return NULL;
@@ -1168,28 +1166,9 @@ struct map *kernel_maps__find_by_dso_name(const char *name)
1168 return NULL; 1166 return NULL;
1169} 1167}
1170 1168
1171static int dso__load_module_sym(struct dso *self, struct map *map, 1169static int dsos__set_modules_path_dir(char *dirname)
1172 symbol_filter_t filter)
1173{
1174 int err = 0, fd = open(self->long_name, O_RDONLY);
1175
1176 self->loaded = 1;
1177
1178 if (fd < 0) {
1179 pr_err("%s: cannot open %s\n", __func__, self->long_name);
1180 return err;
1181 }
1182
1183 err = dso__load_sym(self, map, self->long_name, fd, filter, 0, 1);
1184 close(fd);
1185
1186 return err;
1187}
1188
1189static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
1190{ 1170{
1191 struct dirent *dent; 1171 struct dirent *dent;
1192 int nr_symbols = 0, err;
1193 DIR *dir = opendir(dirname); 1172 DIR *dir = opendir(dirname);
1194 1173
1195 if (!dir) { 1174 if (!dir) {
@@ -1207,14 +1186,12 @@ static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
1207 1186
1208 snprintf(path, sizeof(path), "%s/%s", 1187 snprintf(path, sizeof(path), "%s/%s",
1209 dirname, dent->d_name); 1188 dirname, dent->d_name);
1210 err = dsos__load_modules_sym_dir(path, filter); 1189 if (dsos__set_modules_path_dir(path) < 0)
1211 if (err < 0)
1212 goto failure; 1190 goto failure;
1213 } else { 1191 } else {
1214 char *dot = strrchr(dent->d_name, '.'), 1192 char *dot = strrchr(dent->d_name, '.'),
1215 dso_name[PATH_MAX]; 1193 dso_name[PATH_MAX];
1216 struct map *map; 1194 struct map *map;
1217 struct rb_node *last;
1218 char *long_name; 1195 char *long_name;
1219 1196
1220 if (dot == NULL || strcmp(dot, ".ko")) 1197 if (dot == NULL || strcmp(dot, ".ko"))
@@ -1234,36 +1211,16 @@ static int dsos__load_modules_sym_dir(char *dirname, symbol_filter_t filter)
1234 if (long_name == NULL) 1211 if (long_name == NULL)
1235 goto failure; 1212 goto failure;
1236 dso__set_long_name(map->dso, long_name); 1213 dso__set_long_name(map->dso, long_name);
1237 dso__set_basename(map->dso);
1238
1239 err = dso__load_module_sym(map->dso, map, filter);
1240 if (err < 0)
1241 goto failure;
1242 last = rb_last(&map->dso->syms);
1243 if (last) {
1244 struct symbol *sym;
1245 /*
1246 * We do this here as well, even having the
1247 * symbol size found in the symtab because
1248 * misannotated ASM symbols may have the size
1249 * set to zero.
1250 */
1251 dso__fixup_sym_end(map->dso);
1252
1253 sym = rb_entry(last, struct symbol, rb_node);
1254 map->end = map->start + sym->end;
1255 }
1256 } 1214 }
1257 nr_symbols += err;
1258 } 1215 }
1259 1216
1260 return nr_symbols; 1217 return 0;
1261failure: 1218failure:
1262 closedir(dir); 1219 closedir(dir);
1263 return -1; 1220 return -1;
1264} 1221}
1265 1222
1266int dsos__load_modules_sym(symbol_filter_t filter) 1223static int dsos__set_modules_path(void)
1267{ 1224{
1268 struct utsname uts; 1225 struct utsname uts;
1269 char modules_path[PATH_MAX]; 1226 char modules_path[PATH_MAX];
@@ -1274,7 +1231,7 @@ int dsos__load_modules_sym(symbol_filter_t filter)
1274 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", 1231 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
1275 uts.release); 1232 uts.release);
1276 1233
1277 return dsos__load_modules_sym_dir(modules_path, filter); 1234 return dsos__set_modules_path_dir(modules_path);
1278} 1235}
1279 1236
1280/* 1237/*
@@ -1296,7 +1253,7 @@ static struct map *map__new2(u64 start, struct dso *dso)
1296 return self; 1253 return self;
1297} 1254}
1298 1255
1299int dsos__load_modules(void) 1256static int kernel_maps__create_module_maps(void)
1300{ 1257{
1301 char *line = NULL; 1258 char *line = NULL;
1302 size_t n; 1259 size_t n;
@@ -1360,7 +1317,13 @@ int dsos__load_modules(void)
1360 free(line); 1317 free(line);
1361 fclose(file); 1318 fclose(file);
1362 1319
1363 return 0; 1320 /*
1321 * Now that we have all sorted out, just set the ->end of all
1322 * maps:
1323 */
1324 kernel_maps__fixup_end();
1325
1326 return dsos__set_modules_path();
1364 1327
1365out_delete_line: 1328out_delete_line:
1366 free(line); 1329 free(line);
@@ -1385,40 +1348,17 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1385 return err; 1348 return err;
1386} 1349}
1387 1350
1388int dso__load_kernel_sym(struct dso *self, symbol_filter_t filter, 1351static int dso__load_kernel_sym(struct dso *self, struct map *map,
1389 int use_modules) 1352 symbol_filter_t filter)
1390{ 1353{
1391 int err; 1354 int err = dso__load_vmlinux(self, map, self->name, filter);
1392 1355
1393 kernel_map = map__new2(0, self);
1394 if (kernel_map == NULL)
1395 return -1;
1396
1397 kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
1398
1399 err = dso__load_vmlinux(self, kernel_map, self->name, filter);
1400 if (err <= 0) 1356 if (err <= 0)
1401 err = kernel_maps__load_kallsyms(filter, use_modules); 1357 err = kernel_maps__load_kallsyms(filter);
1402 1358
1403 if (err > 0) { 1359 if (err > 0) {
1404 struct rb_node *node = rb_first(&self->syms); 1360 map__fixup_start(map);
1405 struct symbol *sym = rb_entry(node, struct symbol, rb_node); 1361 map__fixup_end(map);
1406
1407 kernel_map->start = sym->start;
1408 node = rb_last(&self->syms);
1409 sym = rb_entry(node, struct symbol, rb_node);
1410 kernel_map->end = sym->end;
1411
1412 self->origin = DSO__ORIG_KERNEL;
1413 kernel_maps__insert(kernel_map);
1414 /*
1415 * Now that we have all sorted out, just set the ->end of all
1416 * maps:
1417 */
1418 kernel_maps__fixup_end();
1419
1420 if (verbose)
1421 kernel_maps__fprintf(stderr);
1422 } 1362 }
1423 1363
1424 return err; 1364 return err;
@@ -1479,46 +1419,51 @@ size_t dsos__fprintf_buildid(FILE *fp)
1479 return ret; 1419 return ret;
1480} 1420}
1481 1421
1482struct dso *dsos__load_kernel(void) 1422static int kernel_maps__create_kernel_map(void)
1483{ 1423{
1484 struct dso *kernel = dso__new(vmlinux_name); 1424 struct dso *kernel = dso__new(vmlinux_name);
1485 1425
1486 if (kernel == NULL) 1426 if (kernel == NULL)
1487 return NULL; 1427 return -1;
1428
1429 kernel_map = map__new2(0, kernel);
1430 if (kernel_map == NULL)
1431 goto out_delete_kernel_dso;
1432
1433 kernel_map->map_ip = kernel_map->unmap_ip = identity__map_ip;
1488 1434
1489 kernel->short_name = "[kernel]"; 1435 kernel->short_name = "[kernel]";
1436 kernel->kernel = 1;
1490 vdso = dso__new("[vdso]"); 1437 vdso = dso__new("[vdso]");
1491 if (!vdso) 1438 if (vdso == NULL)
1492 return NULL; 1439 goto out_delete_kernel_map;
1493 1440
1494 if (sysfs__read_build_id("/sys/kernel/notes", kernel->build_id, 1441 if (sysfs__read_build_id("/sys/kernel/notes", kernel->build_id,
1495 sizeof(kernel->build_id)) == 0) 1442 sizeof(kernel->build_id)) == 0)
1496 kernel->has_build_id = true; 1443 kernel->has_build_id = true;
1497 1444
1445 kernel_maps__insert(kernel_map);
1498 dsos__add(kernel); 1446 dsos__add(kernel);
1499 dsos__add(vdso); 1447 dsos__add(vdso);
1500 1448
1501 return kernel; 1449 return 0;
1450
1451out_delete_kernel_map:
1452 map__delete(kernel_map);
1453 kernel_map = NULL;
1454out_delete_kernel_dso:
1455 dso__delete(kernel);
1456 return -1;
1502} 1457}
1503 1458
1504int load_kernel(symbol_filter_t filter, bool use_modules) 1459int kernel_maps__init(bool use_modules)
1505{ 1460{
1506 struct dso *kernel = dsos__load_kernel(); 1461 if (kernel_maps__create_kernel_map() < 0)
1507
1508 if (kernel == NULL)
1509 return -1; 1462 return -1;
1510 1463
1511 if (use_modules) { 1464 if (use_modules && kernel_maps__create_module_maps() < 0)
1512 if (dsos__load_modules() < 0) 1465 pr_warning("Failed to load list of modules in use, "
1513 pr_warning("Failed to load list of modules in use, " 1466 "continuing...\n");
1514 "continuing...\n");
1515 else if (dsos__load_modules_sym(filter) < 0)
1516 pr_warning("Failed to read module symbols, "
1517 "continuing...\n");
1518 }
1519
1520 if (dso__load_kernel_sym(kernel, filter, use_modules) < 0)
1521 pr_warning("Failed to read kernel symbols, continuing...\n");
1522 1467
1523 return 0; 1468 return 0;
1524} 1469}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 3d9d346d101b..7a129047c47d 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -64,6 +64,7 @@ struct dso {
64 u8 slen_calculated:1; 64 u8 slen_calculated:1;
65 u8 loaded:1; 65 u8 loaded:1;
66 u8 has_build_id:1; 66 u8 has_build_id:1;
67 u8 kernel:1;
67 unsigned char origin; 68 unsigned char origin;
68 u8 build_id[BUILD_ID_SIZE]; 69 u8 build_id[BUILD_ID_SIZE];
69 u16 long_name_len; 70 u16 long_name_len;
@@ -77,12 +78,8 @@ void dso__delete(struct dso *self);
77 78
78struct symbol *dso__find_symbol(struct dso *self, u64 ip); 79struct symbol *dso__find_symbol(struct dso *self, u64 ip);
79 80
80int dsos__load_modules(void);
81int dsos__load_modules_sym(symbol_filter_t filter);
82struct dso *dsos__findnew(const char *name); 81struct dso *dsos__findnew(const char *name);
83int dso__load(struct dso *self, struct map *map, symbol_filter_t filter); 82int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
84int dso__load_kernel_sym(struct dso *self, symbol_filter_t filter,
85 int use_modules);
86void dsos__fprintf(FILE *fp); 83void dsos__fprintf(FILE *fp);
87size_t dsos__fprintf_buildid(FILE *fp); 84size_t dsos__fprintf_buildid(FILE *fp);
88 85
@@ -96,8 +93,8 @@ int sysfs__read_build_id(const char *filename, void *bf, size_t size);
96bool dsos__read_build_ids(void); 93bool dsos__read_build_ids(void);
97int build_id__sprintf(u8 *self, int len, char *bf); 94int build_id__sprintf(u8 *self, int len, char *bf);
98 95
99struct dso *dsos__load_kernel(void); 96int kernel_maps__init(bool use_modules);
100int load_kernel(symbol_filter_t filter, bool use_modules); 97size_t kernel_maps__fprintf(FILE *fp);
101 98
102void symbol__init(unsigned int priv_size); 99void symbol__init(unsigned int priv_size);
103 100
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 53addd77ce8f..e4b8d437725a 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -26,7 +26,8 @@ size_t threads__fprintf(FILE *fp);
26void maps__insert(struct rb_root *maps, struct map *map); 26void maps__insert(struct rb_root *maps, struct map *map);
27struct map *maps__find(struct rb_root *maps, u64 ip); 27struct map *maps__find(struct rb_root *maps, u64 ip);
28 28
29struct symbol *kernel_maps__find_symbol(const u64 ip, struct map **mapp); 29struct symbol *kernel_maps__find_symbol(const u64 ip, struct map **mapp,
30 symbol_filter_t filter);
30struct map *kernel_maps__find_by_dso_name(const char *name); 31struct map *kernel_maps__find_by_dso_name(const char *name);
31 32
32static inline struct map *thread__find_map(struct thread *self, u64 ip) 33static inline struct map *thread__find_map(struct thread *self, u64 ip)