diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-12-13 16:50:29 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-14 10:57:17 -0500 |
commit | 4aa65636411ccb12f006a6ad593930655c445ff6 (patch) | |
tree | 0f494705a2a7631070a5372bb53f873684b001c2 /tools/perf/util/symbol.c | |
parent | b3165f414416a717f72a376720564012af5a2e01 (diff) |
perf session: Move kmaps to perf_session
There is still some more work to do to disentangle map creation
from DSO loading, but this happens only for the kernel, and for
the early adopters of perf diff, where this disentanglement
matters most, we'll be testing different kernels, so no problem
here.
Further clarification: right now we create the kernel maps for
the various modules and discontiguous kernel text maps when
loading the DSO, we should do it as a two step process, first
creating the maps, for multiple mappings with the same DSO
store, then doing the dso load just once, for the first hit on
one of the maps sharing this DSO backing store.
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: <1260741029-4430-6-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 89 |
1 files changed, 44 insertions, 45 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index d3d9fed74f1d..185b9eec192b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1,5 +1,6 @@ | |||
1 | #include "util.h" | 1 | #include "util.h" |
2 | #include "../perf.h" | 2 | #include "../perf.h" |
3 | #include "session.h" | ||
3 | #include "string.h" | 4 | #include "string.h" |
4 | #include "symbol.h" | 5 | #include "symbol.h" |
5 | #include "thread.h" | 6 | #include "thread.h" |
@@ -31,7 +32,7 @@ enum dso_origin { | |||
31 | static void dsos__add(struct list_head *head, struct dso *dso); | 32 | static void dsos__add(struct list_head *head, struct dso *dso); |
32 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 33 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
33 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 34 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
34 | struct map_groups *mg, symbol_filter_t filter); | 35 | struct perf_session *session, symbol_filter_t filter); |
35 | unsigned int symbol__priv_size; | 36 | unsigned int symbol__priv_size; |
36 | static int vmlinux_path__nr_entries; | 37 | static int vmlinux_path__nr_entries; |
37 | static char **vmlinux_path; | 38 | static char **vmlinux_path; |
@@ -41,9 +42,6 @@ static struct symbol_conf symbol_conf__defaults = { | |||
41 | .try_vmlinux_path = true, | 42 | .try_vmlinux_path = true, |
42 | }; | 43 | }; |
43 | 44 | ||
44 | static struct map_groups kmaps_mem; | ||
45 | struct map_groups *kmaps = &kmaps_mem; | ||
46 | |||
47 | bool dso__loaded(const struct dso *self, enum map_type type) | 45 | bool dso__loaded(const struct dso *self, enum map_type type) |
48 | { | 46 | { |
49 | return self->loaded & (1 << type); | 47 | return self->loaded & (1 << type); |
@@ -456,7 +454,7 @@ out_failure: | |||
456 | * the original ELF section names vmlinux have. | 454 | * the original ELF section names vmlinux have. |
457 | */ | 455 | */ |
458 | static int dso__split_kallsyms(struct dso *self, struct map *map, | 456 | static int dso__split_kallsyms(struct dso *self, struct map *map, |
459 | struct map_groups *mg, symbol_filter_t filter) | 457 | struct perf_session *session, symbol_filter_t filter) |
460 | { | 458 | { |
461 | struct map *curr_map = map; | 459 | struct map *curr_map = map; |
462 | struct symbol *pos; | 460 | struct symbol *pos; |
@@ -473,13 +471,13 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
473 | 471 | ||
474 | module = strchr(pos->name, '\t'); | 472 | module = strchr(pos->name, '\t'); |
475 | if (module) { | 473 | if (module) { |
476 | if (!mg->use_modules) | 474 | if (!session->use_modules) |
477 | goto discard_symbol; | 475 | goto discard_symbol; |
478 | 476 | ||
479 | *module++ = '\0'; | 477 | *module++ = '\0'; |
480 | 478 | ||
481 | if (strcmp(self->name, module)) { | 479 | if (strcmp(self->name, module)) { |
482 | curr_map = map_groups__find_by_name(mg, map->type, module); | 480 | curr_map = map_groups__find_by_name(&session->kmaps, map->type, module); |
483 | if (curr_map == NULL) { | 481 | if (curr_map == NULL) { |
484 | pr_debug("/proc/{kallsyms,modules} " | 482 | pr_debug("/proc/{kallsyms,modules} " |
485 | "inconsistency!\n"); | 483 | "inconsistency!\n"); |
@@ -510,7 +508,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
510 | } | 508 | } |
511 | 509 | ||
512 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; | 510 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; |
513 | map_groups__insert(mg, curr_map); | 511 | map_groups__insert(&session->kmaps, curr_map); |
514 | ++kernel_range; | 512 | ++kernel_range; |
515 | } | 513 | } |
516 | 514 | ||
@@ -531,7 +529,7 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
531 | 529 | ||
532 | 530 | ||
533 | static int dso__load_kallsyms(struct dso *self, struct map *map, | 531 | static int dso__load_kallsyms(struct dso *self, struct map *map, |
534 | struct map_groups *mg, symbol_filter_t filter) | 532 | struct perf_session *session, symbol_filter_t filter) |
535 | { | 533 | { |
536 | if (dso__load_all_kallsyms(self, map) < 0) | 534 | if (dso__load_all_kallsyms(self, map) < 0) |
537 | return -1; | 535 | return -1; |
@@ -539,14 +537,7 @@ static int dso__load_kallsyms(struct dso *self, struct map *map, | |||
539 | symbols__fixup_end(&self->symbols[map->type]); | 537 | symbols__fixup_end(&self->symbols[map->type]); |
540 | self->origin = DSO__ORIG_KERNEL; | 538 | self->origin = DSO__ORIG_KERNEL; |
541 | 539 | ||
542 | return dso__split_kallsyms(self, map, mg, filter); | 540 | return dso__split_kallsyms(self, map, session, filter); |
543 | } | ||
544 | |||
545 | size_t kernel_maps__fprintf(FILE *fp) | ||
546 | { | ||
547 | size_t printed = fprintf(fp, "Kernel maps:\n"); | ||
548 | printed += map_groups__fprintf_maps(kmaps, fp); | ||
549 | return printed + fprintf(fp, "END kernel maps\n"); | ||
550 | } | 541 | } |
551 | 542 | ||
552 | static int dso__load_perf_map(struct dso *self, struct map *map, | 543 | static int dso__load_perf_map(struct dso *self, struct map *map, |
@@ -873,7 +864,7 @@ static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type | |||
873 | } | 864 | } |
874 | 865 | ||
875 | static int dso__load_sym(struct dso *self, struct map *map, | 866 | static int dso__load_sym(struct dso *self, struct map *map, |
876 | struct map_groups *mg, const char *name, int fd, | 867 | struct perf_session *session, const char *name, int fd, |
877 | symbol_filter_t filter, int kernel, int kmodule) | 868 | symbol_filter_t filter, int kernel, int kmodule) |
878 | { | 869 | { |
879 | struct map *curr_map = map; | 870 | struct map *curr_map = map; |
@@ -977,7 +968,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
977 | snprintf(dso_name, sizeof(dso_name), | 968 | snprintf(dso_name, sizeof(dso_name), |
978 | "%s%s", self->short_name, section_name); | 969 | "%s%s", self->short_name, section_name); |
979 | 970 | ||
980 | curr_map = map_groups__find_by_name(mg, map->type, dso_name); | 971 | curr_map = map_groups__find_by_name(&session->kmaps, map->type, dso_name); |
981 | if (curr_map == NULL) { | 972 | if (curr_map == NULL) { |
982 | u64 start = sym.st_value; | 973 | u64 start = sym.st_value; |
983 | 974 | ||
@@ -996,7 +987,7 @@ static int dso__load_sym(struct dso *self, struct map *map, | |||
996 | curr_map->map_ip = identity__map_ip; | 987 | curr_map->map_ip = identity__map_ip; |
997 | curr_map->unmap_ip = identity__map_ip; | 988 | curr_map->unmap_ip = identity__map_ip; |
998 | curr_dso->origin = DSO__ORIG_KERNEL; | 989 | curr_dso->origin = DSO__ORIG_KERNEL; |
999 | map_groups__insert(kmaps, curr_map); | 990 | map_groups__insert(&session->kmaps, curr_map); |
1000 | dsos__add(&dsos__kernel, curr_dso); | 991 | dsos__add(&dsos__kernel, curr_dso); |
1001 | } else | 992 | } else |
1002 | curr_dso = curr_map->dso; | 993 | curr_dso = curr_map->dso; |
@@ -1211,7 +1202,8 @@ char dso__symtab_origin(const struct dso *self) | |||
1211 | return origin[self->origin]; | 1202 | return origin[self->origin]; |
1212 | } | 1203 | } |
1213 | 1204 | ||
1214 | int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | 1205 | int dso__load(struct dso *self, struct map *map, struct perf_session *session, |
1206 | symbol_filter_t filter) | ||
1215 | { | 1207 | { |
1216 | int size = PATH_MAX; | 1208 | int size = PATH_MAX; |
1217 | char *name; | 1209 | char *name; |
@@ -1222,7 +1214,7 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1222 | dso__set_loaded(self, map->type); | 1214 | dso__set_loaded(self, map->type); |
1223 | 1215 | ||
1224 | if (self->kernel) | 1216 | if (self->kernel) |
1225 | return dso__load_kernel_sym(self, map, kmaps, filter); | 1217 | return dso__load_kernel_sym(self, map, session, filter); |
1226 | 1218 | ||
1227 | name = malloc(size); | 1219 | name = malloc(size); |
1228 | if (!name) | 1220 | if (!name) |
@@ -1323,7 +1315,7 @@ struct map *map_groups__find_by_name(struct map_groups *self, | |||
1323 | return NULL; | 1315 | return NULL; |
1324 | } | 1316 | } |
1325 | 1317 | ||
1326 | static int dsos__set_modules_path_dir(char *dirname) | 1318 | static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname) |
1327 | { | 1319 | { |
1328 | struct dirent *dent; | 1320 | struct dirent *dent; |
1329 | DIR *dir = opendir(dirname); | 1321 | DIR *dir = opendir(dirname); |
@@ -1343,7 +1335,7 @@ static int dsos__set_modules_path_dir(char *dirname) | |||
1343 | 1335 | ||
1344 | snprintf(path, sizeof(path), "%s/%s", | 1336 | snprintf(path, sizeof(path), "%s/%s", |
1345 | dirname, dent->d_name); | 1337 | dirname, dent->d_name); |
1346 | if (dsos__set_modules_path_dir(path) < 0) | 1338 | if (perf_session__set_modules_path_dir(self, path) < 0) |
1347 | goto failure; | 1339 | goto failure; |
1348 | } else { | 1340 | } else { |
1349 | char *dot = strrchr(dent->d_name, '.'), | 1341 | char *dot = strrchr(dent->d_name, '.'), |
@@ -1357,7 +1349,7 @@ static int dsos__set_modules_path_dir(char *dirname) | |||
1357 | (int)(dot - dent->d_name), dent->d_name); | 1349 | (int)(dot - dent->d_name), dent->d_name); |
1358 | 1350 | ||
1359 | strxfrchar(dso_name, '-', '_'); | 1351 | strxfrchar(dso_name, '-', '_'); |
1360 | map = map_groups__find_by_name(kmaps, MAP__FUNCTION, dso_name); | 1352 | map = map_groups__find_by_name(&self->kmaps, MAP__FUNCTION, dso_name); |
1361 | if (map == NULL) | 1353 | if (map == NULL) |
1362 | continue; | 1354 | continue; |
1363 | 1355 | ||
@@ -1377,7 +1369,7 @@ failure: | |||
1377 | return -1; | 1369 | return -1; |
1378 | } | 1370 | } |
1379 | 1371 | ||
1380 | static int dsos__set_modules_path(void) | 1372 | static int perf_session__set_modules_path(struct perf_session *self) |
1381 | { | 1373 | { |
1382 | struct utsname uts; | 1374 | struct utsname uts; |
1383 | char modules_path[PATH_MAX]; | 1375 | char modules_path[PATH_MAX]; |
@@ -1388,7 +1380,7 @@ static int dsos__set_modules_path(void) | |||
1388 | snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", | 1380 | snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", |
1389 | uts.release); | 1381 | uts.release); |
1390 | 1382 | ||
1391 | return dsos__set_modules_path_dir(modules_path); | 1383 | return perf_session__set_modules_path_dir(self, modules_path); |
1392 | } | 1384 | } |
1393 | 1385 | ||
1394 | /* | 1386 | /* |
@@ -1410,7 +1402,7 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
1410 | return self; | 1402 | return self; |
1411 | } | 1403 | } |
1412 | 1404 | ||
1413 | static int map_groups__create_module_maps(struct map_groups *self) | 1405 | static int perf_session__create_module_maps(struct perf_session *self) |
1414 | { | 1406 | { |
1415 | char *line = NULL; | 1407 | char *line = NULL; |
1416 | size_t n; | 1408 | size_t n; |
@@ -1467,14 +1459,14 @@ static int map_groups__create_module_maps(struct map_groups *self) | |||
1467 | dso->has_build_id = true; | 1459 | dso->has_build_id = true; |
1468 | 1460 | ||
1469 | dso->origin = DSO__ORIG_KMODULE; | 1461 | dso->origin = DSO__ORIG_KMODULE; |
1470 | map_groups__insert(self, map); | 1462 | map_groups__insert(&self->kmaps, map); |
1471 | dsos__add(&dsos__kernel, dso); | 1463 | dsos__add(&dsos__kernel, dso); |
1472 | } | 1464 | } |
1473 | 1465 | ||
1474 | free(line); | 1466 | free(line); |
1475 | fclose(file); | 1467 | fclose(file); |
1476 | 1468 | ||
1477 | return dsos__set_modules_path(); | 1469 | return perf_session__set_modules_path(self); |
1478 | 1470 | ||
1479 | out_delete_line: | 1471 | out_delete_line: |
1480 | free(line); | 1472 | free(line); |
@@ -1483,7 +1475,7 @@ out_failure: | |||
1483 | } | 1475 | } |
1484 | 1476 | ||
1485 | static int dso__load_vmlinux(struct dso *self, struct map *map, | 1477 | static int dso__load_vmlinux(struct dso *self, struct map *map, |
1486 | struct map_groups *mg, | 1478 | struct perf_session *session, |
1487 | const char *vmlinux, symbol_filter_t filter) | 1479 | const char *vmlinux, symbol_filter_t filter) |
1488 | { | 1480 | { |
1489 | int err = -1, fd; | 1481 | int err = -1, fd; |
@@ -1517,14 +1509,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map, | |||
1517 | return -1; | 1509 | return -1; |
1518 | 1510 | ||
1519 | dso__set_loaded(self, map->type); | 1511 | dso__set_loaded(self, map->type); |
1520 | err = dso__load_sym(self, map, mg, self->long_name, fd, filter, 1, 0); | 1512 | err = dso__load_sym(self, map, session, self->long_name, fd, filter, 1, 0); |
1521 | close(fd); | 1513 | close(fd); |
1522 | 1514 | ||
1523 | return err; | 1515 | return err; |
1524 | } | 1516 | } |
1525 | 1517 | ||
1526 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 1518 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
1527 | struct map_groups *mg, symbol_filter_t filter) | 1519 | struct perf_session *session, symbol_filter_t filter) |
1528 | { | 1520 | { |
1529 | int err; | 1521 | int err; |
1530 | bool is_kallsyms; | 1522 | bool is_kallsyms; |
@@ -1534,7 +1526,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1534 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", | 1526 | pr_debug("Looking at the vmlinux_path (%d entries long)\n", |
1535 | vmlinux_path__nr_entries); | 1527 | vmlinux_path__nr_entries); |
1536 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { | 1528 | for (i = 0; i < vmlinux_path__nr_entries; ++i) { |
1537 | err = dso__load_vmlinux(self, map, mg, | 1529 | err = dso__load_vmlinux(self, map, session, |
1538 | vmlinux_path[i], filter); | 1530 | vmlinux_path[i], filter); |
1539 | if (err > 0) { | 1531 | if (err > 0) { |
1540 | pr_debug("Using %s for symbols\n", | 1532 | pr_debug("Using %s for symbols\n", |
@@ -1550,12 +1542,12 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map, | |||
1550 | if (is_kallsyms) | 1542 | if (is_kallsyms) |
1551 | goto do_kallsyms; | 1543 | goto do_kallsyms; |
1552 | 1544 | ||
1553 | err = dso__load_vmlinux(self, map, mg, self->long_name, filter); | 1545 | err = dso__load_vmlinux(self, map, session, self->long_name, filter); |
1554 | if (err <= 0) { | 1546 | if (err <= 0) { |
1555 | pr_info("The file %s cannot be used, " | 1547 | pr_info("The file %s cannot be used, " |
1556 | "trying to use /proc/kallsyms...", self->long_name); | 1548 | "trying to use /proc/kallsyms...", self->long_name); |
1557 | do_kallsyms: | 1549 | do_kallsyms: |
1558 | err = dso__load_kallsyms(self, map, mg, filter); | 1550 | err = dso__load_kallsyms(self, map, session, filter); |
1559 | if (err > 0 && !is_kallsyms) | 1551 | if (err > 0 && !is_kallsyms) |
1560 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); | 1552 | dso__set_long_name(self, strdup("[kernel.kallsyms]")); |
1561 | } | 1553 | } |
@@ -1757,23 +1749,30 @@ int symbol__init(struct symbol_conf *conf) | |||
1757 | if (pconf->sort_by_name) | 1749 | if (pconf->sort_by_name) |
1758 | symbol__priv_size += (sizeof(struct symbol_name_rb_node) - | 1750 | symbol__priv_size += (sizeof(struct symbol_name_rb_node) - |
1759 | sizeof(struct symbol)); | 1751 | sizeof(struct symbol)); |
1760 | map_groups__init(kmaps); | ||
1761 | 1752 | ||
1762 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) | 1753 | if (pconf->try_vmlinux_path && vmlinux_path__init() < 0) |
1763 | return -1; | 1754 | return -1; |
1764 | 1755 | ||
1765 | if (map_groups__create_kernel_maps(kmaps, pconf->vmlinux_name) < 0) { | 1756 | return 0; |
1766 | vmlinux_path__exit(); | 1757 | } |
1758 | |||
1759 | int perf_session__create_kernel_maps(struct perf_session *self, | ||
1760 | struct symbol_conf *conf) | ||
1761 | { | ||
1762 | const struct symbol_conf *pconf = conf ?: &symbol_conf__defaults; | ||
1763 | |||
1764 | if (map_groups__create_kernel_maps(&self->kmaps, | ||
1765 | pconf->vmlinux_name) < 0) | ||
1767 | return -1; | 1766 | return -1; |
1768 | } | ||
1769 | 1767 | ||
1770 | kmaps->use_modules = pconf->use_modules; | 1768 | self->use_modules = pconf->use_modules; |
1771 | if (pconf->use_modules && map_groups__create_module_maps(kmaps) < 0) | 1769 | |
1772 | pr_debug("Failed to load list of modules in use, " | 1770 | if (pconf->use_modules && perf_session__create_module_maps(self) < 0) |
1773 | "continuing...\n"); | 1771 | pr_debug("Failed to load list of modules for session %s, " |
1772 | "continuing...\n", self->filename); | ||
1774 | /* | 1773 | /* |
1775 | * Now that we have all the maps created, just set the ->end of them: | 1774 | * Now that we have all the maps created, just set the ->end of them: |
1776 | */ | 1775 | */ |
1777 | map_groups__fixup_end(kmaps); | 1776 | map_groups__fixup_end(&self->kmaps); |
1778 | return 0; | 1777 | return 0; |
1779 | } | 1778 | } |