aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-27 13:29:20 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-27 14:22:00 -0500
commit95011c600740837288a3b34b411244a4d9157c4e (patch)
treef52496d2d378a338e7b0eee9b75e627bdfc4d2f1
parent23ea4a3fadc6b1692dec935397ea15e2affc1cba (diff)
perf symbols: Support multiple symtabs in struct thread
Making the routines that were so far specific to the kernel maps useful for all threads. This is done by making the kernel maps be contained in a kernel "thread". This gets the kernel specific routines closer to the userspace counterparts, which will help in reducing the boilerplate for resolving a symbol, as will be demonstrated in the next patches. 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: <1259346563-12568-9-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-report.c2
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/util/symbol.c157
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/thread.c115
-rw-r--r--tools/perf/util/thread.h15
7 files changed, 162 insertions, 133 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index c32e7609b77b..3ebd70b1ef93 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -167,7 +167,7 @@ process_sample_event(event_t *event, unsigned long offset, unsigned long head)
167 map ? map->dso->long_name : "<not found>"); 167 map ? map->dso->long_name : "<not found>");
168 } else if (event->header.misc & PERF_RECORD_MISC_USER) { 168 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
169 level = '.'; 169 level = '.';
170 map = thread__find_map(thread, ip); 170 map = thread__find_map(thread, MAP__FUNCTION, ip);
171 if (map != NULL) { 171 if (map != NULL) {
172 ip = map->map_ip(map, ip); 172 ip = map->map_ip(map, ip);
173 sym = map__find_symbol(map, ip, symbol_filter); 173 sym = map__find_symbol(map, ip, symbol_filter);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 400bef981c6c..9bd20c2ee3dd 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -422,7 +422,7 @@ resolve_symbol(struct thread *thread, struct map **mapp, u64 *ipp)
422 if (!thread) 422 if (!thread)
423 return NULL; 423 return NULL;
424 424
425 map = thread__find_map(thread, ip); 425 map = thread__find_map(thread, MAP__FUNCTION, ip);
426 if (map != NULL) { 426 if (map != NULL) {
427 /* 427 /*
428 * We have to do this here as we may have a dso 428 * We have to do this here as we may have a dso
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index abe78bbd154a..bf6730c76033 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -945,7 +945,7 @@ static void event__process_sample(const event_t *self, int counter)
945 if (thread == NULL) 945 if (thread == NULL)
946 return; 946 return;
947 947
948 map = thread__find_map(thread, ip); 948 map = thread__find_map(thread, MAP__FUNCTION, ip);
949 if (map != NULL) { 949 if (map != NULL) {
950 ip = map->map_ip(map, ip); 950 ip = map->map_ip(map, ip);
951 sym = map__find_symbol(map, ip, symbol_filter); 951 sym = map__find_symbol(map, ip, symbol_filter);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 581db4c43251..b6a2941e7786 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -29,12 +29,11 @@ enum dso_origin {
29}; 29};
30 30
31static void dsos__add(struct list_head *head, struct dso *dso); 31static void dsos__add(struct list_head *head, struct dso *dso);
32static struct map *kernel_maps__find_by_dso_name(const char *name); 32static struct map *thread__find_map_by_name(struct thread *self, char *name);
33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 33static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
34static void kernel_maps__insert(struct map *map);
35struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr); 34struct symbol *dso__find_symbol(struct dso *self, enum map_type type, u64 addr);
36static int dso__load_kernel_sym(struct dso *self, struct map *map, 35static int dso__load_kernel_sym(struct dso *self, struct map *map,
37 symbol_filter_t filter); 36 struct thread *thread, symbol_filter_t filter);
38unsigned int symbol__priv_size; 37unsigned int symbol__priv_size;
39static int vmlinux_path__nr_entries; 38static int vmlinux_path__nr_entries;
40static char **vmlinux_path; 39static char **vmlinux_path;
@@ -44,7 +43,7 @@ static struct symbol_conf symbol_conf__defaults = {
44 .try_vmlinux_path = true, 43 .try_vmlinux_path = true,
45}; 44};
46 45
47static struct rb_root kernel_maps[MAP__NR_TYPES]; 46static struct thread kthread_mem, *kthread = &kthread_mem;
48 47
49bool dso__loaded(const struct dso *self, enum map_type type) 48bool dso__loaded(const struct dso *self, enum map_type type)
50{ 49{
@@ -79,10 +78,10 @@ static void symbols__fixup_end(struct rb_root *self)
79 curr->end = roundup(curr->start, 4096); 78 curr->end = roundup(curr->start, 4096);
80} 79}
81 80
82static void __kernel_maps__fixup_end(struct rb_root *root) 81static void __thread__fixup_maps_end(struct thread *self, enum map_type type)
83{ 82{
84 struct map *prev, *curr; 83 struct map *prev, *curr;
85 struct rb_node *nd, *prevnd = rb_first(root); 84 struct rb_node *nd, *prevnd = rb_first(&self->maps[type]);
86 85
87 if (prevnd == NULL) 86 if (prevnd == NULL)
88 return; 87 return;
@@ -102,11 +101,11 @@ static void __kernel_maps__fixup_end(struct rb_root *root)
102 curr->end = ~0UL; 101 curr->end = ~0UL;
103} 102}
104 103
105static void kernel_maps__fixup_end(void) 104static void thread__fixup_maps_end(struct thread *self)
106{ 105{
107 int i; 106 int i;
108 for (i = 0; i < MAP__NR_TYPES; ++i) 107 for (i = 0; i < MAP__NR_TYPES; ++i)
109 __kernel_maps__fixup_end(&kernel_maps[i]); 108 __thread__fixup_maps_end(self, i);
110} 109}
111 110
112static struct symbol *symbol__new(u64 start, u64 len, const char *name) 111static struct symbol *symbol__new(u64 start, u64 len, const char *name)
@@ -274,25 +273,16 @@ size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
274 return fprintf(fp, "%s", sbuild_id); 273 return fprintf(fp, "%s", sbuild_id);
275} 274}
276 275
277static const char * map_type__name[MAP__NR_TYPES] = { 276size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
278 [MAP__FUNCTION] = "Functions",
279};
280
281size_t dso__fprintf(struct dso *self, FILE *fp)
282{ 277{
283 int i;
284 struct rb_node *nd; 278 struct rb_node *nd;
285 size_t ret = fprintf(fp, "dso: %s (", self->short_name); 279 size_t ret = fprintf(fp, "dso: %s (", self->short_name);
286 280
287 ret += dso__fprintf_buildid(self, fp); 281 ret += dso__fprintf_buildid(self, fp);
288 ret += fprintf(fp, ")\n"); 282 ret += fprintf(fp, ")\n");
289 for (i = 0; i < MAP__NR_TYPES; ++i) { 283 for (nd = rb_first(&self->symbols[type]); nd; nd = rb_next(nd)) {
290 ret += fprintf(fp, "%s:\n", map_type__name[i]); 284 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
291 285 ret += symbol__fprintf(pos, fp);
292 for (nd = rb_first(&self->symbols[i]); nd; nd = rb_next(nd)) {
293 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
294 ret += symbol__fprintf(pos, fp);
295 }
296 } 286 }
297 287
298 return ret; 288 return ret;
@@ -373,7 +363,7 @@ out_failure:
373 * kernel range is broken in several maps, named [kernel].N, as we don't have 363 * kernel range is broken in several maps, named [kernel].N, as we don't have
374 * the original ELF section names vmlinux have. 364 * the original ELF section names vmlinux have.
375 */ 365 */
376static int dso__split_kallsyms(struct dso *self, struct map *map, 366static int dso__split_kallsyms(struct dso *self, struct map *map, struct thread *thread,
377 symbol_filter_t filter) 367 symbol_filter_t filter)
378{ 368{
379 struct map *curr_map = map; 369 struct map *curr_map = map;
@@ -394,10 +384,10 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
394 *module++ = '\0'; 384 *module++ = '\0';
395 385
396 if (strcmp(self->name, module)) { 386 if (strcmp(self->name, module)) {
397 curr_map = kernel_maps__find_by_dso_name(module); 387 curr_map = thread__find_map_by_name(thread, module);
398 if (curr_map == NULL) { 388 if (curr_map == NULL) {
399 pr_err("/proc/{kallsyms,modules} " 389 pr_debug("/proc/{kallsyms,modules} "
400 "inconsistency!\n"); 390 "inconsistency!\n");
401 return -1; 391 return -1;
402 } 392 }
403 } 393 }
@@ -425,7 +415,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
425 } 415 }
426 416
427 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 417 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
428 kernel_maps__insert(curr_map); 418 __thread__insert_map(thread, curr_map);
429 ++kernel_range; 419 ++kernel_range;
430 } 420 }
431 421
@@ -446,7 +436,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
446 436
447 437
448static int dso__load_kallsyms(struct dso *self, struct map *map, 438static int dso__load_kallsyms(struct dso *self, struct map *map,
449 symbol_filter_t filter) 439 struct thread *thread, symbol_filter_t filter)
450{ 440{
451 if (dso__load_all_kallsyms(self, map) < 0) 441 if (dso__load_all_kallsyms(self, map) < 0)
452 return -1; 442 return -1;
@@ -454,35 +444,13 @@ static int dso__load_kallsyms(struct dso *self, struct map *map,
454 symbols__fixup_end(&self->symbols[map->type]); 444 symbols__fixup_end(&self->symbols[map->type]);
455 self->origin = DSO__ORIG_KERNEL; 445 self->origin = DSO__ORIG_KERNEL;
456 446
457 return dso__split_kallsyms(self, map, filter); 447 return dso__split_kallsyms(self, map, thread, filter);
458}
459
460static size_t __kernel_maps__fprintf(enum map_type type, FILE *fp)
461{
462 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
463 struct rb_node *nd;
464
465 for (nd = rb_first(&kernel_maps[type]); nd; nd = rb_next(nd)) {
466 struct map *pos = rb_entry(nd, struct map, rb_node);
467
468 printed += fprintf(fp, "Map:");
469 printed += map__fprintf(pos, fp);
470 if (verbose > 1) {
471 printed += dso__fprintf(pos->dso, fp);
472 printed += fprintf(fp, "--\n");
473 }
474 }
475
476 return printed;
477} 448}
478 449
479size_t kernel_maps__fprintf(FILE *fp) 450size_t kernel_maps__fprintf(FILE *fp)
480{ 451{
481 size_t printed = fprintf(fp, "Kernel maps:\n"); 452 size_t printed = fprintf(fp, "Kernel maps:\n");
482 int i; 453 printed += thread__fprintf_maps(kthread, fp);
483 for (i = 0; i < MAP__NR_TYPES; ++i)
484 printed += __kernel_maps__fprintf(i, fp);
485
486 return printed + fprintf(fp, "END kernel maps\n"); 454 return printed + fprintf(fp, "END kernel maps\n");
487} 455}
488 456
@@ -772,9 +740,9 @@ out:
772 return 0; 740 return 0;
773} 741}
774 742
775static int dso__load_sym(struct dso *self, struct map *map, const char *name, 743static int dso__load_sym(struct dso *self, struct map *map,
776 int fd, symbol_filter_t filter, int kernel, 744 struct thread *thread, const char *name, int fd,
777 int kmodule) 745 symbol_filter_t filter, int kernel, int kmodule)
778{ 746{
779 struct map *curr_map = map; 747 struct map *curr_map = map;
780 struct dso *curr_dso = self; 748 struct dso *curr_dso = self;
@@ -877,7 +845,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
877 snprintf(dso_name, sizeof(dso_name), 845 snprintf(dso_name, sizeof(dso_name),
878 "%s%s", self->short_name, section_name); 846 "%s%s", self->short_name, section_name);
879 847
880 curr_map = kernel_maps__find_by_dso_name(dso_name); 848 curr_map = thread__find_map_by_name(thread, dso_name);
881 if (curr_map == NULL) { 849 if (curr_map == NULL) {
882 u64 start = sym.st_value; 850 u64 start = sym.st_value;
883 851
@@ -896,7 +864,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
896 curr_map->map_ip = identity__map_ip; 864 curr_map->map_ip = identity__map_ip;
897 curr_map->unmap_ip = identity__map_ip; 865 curr_map->unmap_ip = identity__map_ip;
898 curr_dso->origin = DSO__ORIG_KERNEL; 866 curr_dso->origin = DSO__ORIG_KERNEL;
899 kernel_maps__insert(curr_map); 867 __thread__insert_map(kthread, curr_map);
900 dsos__add(&dsos__kernel, curr_dso); 868 dsos__add(&dsos__kernel, curr_dso);
901 } else 869 } else
902 curr_dso = curr_map->dso; 870 curr_dso = curr_map->dso;
@@ -1121,7 +1089,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1121 dso__set_loaded(self, map->type); 1089 dso__set_loaded(self, map->type);
1122 1090
1123 if (self->kernel) 1091 if (self->kernel)
1124 return dso__load_kernel_sym(self, map, filter); 1092 return dso__load_kernel_sym(self, map, kthread, filter);
1125 1093
1126 name = malloc(size); 1094 name = malloc(size);
1127 if (!name) 1095 if (!name)
@@ -1186,7 +1154,7 @@ compare_build_id:
1186 fd = open(name, O_RDONLY); 1154 fd = open(name, O_RDONLY);
1187 } while (fd < 0); 1155 } while (fd < 0);
1188 1156
1189 ret = dso__load_sym(self, map, name, fd, filter, 0, 0); 1157 ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0);
1190 close(fd); 1158 close(fd);
1191 1159
1192 /* 1160 /*
@@ -1207,16 +1175,11 @@ out:
1207 return ret; 1175 return ret;
1208} 1176}
1209 1177
1210static void kernel_maps__insert(struct map *map) 1178static struct symbol *thread__find_symbol(struct thread *self, u64 ip,
1211{ 1179 enum map_type type, struct map **mapp,
1212 maps__insert(&kernel_maps[map->type], map); 1180 symbol_filter_t filter)
1213}
1214
1215static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type,
1216 struct map **mapp,
1217 symbol_filter_t filter)
1218{ 1181{
1219 struct map *map = maps__find(&kernel_maps[type], ip); 1182 struct map *map = thread__find_map(self, type, ip);
1220 1183
1221 if (mapp) 1184 if (mapp)
1222 *mapp = map; 1185 *mapp = map;
@@ -1224,9 +1187,7 @@ static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type,
1224 if (map) { 1187 if (map) {
1225 ip = map->map_ip(map, ip); 1188 ip = map->map_ip(map, ip);
1226 return map__find_symbol(map, ip, filter); 1189 return map__find_symbol(map, ip, filter);
1227 } else 1190 }
1228 WARN_ONCE(RB_EMPTY_ROOT(&kernel_maps[type]),
1229 "Empty kernel_maps, was symbol__init() called?\n");
1230 1191
1231 return NULL; 1192 return NULL;
1232} 1193}
@@ -1234,14 +1195,14 @@ static struct symbol *kernel_maps__find_symbol(u64 ip, enum map_type type,
1234struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp, 1195struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp,
1235 symbol_filter_t filter) 1196 symbol_filter_t filter)
1236{ 1197{
1237 return kernel_maps__find_symbol(ip, MAP__FUNCTION, mapp, filter); 1198 return thread__find_symbol(kthread, ip, MAP__FUNCTION, mapp, filter);
1238} 1199}
1239 1200
1240static struct map *kernel_maps__find_by_dso_name(const char *name) 1201static struct map *thread__find_map_by_name(struct thread *self, char *name)
1241{ 1202{
1242 struct rb_node *nd; 1203 struct rb_node *nd;
1243 1204
1244 for (nd = rb_first(&kernel_maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) { 1205 for (nd = rb_first(&self->maps[MAP__FUNCTION]); nd; nd = rb_next(nd)) {
1245 struct map *map = rb_entry(nd, struct map, rb_node); 1206 struct map *map = rb_entry(nd, struct map, rb_node);
1246 1207
1247 if (map->dso && strcmp(map->dso->name, name) == 0) 1208 if (map->dso && strcmp(map->dso->name, name) == 0)
@@ -1285,7 +1246,7 @@ static int dsos__set_modules_path_dir(char *dirname)
1285 (int)(dot - dent->d_name), dent->d_name); 1246 (int)(dot - dent->d_name), dent->d_name);
1286 1247
1287 strxfrchar(dso_name, '-', '_'); 1248 strxfrchar(dso_name, '-', '_');
1288 map = kernel_maps__find_by_dso_name(dso_name); 1249 map = thread__find_map_by_name(kthread, dso_name);
1289 if (map == NULL) 1250 if (map == NULL)
1290 continue; 1251 continue;
1291 1252
@@ -1338,7 +1299,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1338 return self; 1299 return self;
1339} 1300}
1340 1301
1341static int kernel_maps__create_module_maps(void) 1302static int thread__create_module_maps(struct thread *self)
1342{ 1303{
1343 char *line = NULL; 1304 char *line = NULL;
1344 size_t n; 1305 size_t n;
@@ -1395,7 +1356,7 @@ static int kernel_maps__create_module_maps(void)
1395 dso->has_build_id = true; 1356 dso->has_build_id = true;
1396 1357
1397 dso->origin = DSO__ORIG_KMODULE; 1358 dso->origin = DSO__ORIG_KMODULE;
1398 kernel_maps__insert(map); 1359 __thread__insert_map(self, map);
1399 dsos__add(&dsos__kernel, dso); 1360 dsos__add(&dsos__kernel, dso);
1400 } 1361 }
1401 1362
@@ -1410,7 +1371,7 @@ out_failure:
1410 return -1; 1371 return -1;
1411} 1372}
1412 1373
1413static int dso__load_vmlinux(struct dso *self, struct map *map, 1374static int dso__load_vmlinux(struct dso *self, struct map *map, struct thread *thread,
1414 const char *vmlinux, symbol_filter_t filter) 1375 const char *vmlinux, symbol_filter_t filter)
1415{ 1376{
1416 int err = -1, fd; 1377 int err = -1, fd;
@@ -1444,15 +1405,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1444 return -1; 1405 return -1;
1445 1406
1446 dso__set_loaded(self, map->type); 1407 dso__set_loaded(self, map->type);
1447 err = dso__load_sym(self, map, self->long_name, fd, filter, 1, 0); 1408 err = dso__load_sym(self, map, thread, self->long_name, fd, filter, 1, 0);
1448
1449 close(fd); 1409 close(fd);
1450 1410
1451 return err; 1411 return err;
1452} 1412}
1453 1413
1454static int dso__load_kernel_sym(struct dso *self, struct map *map, 1414static int dso__load_kernel_sym(struct dso *self, struct map *map,
1455 symbol_filter_t filter) 1415 struct thread *thread, symbol_filter_t filter)
1456{ 1416{
1457 int err; 1417 int err;
1458 bool is_kallsyms; 1418 bool is_kallsyms;
@@ -1462,8 +1422,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1462 pr_debug("Looking at the vmlinux_path (%d entries long)\n", 1422 pr_debug("Looking at the vmlinux_path (%d entries long)\n",
1463 vmlinux_path__nr_entries); 1423 vmlinux_path__nr_entries);
1464 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1424 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1465 err = dso__load_vmlinux(self, map, vmlinux_path[i], 1425 err = dso__load_vmlinux(self, map, thread,
1466 filter); 1426 vmlinux_path[i], filter);
1467 if (err > 0) { 1427 if (err > 0) {
1468 pr_debug("Using %s for symbols\n", 1428 pr_debug("Using %s for symbols\n",
1469 vmlinux_path[i]); 1429 vmlinux_path[i]);
@@ -1478,12 +1438,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1478 if (is_kallsyms) 1438 if (is_kallsyms)
1479 goto do_kallsyms; 1439 goto do_kallsyms;
1480 1440
1481 err = dso__load_vmlinux(self, map, self->long_name, filter); 1441 err = dso__load_vmlinux(self, map, thread, self->long_name, filter);
1482 if (err <= 0) { 1442 if (err <= 0) {
1483 pr_info("The file %s cannot be used, " 1443 pr_info("The file %s cannot be used, "
1484 "trying to use /proc/kallsyms...", self->long_name); 1444 "trying to use /proc/kallsyms...", self->long_name);
1485do_kallsyms: 1445do_kallsyms:
1486 err = dso__load_kallsyms(self, map, filter); 1446 err = dso__load_kallsyms(self, map, thread, filter);
1487 if (err > 0 && !is_kallsyms) 1447 if (err > 0 && !is_kallsyms)
1488 dso__set_long_name(self, strdup("[kernel.kallsyms]")); 1448 dso__set_long_name(self, strdup("[kernel.kallsyms]"));
1489 } 1449 }
@@ -1535,8 +1495,11 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp)
1535{ 1495{
1536 struct dso *pos; 1496 struct dso *pos;
1537 1497
1538 list_for_each_entry(pos, head, node) 1498 list_for_each_entry(pos, head, node) {
1539 dso__fprintf(pos, fp); 1499 int i;
1500 for (i = 0; i < MAP__NR_TYPES; ++i)
1501 dso__fprintf(pos, i, fp);
1502 }
1540} 1503}
1541 1504
1542void dsos__fprintf(FILE *fp) 1505void dsos__fprintf(FILE *fp)
@@ -1563,10 +1526,10 @@ size_t dsos__fprintf_buildid(FILE *fp)
1563 __dsos__fprintf_buildid(&dsos__user, fp)); 1526 __dsos__fprintf_buildid(&dsos__user, fp));
1564} 1527}
1565 1528
1566static int kernel_maps__create_kernel_map(const struct symbol_conf *conf) 1529static int thread__create_kernel_map(struct thread *self, const char *vmlinux)
1567{ 1530{
1568 struct map *kmap; 1531 struct map *kmap;
1569 struct dso *kernel = dso__new(conf->vmlinux_name ?: "[kernel.kallsyms]"); 1532 struct dso *kernel = dso__new(vmlinux ?: "[kernel.kallsyms]");
1570 1533
1571 if (kernel == NULL) 1534 if (kernel == NULL)
1572 return -1; 1535 return -1;
@@ -1588,7 +1551,7 @@ static int kernel_maps__create_kernel_map(const struct symbol_conf *conf)
1588 sizeof(kernel->build_id)) == 0) 1551 sizeof(kernel->build_id)) == 0)
1589 kernel->has_build_id = true; 1552 kernel->has_build_id = true;
1590 1553
1591 kernel_maps__insert(kmap); 1554 __thread__insert_map(self, kmap);
1592 dsos__add(&dsos__kernel, kernel); 1555 dsos__add(&dsos__kernel, kernel);
1593 dsos__add(&dsos__user, vdso); 1556 dsos__add(&dsos__user, vdso);
1594 1557
@@ -1656,32 +1619,28 @@ out_fail:
1656 return -1; 1619 return -1;
1657} 1620}
1658 1621
1659static int kernel_maps__init(const struct symbol_conf *conf) 1622int symbol__init(struct symbol_conf *conf)
1660{ 1623{
1661 const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults; 1624 const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults;
1662 1625
1626 elf_version(EV_CURRENT);
1663 symbol__priv_size = pconf->priv_size; 1627 symbol__priv_size = pconf->priv_size;
1628 thread__init(kthread, 0);
1664 1629
1665 if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) 1630 if (pconf->try_vmlinux_path && vmlinux_path__init() < 0)
1666 return -1; 1631 return -1;
1667 1632
1668 if (kernel_maps__create_kernel_map(pconf) < 0) { 1633 if (thread__create_kernel_map(kthread, pconf->vmlinux_name) < 0) {
1669 vmlinux_path__exit(); 1634 vmlinux_path__exit();
1670 return -1; 1635 return -1;
1671 } 1636 }
1672 1637
1673 if (pconf->use_modules && kernel_maps__create_module_maps() < 0) 1638 if (pconf->use_modules && thread__create_module_maps(kthread) < 0)
1674 pr_debug("Failed to load list of modules in use, " 1639 pr_debug("Failed to load list of modules in use, "
1675 "continuing...\n"); 1640 "continuing...\n");
1676 /* 1641 /*
1677 * Now that we have all the maps created, just set the ->end of them: 1642 * Now that we have all the maps created, just set the ->end of them:
1678 */ 1643 */
1679 kernel_maps__fixup_end(); 1644 thread__fixup_maps_end(kthread);
1680 return 0; 1645 return 0;
1681} 1646}
1682
1683int symbol__init(struct symbol_conf *conf)
1684{
1685 elf_version(EV_CURRENT);
1686 return kernel_maps__init(conf);
1687}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 8934814d5a64..3f9e4a4d83dd 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -92,7 +92,7 @@ void dsos__fprintf(FILE *fp);
92size_t dsos__fprintf_buildid(FILE *fp); 92size_t dsos__fprintf_buildid(FILE *fp);
93 93
94size_t dso__fprintf_buildid(struct dso *self, FILE *fp); 94size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
95size_t dso__fprintf(struct dso *self, FILE *fp); 95size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp);
96char dso__symtab_origin(const struct dso *self); 96char dso__symtab_origin(const struct dso *self);
97void dso__set_build_id(struct dso *self, void *build_id); 97void dso__set_build_id(struct dso *self, void *build_id);
98 98
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 1796625f7784..2229f82cd630 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -9,17 +9,26 @@
9static struct rb_root threads; 9static struct rb_root threads;
10static struct thread *last_match; 10static struct thread *last_match;
11 11
12void thread__init(struct thread *self, pid_t pid)
13{
14 int i;
15 self->pid = pid;
16 self->comm = NULL;
17 for (i = 0; i < MAP__NR_TYPES; ++i) {
18 self->maps[i] = RB_ROOT;
19 INIT_LIST_HEAD(&self->removed_maps[i]);
20 }
21}
22
12static struct thread *thread__new(pid_t pid) 23static struct thread *thread__new(pid_t pid)
13{ 24{
14 struct thread *self = zalloc(sizeof(*self)); 25 struct thread *self = zalloc(sizeof(*self));
15 26
16 if (self != NULL) { 27 if (self != NULL) {
17 self->pid = pid; 28 thread__init(self, pid);
18 self->comm = malloc(32); 29 self->comm = malloc(32);
19 if (self->comm) 30 if (self->comm)
20 snprintf(self->comm, 32, ":%d", self->pid); 31 snprintf(self->comm, 32, ":%d", self->pid);
21 self->maps = RB_ROOT;
22 INIT_LIST_HEAD(&self->removed_maps);
23 } 32 }
24 33
25 return self; 34 return self;
@@ -44,24 +53,68 @@ int thread__comm_len(struct thread *self)
44 return self->comm_len; 53 return self->comm_len;
45} 54}
46 55
47static size_t thread__fprintf(struct thread *self, FILE *fp) 56static const char *map_type__name[MAP__NR_TYPES] = {
57 [MAP__FUNCTION] = "Functions",
58};
59
60static size_t __thread__fprintf_maps(struct thread *self,
61 enum map_type type, FILE *fp)
48{ 62{
63 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
49 struct rb_node *nd; 64 struct rb_node *nd;
50 struct map *pos;
51 size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
52 self->pid, self->comm);
53 65
54 for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) { 66 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
55 pos = rb_entry(nd, struct map, rb_node); 67 struct map *pos = rb_entry(nd, struct map, rb_node);
56 ret += map__fprintf(pos, fp); 68 printed += fprintf(fp, "Map:");
69 printed += map__fprintf(pos, fp);
70 if (verbose > 1) {
71 printed += dso__fprintf(pos->dso, type, fp);
72 printed += fprintf(fp, "--\n");
73 }
57 } 74 }
58 75
59 ret = fprintf(fp, "Removed maps:\n"); 76 return printed;
77}
78
79size_t thread__fprintf_maps(struct thread *self, FILE *fp)
80{
81 size_t printed = 0, i;
82 for (i = 0; i < MAP__NR_TYPES; ++i)
83 printed += __thread__fprintf_maps(self, i, fp);
84 return printed;
85}
60 86
61 list_for_each_entry(pos, &self->removed_maps, node) 87static size_t __thread__fprintf_removed_maps(struct thread *self,
62 ret += map__fprintf(pos, fp); 88 enum map_type type, FILE *fp)
89{
90 struct map *pos;
91 size_t printed = 0;
92
93 list_for_each_entry(pos, &self->removed_maps[type], node) {
94 printed += fprintf(fp, "Map:");
95 printed += map__fprintf(pos, fp);
96 if (verbose > 1) {
97 printed += dso__fprintf(pos->dso, type, fp);
98 printed += fprintf(fp, "--\n");
99 }
100 }
101 return printed;
102}
63 103
64 return ret; 104static size_t thread__fprintf_removed_maps(struct thread *self, FILE *fp)
105{
106 size_t printed = 0, i;
107 for (i = 0; i < MAP__NR_TYPES; ++i)
108 printed += __thread__fprintf_removed_maps(self, i, fp);
109 return printed;
110}
111
112static size_t thread__fprintf(struct thread *self, FILE *fp)
113{
114 size_t printed = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
115 printed += thread__fprintf_removed_maps(self, fp);
116 printed += fprintf(fp, "Removed maps:\n");
117 return printed + thread__fprintf_removed_maps(self, fp);
65} 118}
66 119
67struct thread *threads__findnew(pid_t pid) 120struct thread *threads__findnew(pid_t pid)
@@ -117,7 +170,8 @@ struct thread *register_idle_thread(void)
117 170
118static void thread__remove_overlappings(struct thread *self, struct map *map) 171static void thread__remove_overlappings(struct thread *self, struct map *map)
119{ 172{
120 struct rb_node *next = rb_first(&self->maps); 173 struct rb_root *root = &self->maps[map->type];
174 struct rb_node *next = rb_first(root);
121 175
122 while (next) { 176 while (next) {
123 struct map *pos = rb_entry(next, struct map, rb_node); 177 struct map *pos = rb_entry(next, struct map, rb_node);
@@ -132,13 +186,13 @@ static void thread__remove_overlappings(struct thread *self, struct map *map)
132 map__fprintf(pos, stderr); 186 map__fprintf(pos, stderr);
133 } 187 }
134 188
135 rb_erase(&pos->rb_node, &self->maps); 189 rb_erase(&pos->rb_node, root);
136 /* 190 /*
137 * We may have references to this map, for instance in some 191 * We may have references to this map, for instance in some
138 * hist_entry instances, so just move them to a separate 192 * hist_entry instances, so just move them to a separate
139 * list. 193 * list.
140 */ 194 */
141 list_add_tail(&pos->node, &self->removed_maps); 195 list_add_tail(&pos->node, &self->removed_maps[map->type]);
142 } 196 }
143} 197}
144 198
@@ -185,12 +239,26 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
185void thread__insert_map(struct thread *self, struct map *map) 239void thread__insert_map(struct thread *self, struct map *map)
186{ 240{
187 thread__remove_overlappings(self, map); 241 thread__remove_overlappings(self, map);
188 maps__insert(&self->maps, map); 242 maps__insert(&self->maps[map->type], map);
189} 243}
190 244
191int thread__fork(struct thread *self, struct thread *parent) 245static int thread__clone_maps(struct thread *self, struct thread *parent,
246 enum map_type type)
192{ 247{
193 struct rb_node *nd; 248 struct rb_node *nd;
249 for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
250 struct map *map = rb_entry(nd, struct map, rb_node);
251 struct map *new = map__clone(map);
252 if (new == NULL)
253 return -ENOMEM;
254 thread__insert_map(self, new);
255 }
256 return 0;
257}
258
259int thread__fork(struct thread *self, struct thread *parent)
260{
261 int i;
194 262
195 if (self->comm) 263 if (self->comm)
196 free(self->comm); 264 free(self->comm);
@@ -198,14 +266,9 @@ int thread__fork(struct thread *self, struct thread *parent)
198 if (!self->comm) 266 if (!self->comm)
199 return -ENOMEM; 267 return -ENOMEM;
200 268
201 for (nd = rb_first(&parent->maps); nd; nd = rb_next(nd)) { 269 for (i = 0; i < MAP__NR_TYPES; ++i)
202 struct map *map = rb_entry(nd, struct map, rb_node); 270 if (thread__clone_maps(self, parent, i) < 0)
203 struct map *new = map__clone(map);
204 if (!new)
205 return -ENOMEM; 271 return -ENOMEM;
206 thread__insert_map(self, new);
207 }
208
209 return 0; 272 return 0;
210} 273}
211 274
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 54580bb80008..3bdd9b2276f0 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -7,20 +7,22 @@
7 7
8struct thread { 8struct thread {
9 struct rb_node rb_node; 9 struct rb_node rb_node;
10 struct rb_root maps; 10 struct rb_root maps[MAP__NR_TYPES];
11 struct list_head removed_maps; 11 struct list_head removed_maps[MAP__NR_TYPES];
12 pid_t pid; 12 pid_t pid;
13 char shortname[3]; 13 char shortname[3];
14 char *comm; 14 char *comm;
15 int comm_len; 15 int comm_len;
16}; 16};
17 17
18void thread__init(struct thread *self, pid_t pid);
18int thread__set_comm(struct thread *self, const char *comm); 19int thread__set_comm(struct thread *self, const char *comm);
19int thread__comm_len(struct thread *self); 20int thread__comm_len(struct thread *self);
20struct thread *threads__findnew(pid_t pid); 21struct thread *threads__findnew(pid_t pid);
21struct thread *register_idle_thread(void); 22struct thread *register_idle_thread(void);
22void thread__insert_map(struct thread *self, struct map *map); 23void thread__insert_map(struct thread *self, struct map *map);
23int thread__fork(struct thread *self, struct thread *parent); 24int thread__fork(struct thread *self, struct thread *parent);
25size_t thread__fprintf_maps(struct thread *self, FILE *fp);
24size_t threads__fprintf(FILE *fp); 26size_t threads__fprintf(FILE *fp);
25 27
26void maps__insert(struct rb_root *maps, struct map *map); 28void maps__insert(struct rb_root *maps, struct map *map);
@@ -29,9 +31,14 @@ struct map *maps__find(struct rb_root *maps, u64 ip);
29struct symbol *kernel_maps__find_function(const u64 ip, struct map **mapp, 31struct symbol *kernel_maps__find_function(const u64 ip, struct map **mapp,
30 symbol_filter_t filter); 32 symbol_filter_t filter);
31 33
32static inline struct map *thread__find_map(struct thread *self, u64 ip) 34static inline struct map *thread__find_map(struct thread *self,
35 enum map_type type, u64 ip)
33{ 36{
34 return self ? maps__find(&self->maps, ip) : NULL; 37 return self ? maps__find(&self->maps[type], ip) : NULL;
35} 38}
36 39
40static inline void __thread__insert_map(struct thread *self, struct map *map)
41{
42 maps__insert(&self->maps[map->type], map);
43}
37#endif /* __PERF_THREAD_H */ 44#endif /* __PERF_THREAD_H */