aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c122
1 files changed, 57 insertions, 65 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index f9049d12ead6..613874260761 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1,6 +1,5 @@
1#include "util.h" 1#include "util.h"
2#include "../perf.h" 2#include "../perf.h"
3#include "session.h"
4#include "sort.h" 3#include "sort.h"
5#include "string.h" 4#include "string.h"
6#include "symbol.h" 5#include "symbol.h"
@@ -34,7 +33,7 @@ enum dso_origin {
34static void dsos__add(struct list_head *head, struct dso *dso); 33static void dsos__add(struct list_head *head, struct dso *dso);
35static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 34static struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
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 struct perf_session *session, symbol_filter_t filter); 36 symbol_filter_t filter);
38static int vmlinux_path__nr_entries; 37static int vmlinux_path__nr_entries;
39static char **vmlinux_path; 38static char **vmlinux_path;
40 39
@@ -480,8 +479,9 @@ static int dso__load_all_kallsyms(struct dso *self, const char *filename,
480 * the original ELF section names vmlinux have. 479 * the original ELF section names vmlinux have.
481 */ 480 */
482static int dso__split_kallsyms(struct dso *self, struct map *map, 481static int dso__split_kallsyms(struct dso *self, struct map *map,
483 struct perf_session *session, symbol_filter_t filter) 482 symbol_filter_t filter)
484{ 483{
484 struct map_groups *kmaps = map__kmap(map)->kmaps;
485 struct map *curr_map = map; 485 struct map *curr_map = map;
486 struct symbol *pos; 486 struct symbol *pos;
487 int count = 0; 487 int count = 0;
@@ -503,7 +503,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
503 *module++ = '\0'; 503 *module++ = '\0';
504 504
505 if (strcmp(curr_map->dso->short_name, module)) { 505 if (strcmp(curr_map->dso->short_name, module)) {
506 curr_map = map_groups__find_by_name(&session->kmaps, map->type, module); 506 curr_map = map_groups__find_by_name(kmaps, map->type, module);
507 if (curr_map == NULL) { 507 if (curr_map == NULL) {
508 pr_debug("/proc/{kallsyms,modules} " 508 pr_debug("/proc/{kallsyms,modules} "
509 "inconsistency while looking " 509 "inconsistency while looking "
@@ -538,7 +538,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map,
538 } 538 }
539 539
540 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 540 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
541 map_groups__insert(&session->kmaps, curr_map); 541 map_groups__insert(kmaps, curr_map);
542 ++kernel_range; 542 ++kernel_range;
543 } 543 }
544 544
@@ -557,9 +557,8 @@ discard_symbol: rb_erase(&pos->rb_node, root);
557 return count; 557 return count;
558} 558}
559 559
560 560int dso__load_kallsyms(struct dso *self, const char *filename,
561static int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map, 561 struct map *map, symbol_filter_t filter)
562 struct perf_session *session, symbol_filter_t filter)
563{ 562{
564 if (dso__load_all_kallsyms(self, filename, map) < 0) 563 if (dso__load_all_kallsyms(self, filename, map) < 0)
565 return -1; 564 return -1;
@@ -567,7 +566,7 @@ static int dso__load_kallsyms(struct dso *self, const char *filename, struct map
567 symbols__fixup_end(&self->symbols[map->type]); 566 symbols__fixup_end(&self->symbols[map->type]);
568 self->origin = DSO__ORIG_KERNEL; 567 self->origin = DSO__ORIG_KERNEL;
569 568
570 return dso__split_kallsyms(self, map, session, filter); 569 return dso__split_kallsyms(self, map, filter);
571} 570}
572 571
573static int dso__load_perf_map(struct dso *self, struct map *map, 572static int dso__load_perf_map(struct dso *self, struct map *map,
@@ -893,10 +892,10 @@ static bool elf_sec__is_a(GElf_Shdr *self, Elf_Data *secstrs, enum map_type type
893 } 892 }
894} 893}
895 894
896static int dso__load_sym(struct dso *self, struct map *map, 895static int dso__load_sym(struct dso *self, struct map *map, const char *name,
897 struct perf_session *session, const char *name, int fd, 896 int fd, symbol_filter_t filter, int kmodule)
898 symbol_filter_t filter, int kernel, int kmodule)
899{ 897{
898 struct kmap *kmap = self->kernel ? map__kmap(map) : NULL;
900 struct map *curr_map = map; 899 struct map *curr_map = map;
901 struct dso *curr_dso = self; 900 struct dso *curr_dso = self;
902 size_t dso_name_len = strlen(self->short_name); 901 size_t dso_name_len = strlen(self->short_name);
@@ -953,7 +952,7 @@ static int dso__load_sym(struct dso *self, struct map *map,
953 nr_syms = shdr.sh_size / shdr.sh_entsize; 952 nr_syms = shdr.sh_size / shdr.sh_entsize;
954 953
955 memset(&sym, 0, sizeof(sym)); 954 memset(&sym, 0, sizeof(sym));
956 if (!kernel) { 955 if (!self->kernel) {
957 self->adjust_symbols = (ehdr.e_type == ET_EXEC || 956 self->adjust_symbols = (ehdr.e_type == ET_EXEC ||
958 elf_section_by_name(elf, &ehdr, &shdr, 957 elf_section_by_name(elf, &ehdr, &shdr,
959 ".gnu.prelink_undo", 958 ".gnu.prelink_undo",
@@ -967,9 +966,9 @@ static int dso__load_sym(struct dso *self, struct map *map,
967 int is_label = elf_sym__is_label(&sym); 966 int is_label = elf_sym__is_label(&sym);
968 const char *section_name; 967 const char *section_name;
969 968
970 if (kernel && session->ref_reloc_sym.name != NULL && 969 if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name &&
971 strcmp(elf_name, session->ref_reloc_sym.name) == 0) 970 strcmp(elf_name, kmap->ref_reloc_sym->name) == 0)
972 perf_session__reloc_vmlinux_maps(session, sym.st_value); 971 kmap->ref_reloc_sym->unrelocated_addr = sym.st_value;
973 972
974 if (!is_label && !elf_sym__is_a(&sym, map->type)) 973 if (!is_label && !elf_sym__is_a(&sym, map->type))
975 continue; 974 continue;
@@ -985,7 +984,7 @@ static int dso__load_sym(struct dso *self, struct map *map,
985 984
986 section_name = elf_sec__name(&shdr, secstrs); 985 section_name = elf_sec__name(&shdr, secstrs);
987 986
988 if (kernel || kmodule) { 987 if (self->kernel || kmodule) {
989 char dso_name[PATH_MAX]; 988 char dso_name[PATH_MAX];
990 989
991 if (strcmp(section_name, 990 if (strcmp(section_name,
@@ -1001,7 +1000,7 @@ static int dso__load_sym(struct dso *self, struct map *map,
1001 snprintf(dso_name, sizeof(dso_name), 1000 snprintf(dso_name, sizeof(dso_name),
1002 "%s%s", self->short_name, section_name); 1001 "%s%s", self->short_name, section_name);
1003 1002
1004 curr_map = map_groups__find_by_name(&session->kmaps, map->type, dso_name); 1003 curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name);
1005 if (curr_map == NULL) { 1004 if (curr_map == NULL) {
1006 u64 start = sym.st_value; 1005 u64 start = sym.st_value;
1007 1006
@@ -1020,7 +1019,7 @@ static int dso__load_sym(struct dso *self, struct map *map,
1020 curr_map->map_ip = identity__map_ip; 1019 curr_map->map_ip = identity__map_ip;
1021 curr_map->unmap_ip = identity__map_ip; 1020 curr_map->unmap_ip = identity__map_ip;
1022 curr_dso->origin = DSO__ORIG_KERNEL; 1021 curr_dso->origin = DSO__ORIG_KERNEL;
1023 map_groups__insert(&session->kmaps, curr_map); 1022 map_groups__insert(kmap->kmaps, curr_map);
1024 dsos__add(&dsos__kernel, curr_dso); 1023 dsos__add(&dsos__kernel, curr_dso);
1025 } else 1024 } else
1026 curr_dso = curr_map->dso; 1025 curr_dso = curr_map->dso;
@@ -1236,8 +1235,7 @@ char dso__symtab_origin(const struct dso *self)
1236 return origin[self->origin]; 1235 return origin[self->origin];
1237} 1236}
1238 1237
1239int dso__load(struct dso *self, struct map *map, struct perf_session *session, 1238int dso__load(struct dso *self, struct map *map, symbol_filter_t filter)
1240 symbol_filter_t filter)
1241{ 1239{
1242 int size = PATH_MAX; 1240 int size = PATH_MAX;
1243 char *name; 1241 char *name;
@@ -1249,7 +1247,7 @@ int dso__load(struct dso *self, struct map *map, struct perf_session *session,
1249 dso__set_loaded(self, map->type); 1247 dso__set_loaded(self, map->type);
1250 1248
1251 if (self->kernel) 1249 if (self->kernel)
1252 return dso__load_kernel_sym(self, map, session, filter); 1250 return dso__load_kernel_sym(self, map, filter);
1253 1251
1254 name = malloc(size); 1252 name = malloc(size);
1255 if (!name) 1253 if (!name)
@@ -1320,7 +1318,7 @@ open_file:
1320 fd = open(name, O_RDONLY); 1318 fd = open(name, O_RDONLY);
1321 } while (fd < 0); 1319 } while (fd < 0);
1322 1320
1323 ret = dso__load_sym(self, map, NULL, name, fd, filter, 0, 0); 1321 ret = dso__load_sym(self, map, name, fd, filter, 0);
1324 close(fd); 1322 close(fd);
1325 1323
1326 /* 1324 /*
@@ -1376,7 +1374,7 @@ static int dso__kernel_module_get_build_id(struct dso *self)
1376 return 0; 1374 return 0;
1377} 1375}
1378 1376
1379static int perf_session__set_modules_path_dir(struct perf_session *self, char *dirname) 1377static int map_groups__set_modules_path_dir(struct map_groups *self, char *dirname)
1380{ 1378{
1381 struct dirent *dent; 1379 struct dirent *dent;
1382 DIR *dir = opendir(dirname); 1380 DIR *dir = opendir(dirname);
@@ -1396,7 +1394,7 @@ static int perf_session__set_modules_path_dir(struct perf_session *self, char *d
1396 1394
1397 snprintf(path, sizeof(path), "%s/%s", 1395 snprintf(path, sizeof(path), "%s/%s",
1398 dirname, dent->d_name); 1396 dirname, dent->d_name);
1399 if (perf_session__set_modules_path_dir(self, path) < 0) 1397 if (map_groups__set_modules_path_dir(self, path) < 0)
1400 goto failure; 1398 goto failure;
1401 } else { 1399 } else {
1402 char *dot = strrchr(dent->d_name, '.'), 1400 char *dot = strrchr(dent->d_name, '.'),
@@ -1410,7 +1408,7 @@ static int perf_session__set_modules_path_dir(struct perf_session *self, char *d
1410 (int)(dot - dent->d_name), dent->d_name); 1408 (int)(dot - dent->d_name), dent->d_name);
1411 1409
1412 strxfrchar(dso_name, '-', '_'); 1410 strxfrchar(dso_name, '-', '_');
1413 map = map_groups__find_by_name(&self->kmaps, MAP__FUNCTION, dso_name); 1411 map = map_groups__find_by_name(self, MAP__FUNCTION, dso_name);
1414 if (map == NULL) 1412 if (map == NULL)
1415 continue; 1413 continue;
1416 1414
@@ -1431,7 +1429,7 @@ failure:
1431 return -1; 1429 return -1;
1432} 1430}
1433 1431
1434static int perf_session__set_modules_path(struct perf_session *self) 1432static int map_groups__set_modules_path(struct map_groups *self)
1435{ 1433{
1436 struct utsname uts; 1434 struct utsname uts;
1437 char modules_path[PATH_MAX]; 1435 char modules_path[PATH_MAX];
@@ -1442,7 +1440,7 @@ static int perf_session__set_modules_path(struct perf_session *self)
1442 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", 1440 snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel",
1443 uts.release); 1441 uts.release);
1444 1442
1445 return perf_session__set_modules_path_dir(self, modules_path); 1443 return map_groups__set_modules_path_dir(self, modules_path);
1446} 1444}
1447 1445
1448/* 1446/*
@@ -1452,8 +1450,8 @@ static int perf_session__set_modules_path(struct perf_session *self)
1452 */ 1450 */
1453static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) 1451static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1454{ 1452{
1455 struct map *self = malloc(sizeof(*self)); 1453 struct map *self = zalloc(sizeof(*self) +
1456 1454 (dso->kernel ? sizeof(struct kmap) : 0));
1457 if (self != NULL) { 1455 if (self != NULL) {
1458 /* 1456 /*
1459 * ->end will be filled after we load all the symbols 1457 * ->end will be filled after we load all the symbols
@@ -1464,8 +1462,8 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type)
1464 return self; 1462 return self;
1465} 1463}
1466 1464
1467struct map *perf_session__new_module_map(struct perf_session *self, u64 start, 1465struct map *map_groups__new_module(struct map_groups *self, u64 start,
1468 const char *filename) 1466 const char *filename)
1469{ 1467{
1470 struct map *map; 1468 struct map *map;
1471 struct dso *dso = __dsos__findnew(&dsos__kernel, filename); 1469 struct dso *dso = __dsos__findnew(&dsos__kernel, filename);
@@ -1478,11 +1476,11 @@ struct map *perf_session__new_module_map(struct perf_session *self, u64 start,
1478 return NULL; 1476 return NULL;
1479 1477
1480 dso->origin = DSO__ORIG_KMODULE; 1478 dso->origin = DSO__ORIG_KMODULE;
1481 map_groups__insert(&self->kmaps, map); 1479 map_groups__insert(self, map);
1482 return map; 1480 return map;
1483} 1481}
1484 1482
1485static int perf_session__create_module_maps(struct perf_session *self) 1483static int map_groups__create_modules(struct map_groups *self)
1486{ 1484{
1487 char *line = NULL; 1485 char *line = NULL;
1488 size_t n; 1486 size_t n;
@@ -1520,7 +1518,7 @@ static int perf_session__create_module_maps(struct perf_session *self)
1520 *sep = '\0'; 1518 *sep = '\0';
1521 1519
1522 snprintf(name, sizeof(name), "[%s]", line); 1520 snprintf(name, sizeof(name), "[%s]", line);
1523 map = perf_session__new_module_map(self, start, name); 1521 map = map_groups__new_module(self, start, name);
1524 if (map == NULL) 1522 if (map == NULL)
1525 goto out_delete_line; 1523 goto out_delete_line;
1526 dso__kernel_module_get_build_id(map->dso); 1524 dso__kernel_module_get_build_id(map->dso);
@@ -1529,7 +1527,7 @@ static int perf_session__create_module_maps(struct perf_session *self)
1529 free(line); 1527 free(line);
1530 fclose(file); 1528 fclose(file);
1531 1529
1532 return perf_session__set_modules_path(self); 1530 return map_groups__set_modules_path(self);
1533 1531
1534out_delete_line: 1532out_delete_line:
1535 free(line); 1533 free(line);
@@ -1538,7 +1536,6 @@ out_failure:
1538} 1536}
1539 1537
1540static int dso__load_vmlinux(struct dso *self, struct map *map, 1538static int dso__load_vmlinux(struct dso *self, struct map *map,
1541 struct perf_session *session,
1542 const char *vmlinux, symbol_filter_t filter) 1539 const char *vmlinux, symbol_filter_t filter)
1543{ 1540{
1544 int err = -1, fd; 1541 int err = -1, fd;
@@ -1572,14 +1569,14 @@ static int dso__load_vmlinux(struct dso *self, struct map *map,
1572 return -1; 1569 return -1;
1573 1570
1574 dso__set_loaded(self, map->type); 1571 dso__set_loaded(self, map->type);
1575 err = dso__load_sym(self, map, session, vmlinux, fd, filter, 1, 0); 1572 err = dso__load_sym(self, map, vmlinux, fd, filter, 0);
1576 close(fd); 1573 close(fd);
1577 1574
1578 return err; 1575 return err;
1579} 1576}
1580 1577
1581int dso__load_vmlinux_path(struct dso *self, struct map *map, 1578int dso__load_vmlinux_path(struct dso *self, struct map *map,
1582 struct perf_session *session, symbol_filter_t filter) 1579 symbol_filter_t filter)
1583{ 1580{
1584 int i, err = 0; 1581 int i, err = 0;
1585 1582
@@ -1587,8 +1584,7 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map,
1587 vmlinux_path__nr_entries); 1584 vmlinux_path__nr_entries);
1588 1585
1589 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1586 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1590 err = dso__load_vmlinux(self, map, session, vmlinux_path[i], 1587 err = dso__load_vmlinux(self, map, vmlinux_path[i], filter);
1591 filter);
1592 if (err > 0) { 1588 if (err > 0) {
1593 pr_debug("Using %s for symbols\n", vmlinux_path[i]); 1589 pr_debug("Using %s for symbols\n", vmlinux_path[i]);
1594 dso__set_long_name(self, strdup(vmlinux_path[i])); 1590 dso__set_long_name(self, strdup(vmlinux_path[i]));
@@ -1600,7 +1596,7 @@ int dso__load_vmlinux_path(struct dso *self, struct map *map,
1600} 1596}
1601 1597
1602static int dso__load_kernel_sym(struct dso *self, struct map *map, 1598static int dso__load_kernel_sym(struct dso *self, struct map *map,
1603 struct perf_session *session, symbol_filter_t filter) 1599 symbol_filter_t filter)
1604{ 1600{
1605 int err; 1601 int err;
1606 const char *kallsyms_filename = NULL; 1602 const char *kallsyms_filename = NULL;
@@ -1621,13 +1617,13 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1621 * match. 1617 * match.
1622 */ 1618 */
1623 if (symbol_conf.vmlinux_name != NULL) { 1619 if (symbol_conf.vmlinux_name != NULL) {
1624 err = dso__load_vmlinux(self, map, session, 1620 err = dso__load_vmlinux(self, map,
1625 symbol_conf.vmlinux_name, filter); 1621 symbol_conf.vmlinux_name, filter);
1626 goto out_try_fixup; 1622 goto out_try_fixup;
1627 } 1623 }
1628 1624
1629 if (vmlinux_path != NULL) { 1625 if (vmlinux_path != NULL) {
1630 err = dso__load_vmlinux_path(self, map, session, filter); 1626 err = dso__load_vmlinux_path(self, map, filter);
1631 if (err > 0) 1627 if (err > 0)
1632 goto out_fixup; 1628 goto out_fixup;
1633 } 1629 }
@@ -1675,7 +1671,7 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
1675 } 1671 }
1676 1672
1677do_kallsyms: 1673do_kallsyms:
1678 err = dso__load_kallsyms(self, kallsyms_filename, map, session, filter); 1674 err = dso__load_kallsyms(self, kallsyms_filename, map, filter);
1679 free(kallsyms_allocated_filename); 1675 free(kallsyms_allocated_filename);
1680 1676
1681out_try_fixup: 1677out_try_fixup:
@@ -1812,30 +1808,23 @@ int __map_groups__create_kernel_maps(struct map_groups *self,
1812 enum map_type type; 1808 enum map_type type;
1813 1809
1814 for (type = 0; type < MAP__NR_TYPES; ++type) { 1810 for (type = 0; type < MAP__NR_TYPES; ++type) {
1811 struct kmap *kmap;
1812
1815 vmlinux_maps[type] = map__new2(0, kernel, type); 1813 vmlinux_maps[type] = map__new2(0, kernel, type);
1816 if (vmlinux_maps[type] == NULL) 1814 if (vmlinux_maps[type] == NULL)
1817 return -1; 1815 return -1;
1818 1816
1819 vmlinux_maps[type]->map_ip = 1817 vmlinux_maps[type]->map_ip =
1820 vmlinux_maps[type]->unmap_ip = identity__map_ip; 1818 vmlinux_maps[type]->unmap_ip = identity__map_ip;
1819
1820 kmap = map__kmap(vmlinux_maps[type]);
1821 kmap->kmaps = self;
1821 map_groups__insert(self, vmlinux_maps[type]); 1822 map_groups__insert(self, vmlinux_maps[type]);
1822 } 1823 }
1823 1824
1824 return 0; 1825 return 0;
1825} 1826}
1826 1827
1827static int map_groups__create_kernel_maps(struct map_groups *self,
1828 struct map *vmlinux_maps[MAP__NR_TYPES],
1829 const char *vmlinux)
1830{
1831 struct dso *kernel = dsos__create_kernel(vmlinux);
1832
1833 if (kernel == NULL)
1834 return -1;
1835
1836 return __map_groups__create_kernel_maps(self, vmlinux_maps, kernel);
1837}
1838
1839static void vmlinux_path__exit(void) 1828static void vmlinux_path__exit(void)
1840{ 1829{
1841 while (--vmlinux_path__nr_entries >= 0) { 1830 while (--vmlinux_path__nr_entries >= 0) {
@@ -1941,19 +1930,22 @@ out_free_comm_list:
1941 return -1; 1930 return -1;
1942} 1931}
1943 1932
1944int perf_session__create_kernel_maps(struct perf_session *self) 1933int map_groups__create_kernel_maps(struct map_groups *self,
1934 struct map *vmlinux_maps[MAP__NR_TYPES])
1945{ 1935{
1946 if (map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps, 1936 struct dso *kernel = dsos__create_kernel(symbol_conf.vmlinux_name);
1947 symbol_conf.vmlinux_name) < 0) 1937
1938 if (kernel == NULL)
1939 return -1;
1940
1941 if (__map_groups__create_kernel_maps(self, vmlinux_maps, kernel) < 0)
1948 return -1; 1942 return -1;
1949 1943
1950 if (symbol_conf.use_modules && 1944 if (symbol_conf.use_modules && map_groups__create_modules(self) < 0)
1951 perf_session__create_module_maps(self) < 0) 1945 return -1;
1952 pr_debug("Failed to load list of modules for session %s, "
1953 "continuing...\n", self->filename);
1954 /* 1946 /*
1955 * Now that we have all the maps created, just set the ->end of them: 1947 * Now that we have all the maps created, just set the ->end of them:
1956 */ 1948 */
1957 map_groups__fixup_end(&self->kmaps); 1949 map_groups__fixup_end(self);
1958 return 0; 1950 return 0;
1959} 1951}