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.c232
1 files changed, 122 insertions, 110 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index c0c36965fff0..e89afc097d8a 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -18,12 +18,9 @@
18 18
19#include <elf.h> 19#include <elf.h>
20#include <limits.h> 20#include <limits.h>
21#include <symbol/kallsyms.h>
21#include <sys/utsname.h> 22#include <sys/utsname.h>
22 23
23#ifndef KSYM_NAME_LEN
24#define KSYM_NAME_LEN 256
25#endif
26
27static int dso__load_kernel_sym(struct dso *dso, struct map *map, 24static int dso__load_kernel_sym(struct dso *dso, struct map *map,
28 symbol_filter_t filter); 25 symbol_filter_t filter);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 26static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
@@ -446,62 +443,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
446 return ret; 443 return ret;
447} 444}
448 445
449int kallsyms__parse(const char *filename, void *arg,
450 int (*process_symbol)(void *arg, const char *name,
451 char type, u64 start))
452{
453 char *line = NULL;
454 size_t n;
455 int err = -1;
456 FILE *file = fopen(filename, "r");
457
458 if (file == NULL)
459 goto out_failure;
460
461 err = 0;
462
463 while (!feof(file)) {
464 u64 start;
465 int line_len, len;
466 char symbol_type;
467 char *symbol_name;
468
469 line_len = getline(&line, &n, file);
470 if (line_len < 0 || !line)
471 break;
472
473 line[--line_len] = '\0'; /* \n */
474
475 len = hex2u64(line, &start);
476
477 len++;
478 if (len + 2 >= line_len)
479 continue;
480
481 symbol_type = line[len];
482 len += 2;
483 symbol_name = line + len;
484 len = line_len - len;
485
486 if (len >= KSYM_NAME_LEN) {
487 err = -1;
488 break;
489 }
490
491 err = process_symbol(arg, symbol_name,
492 symbol_type, start);
493 if (err)
494 break;
495 }
496
497 free(line);
498 fclose(file);
499 return err;
500
501out_failure:
502 return -1;
503}
504
505int modules__parse(const char *filename, void *arg, 446int modules__parse(const char *filename, void *arg,
506 int (*process_module)(void *arg, const char *name, 447 int (*process_module)(void *arg, const char *name,
507 u64 start)) 448 u64 start))
@@ -565,12 +506,34 @@ struct process_kallsyms_args {
565 struct dso *dso; 506 struct dso *dso;
566}; 507};
567 508
568static u8 kallsyms2elf_type(char type) 509bool symbol__is_idle(struct symbol *sym)
569{ 510{
570 if (type == 'W') 511 const char * const idle_symbols[] = {
571 return STB_WEAK; 512 "cpu_idle",
513 "intel_idle",
514 "default_idle",
515 "native_safe_halt",
516 "enter_idle",
517 "exit_idle",
518 "mwait_idle",
519 "mwait_idle_with_hints",
520 "poll_idle",
521 "ppc64_runlatch_off",
522 "pseries_dedicated_idle_sleep",
523 NULL
524 };
525
526 int i;
527
528 if (!sym)
529 return false;
572 530
573 return isupper(type) ? STB_GLOBAL : STB_LOCAL; 531 for (i = 0; idle_symbols[i]; i++) {
532 if (!strcmp(idle_symbols[i], sym->name))
533 return true;
534 }
535
536 return false;
574} 537}
575 538
576static int map__process_kallsym_symbol(void *arg, const char *name, 539static int map__process_kallsym_symbol(void *arg, const char *name,
@@ -664,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
664 * kernel range is broken in several maps, named [kernel].N, as we don't have 627 * kernel range is broken in several maps, named [kernel].N, as we don't have
665 * the original ELF section names vmlinux have. 628 * the original ELF section names vmlinux have.
666 */ 629 */
667static int dso__split_kallsyms(struct dso *dso, struct map *map, 630static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
668 symbol_filter_t filter) 631 symbol_filter_t filter)
669{ 632{
670 struct map_groups *kmaps = map__kmap(map)->kmaps; 633 struct map_groups *kmaps = map__kmap(map)->kmaps;
@@ -729,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
729 char dso_name[PATH_MAX]; 692 char dso_name[PATH_MAX];
730 struct dso *ndso; 693 struct dso *ndso;
731 694
695 if (delta) {
696 /* Kernel was relocated at boot time */
697 pos->start -= delta;
698 pos->end -= delta;
699 }
700
732 if (count == 0) { 701 if (count == 0) {
733 curr_map = map; 702 curr_map = map;
734 goto filter_symbol; 703 goto filter_symbol;
@@ -758,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map,
758 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; 727 curr_map->map_ip = curr_map->unmap_ip = identity__map_ip;
759 map_groups__insert(kmaps, curr_map); 728 map_groups__insert(kmaps, curr_map);
760 ++kernel_range; 729 ++kernel_range;
730 } else if (delta) {
731 /* Kernel was relocated at boot time */
732 pos->start -= delta;
733 pos->end -= delta;
761 } 734 }
762filter_symbol: 735filter_symbol:
763 if (filter && filter(curr_map, pos)) { 736 if (filter && filter(curr_map, pos)) {
@@ -833,7 +806,7 @@ static void delete_modules(struct rb_root *modules)
833 mi = rb_entry(next, struct module_info, rb_node); 806 mi = rb_entry(next, struct module_info, rb_node);
834 next = rb_next(&mi->rb_node); 807 next = rb_next(&mi->rb_node);
835 rb_erase(&mi->rb_node, modules); 808 rb_erase(&mi->rb_node, modules);
836 free(mi->name); 809 zfree(&mi->name);
837 free(mi); 810 free(mi);
838 } 811 }
839} 812}
@@ -1013,6 +986,23 @@ static int validate_kcore_modules(const char *kallsyms_filename,
1013 return 0; 986 return 0;
1014} 987}
1015 988
989static int validate_kcore_addresses(const char *kallsyms_filename,
990 struct map *map)
991{
992 struct kmap *kmap = map__kmap(map);
993
994 if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
995 u64 start;
996
997 start = kallsyms__get_function_start(kallsyms_filename,
998 kmap->ref_reloc_sym->name);
999 if (start != kmap->ref_reloc_sym->addr)
1000 return -EINVAL;
1001 }
1002
1003 return validate_kcore_modules(kallsyms_filename, map);
1004}
1005
1016struct kcore_mapfn_data { 1006struct kcore_mapfn_data {
1017 struct dso *dso; 1007 struct dso *dso;
1018 enum map_type type; 1008 enum map_type type;
@@ -1056,8 +1046,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1056 kallsyms_filename)) 1046 kallsyms_filename))
1057 return -EINVAL; 1047 return -EINVAL;
1058 1048
1059 /* All modules must be present at their original addresses */ 1049 /* Modules and kernel must be present at their original addresses */
1060 if (validate_kcore_modules(kallsyms_filename, map)) 1050 if (validate_kcore_addresses(kallsyms_filename, map))
1061 return -EINVAL; 1051 return -EINVAL;
1062 1052
1063 md.dso = dso; 1053 md.dso = dso;
@@ -1126,10 +1116,10 @@ static int dso__load_kcore(struct dso *dso, struct map *map,
1126 * dso__data_read_addr(). 1116 * dso__data_read_addr().
1127 */ 1117 */
1128 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1118 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1129 dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; 1119 dso->binary_type = DSO_BINARY_TYPE__GUEST_KCORE;
1130 else 1120 else
1131 dso->data_type = DSO_BINARY_TYPE__KCORE; 1121 dso->binary_type = DSO_BINARY_TYPE__KCORE;
1132 dso__set_long_name(dso, strdup(kcore_filename)); 1122 dso__set_long_name(dso, strdup(kcore_filename), true);
1133 1123
1134 close(fd); 1124 close(fd);
1135 1125
@@ -1150,15 +1140,41 @@ out_err:
1150 return -EINVAL; 1140 return -EINVAL;
1151} 1141}
1152 1142
1143/*
1144 * If the kernel is relocated at boot time, kallsyms won't match. Compute the
1145 * delta based on the relocation reference symbol.
1146 */
1147static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1148{
1149 struct kmap *kmap = map__kmap(map);
1150 u64 addr;
1151
1152 if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
1153 return 0;
1154
1155 addr = kallsyms__get_function_start(filename,
1156 kmap->ref_reloc_sym->name);
1157 if (!addr)
1158 return -1;
1159
1160 *delta = addr - kmap->ref_reloc_sym->addr;
1161 return 0;
1162}
1163
1153int dso__load_kallsyms(struct dso *dso, const char *filename, 1164int dso__load_kallsyms(struct dso *dso, const char *filename,
1154 struct map *map, symbol_filter_t filter) 1165 struct map *map, symbol_filter_t filter)
1155{ 1166{
1167 u64 delta = 0;
1168
1156 if (symbol__restricted_filename(filename, "/proc/kallsyms")) 1169 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
1157 return -1; 1170 return -1;
1158 1171
1159 if (dso__load_all_kallsyms(dso, filename, map) < 0) 1172 if (dso__load_all_kallsyms(dso, filename, map) < 0)
1160 return -1; 1173 return -1;
1161 1174
1175 if (kallsyms__delta(map, filename, &delta))
1176 return -1;
1177
1162 symbols__fixup_duplicate(&dso->symbols[map->type]); 1178 symbols__fixup_duplicate(&dso->symbols[map->type]);
1163 symbols__fixup_end(&dso->symbols[map->type]); 1179 symbols__fixup_end(&dso->symbols[map->type]);
1164 1180
@@ -1170,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
1170 if (!dso__load_kcore(dso, map, filename)) 1186 if (!dso__load_kcore(dso, map, filename))
1171 return dso__split_kallsyms_for_kcore(dso, map, filter); 1187 return dso__split_kallsyms_for_kcore(dso, map, filter);
1172 else 1188 else
1173 return dso__split_kallsyms(dso, map, filter); 1189 return dso__split_kallsyms(dso, map, delta, filter);
1174} 1190}
1175 1191
1176static int dso__load_perf_map(struct dso *dso, struct map *map, 1192static int dso__load_perf_map(struct dso *dso, struct map *map,
@@ -1295,8 +1311,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1295 1311
1296 enum dso_binary_type symtab_type = binary_type_symtab[i]; 1312 enum dso_binary_type symtab_type = binary_type_symtab[i];
1297 1313
1298 if (dso__binary_type_file(dso, symtab_type, 1314 if (dso__read_binary_type_filename(dso, symtab_type,
1299 root_dir, name, PATH_MAX)) 1315 root_dir, name, PATH_MAX))
1300 continue; 1316 continue;
1301 1317
1302 /* Name is now the name of the next image to try */ 1318 /* Name is now the name of the next image to try */
@@ -1306,6 +1322,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1306 if (!syms_ss && symsrc__has_symtab(ss)) { 1322 if (!syms_ss && symsrc__has_symtab(ss)) {
1307 syms_ss = ss; 1323 syms_ss = ss;
1308 next_slot = true; 1324 next_slot = true;
1325 if (!dso->symsrc_filename)
1326 dso->symsrc_filename = strdup(name);
1309 } 1327 }
1310 1328
1311 if (!runtime_ss && symsrc__possibly_runtime(ss)) { 1329 if (!runtime_ss && symsrc__possibly_runtime(ss)) {
@@ -1318,6 +1336,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1318 1336
1319 if (syms_ss && runtime_ss) 1337 if (syms_ss && runtime_ss)
1320 break; 1338 break;
1339 } else {
1340 symsrc__destroy(ss);
1321 } 1341 }
1322 1342
1323 } 1343 }
@@ -1376,7 +1396,8 @@ struct map *map_groups__find_by_name(struct map_groups *mg,
1376} 1396}
1377 1397
1378int dso__load_vmlinux(struct dso *dso, struct map *map, 1398int dso__load_vmlinux(struct dso *dso, struct map *map,
1379 const char *vmlinux, symbol_filter_t filter) 1399 const char *vmlinux, bool vmlinux_allocated,
1400 symbol_filter_t filter)
1380{ 1401{
1381 int err = -1; 1402 int err = -1;
1382 struct symsrc ss; 1403 struct symsrc ss;
@@ -1402,10 +1423,10 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1402 1423
1403 if (err > 0) { 1424 if (err > 0) {
1404 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1425 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1405 dso->data_type = DSO_BINARY_TYPE__GUEST_VMLINUX; 1426 dso->binary_type = DSO_BINARY_TYPE__GUEST_VMLINUX;
1406 else 1427 else
1407 dso->data_type = DSO_BINARY_TYPE__VMLINUX; 1428 dso->binary_type = DSO_BINARY_TYPE__VMLINUX;
1408 dso__set_long_name(dso, (char *)vmlinux); 1429 dso__set_long_name(dso, vmlinux, vmlinux_allocated);
1409 dso__set_loaded(dso, map->type); 1430 dso__set_loaded(dso, map->type);
1410 pr_debug("Using %s for symbols\n", symfs_vmlinux); 1431 pr_debug("Using %s for symbols\n", symfs_vmlinux);
1411 } 1432 }
@@ -1424,21 +1445,16 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1424 1445
1425 filename = dso__build_id_filename(dso, NULL, 0); 1446 filename = dso__build_id_filename(dso, NULL, 0);
1426 if (filename != NULL) { 1447 if (filename != NULL) {
1427 err = dso__load_vmlinux(dso, map, filename, filter); 1448 err = dso__load_vmlinux(dso, map, filename, true, filter);
1428 if (err > 0) { 1449 if (err > 0)
1429 dso->lname_alloc = 1;
1430 goto out; 1450 goto out;
1431 }
1432 free(filename); 1451 free(filename);
1433 } 1452 }
1434 1453
1435 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1454 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1436 err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); 1455 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter);
1437 if (err > 0) { 1456 if (err > 0)
1438 dso__set_long_name(dso, strdup(vmlinux_path[i]));
1439 dso->lname_alloc = 1;
1440 break; 1457 break;
1441 }
1442 } 1458 }
1443out: 1459out:
1444 return err; 1460 return err;
@@ -1463,7 +1479,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1463 continue; 1479 continue;
1464 scnprintf(kallsyms_filename, sizeof(kallsyms_filename), 1480 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1465 "%s/%s/kallsyms", dir, dent->d_name); 1481 "%s/%s/kallsyms", dir, dent->d_name);
1466 if (!validate_kcore_modules(kallsyms_filename, map)) { 1482 if (!validate_kcore_addresses(kallsyms_filename, map)) {
1467 strlcpy(dir, kallsyms_filename, dir_sz); 1483 strlcpy(dir, kallsyms_filename, dir_sz);
1468 ret = 0; 1484 ret = 0;
1469 break; 1485 break;
@@ -1496,14 +1512,15 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1496 1512
1497 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1513 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1498 1514
1515 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
1516 sbuild_id);
1517
1499 /* Use /proc/kallsyms if possible */ 1518 /* Use /proc/kallsyms if possible */
1500 if (is_host) { 1519 if (is_host) {
1501 DIR *d; 1520 DIR *d;
1502 int fd; 1521 int fd;
1503 1522
1504 /* If no cached kcore go with /proc/kallsyms */ 1523 /* If no cached kcore go with /proc/kallsyms */
1505 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s",
1506 buildid_dir, sbuild_id);
1507 d = opendir(path); 1524 d = opendir(path);
1508 if (!d) 1525 if (!d)
1509 goto proc_kallsyms; 1526 goto proc_kallsyms;
@@ -1517,7 +1534,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1517 if (fd != -1) { 1534 if (fd != -1) {
1518 close(fd); 1535 close(fd);
1519 /* If module maps match go with /proc/kallsyms */ 1536 /* If module maps match go with /proc/kallsyms */
1520 if (!validate_kcore_modules("/proc/kallsyms", map)) 1537 if (!validate_kcore_addresses("/proc/kallsyms", map))
1521 goto proc_kallsyms; 1538 goto proc_kallsyms;
1522 } 1539 }
1523 1540
@@ -1528,6 +1545,10 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1528 goto proc_kallsyms; 1545 goto proc_kallsyms;
1529 } 1546 }
1530 1547
1548 /* Find kallsyms in build-id cache with kcore */
1549 if (!find_matching_kcore(map, path, sizeof(path)))
1550 return strdup(path);
1551
1531 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", 1552 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s",
1532 buildid_dir, sbuild_id); 1553 buildid_dir, sbuild_id);
1533 1554
@@ -1570,15 +1591,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1570 } 1591 }
1571 1592
1572 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { 1593 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1573 err = dso__load_vmlinux(dso, map, 1594 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name,
1574 symbol_conf.vmlinux_name, filter); 1595 false, filter);
1575 if (err > 0) {
1576 dso__set_long_name(dso,
1577 strdup(symbol_conf.vmlinux_name));
1578 dso->lname_alloc = 1;
1579 return err;
1580 }
1581 return err;
1582 } 1596 }
1583 1597
1584 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { 1598 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
@@ -1604,7 +1618,7 @@ do_kallsyms:
1604 free(kallsyms_allocated_filename); 1618 free(kallsyms_allocated_filename);
1605 1619
1606 if (err > 0 && !dso__is_kcore(dso)) { 1620 if (err > 0 && !dso__is_kcore(dso)) {
1607 dso__set_long_name(dso, strdup("[kernel.kallsyms]")); 1621 dso__set_long_name(dso, "[kernel.kallsyms]", false);
1608 map__fixup_start(map); 1622 map__fixup_start(map);
1609 map__fixup_end(map); 1623 map__fixup_end(map);
1610 } 1624 }
@@ -1634,7 +1648,8 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1634 */ 1648 */
1635 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1649 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1636 err = dso__load_vmlinux(dso, map, 1650 err = dso__load_vmlinux(dso, map,
1637 symbol_conf.default_guest_vmlinux_name, filter); 1651 symbol_conf.default_guest_vmlinux_name,
1652 false, filter);
1638 return err; 1653 return err;
1639 } 1654 }
1640 1655
@@ -1651,7 +1666,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1651 pr_debug("Using %s for symbols\n", kallsyms_filename); 1666 pr_debug("Using %s for symbols\n", kallsyms_filename);
1652 if (err > 0 && !dso__is_kcore(dso)) { 1667 if (err > 0 && !dso__is_kcore(dso)) {
1653 machine__mmap_name(machine, path, sizeof(path)); 1668 machine__mmap_name(machine, path, sizeof(path));
1654 dso__set_long_name(dso, strdup(path)); 1669 dso__set_long_name(dso, strdup(path), true);
1655 map__fixup_start(map); 1670 map__fixup_start(map);
1656 map__fixup_end(map); 1671 map__fixup_end(map);
1657 } 1672 }
@@ -1661,13 +1676,10 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1661 1676
1662static void vmlinux_path__exit(void) 1677static void vmlinux_path__exit(void)
1663{ 1678{
1664 while (--vmlinux_path__nr_entries >= 0) { 1679 while (--vmlinux_path__nr_entries >= 0)
1665 free(vmlinux_path[vmlinux_path__nr_entries]); 1680 zfree(&vmlinux_path[vmlinux_path__nr_entries]);
1666 vmlinux_path[vmlinux_path__nr_entries] = NULL;
1667 }
1668 1681
1669 free(vmlinux_path); 1682 zfree(&vmlinux_path);
1670 vmlinux_path = NULL;
1671} 1683}
1672 1684
1673static int vmlinux_path__init(void) 1685static int vmlinux_path__init(void)
@@ -1719,7 +1731,7 @@ out_fail:
1719 return -1; 1731 return -1;
1720} 1732}
1721 1733
1722static int setup_list(struct strlist **list, const char *list_str, 1734int setup_list(struct strlist **list, const char *list_str,
1723 const char *list_name) 1735 const char *list_name)
1724{ 1736{
1725 if (list_str == NULL) 1737 if (list_str == NULL)