diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 39ce9adbaaf0..a9d758a3b371 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -627,7 +627,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | |||
627 | * 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 |
628 | * the original ELF section names vmlinux have. | 628 | * the original ELF section names vmlinux have. |
629 | */ | 629 | */ |
630 | static int dso__split_kallsyms(struct dso *dso, struct map *map, | 630 | static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, |
631 | symbol_filter_t filter) | 631 | symbol_filter_t filter) |
632 | { | 632 | { |
633 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 633 | struct map_groups *kmaps = map__kmap(map)->kmaps; |
@@ -692,6 +692,12 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, | |||
692 | char dso_name[PATH_MAX]; | 692 | char dso_name[PATH_MAX]; |
693 | struct dso *ndso; | 693 | struct dso *ndso; |
694 | 694 | ||
695 | if (delta) { | ||
696 | /* Kernel was relocated at boot time */ | ||
697 | pos->start -= delta; | ||
698 | pos->end -= delta; | ||
699 | } | ||
700 | |||
695 | if (count == 0) { | 701 | if (count == 0) { |
696 | curr_map = map; | 702 | curr_map = map; |
697 | goto filter_symbol; | 703 | goto filter_symbol; |
@@ -721,6 +727,10 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, | |||
721 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; | 727 | curr_map->map_ip = curr_map->unmap_ip = identity__map_ip; |
722 | map_groups__insert(kmaps, curr_map); | 728 | map_groups__insert(kmaps, curr_map); |
723 | ++kernel_range; | 729 | ++kernel_range; |
730 | } else if (delta) { | ||
731 | /* Kernel was relocated at boot time */ | ||
732 | pos->start -= delta; | ||
733 | pos->end -= delta; | ||
724 | } | 734 | } |
725 | filter_symbol: | 735 | filter_symbol: |
726 | if (filter && filter(curr_map, pos)) { | 736 | if (filter && filter(curr_map, pos)) { |
@@ -976,6 +986,23 @@ static int validate_kcore_modules(const char *kallsyms_filename, | |||
976 | return 0; | 986 | return 0; |
977 | } | 987 | } |
978 | 988 | ||
989 | static 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 | |||
979 | struct kcore_mapfn_data { | 1006 | struct kcore_mapfn_data { |
980 | struct dso *dso; | 1007 | struct dso *dso; |
981 | enum map_type type; | 1008 | enum map_type type; |
@@ -1019,8 +1046,8 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
1019 | kallsyms_filename)) | 1046 | kallsyms_filename)) |
1020 | return -EINVAL; | 1047 | return -EINVAL; |
1021 | 1048 | ||
1022 | /* All modules must be present at their original addresses */ | 1049 | /* Modules and kernel must be present at their original addresses */ |
1023 | if (validate_kcore_modules(kallsyms_filename, map)) | 1050 | if (validate_kcore_addresses(kallsyms_filename, map)) |
1024 | return -EINVAL; | 1051 | return -EINVAL; |
1025 | 1052 | ||
1026 | md.dso = dso; | 1053 | md.dso = dso; |
@@ -1113,15 +1140,41 @@ out_err: | |||
1113 | return -EINVAL; | 1140 | return -EINVAL; |
1114 | } | 1141 | } |
1115 | 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 | */ | ||
1147 | static 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 | |||
1116 | int dso__load_kallsyms(struct dso *dso, const char *filename, | 1164 | int dso__load_kallsyms(struct dso *dso, const char *filename, |
1117 | struct map *map, symbol_filter_t filter) | 1165 | struct map *map, symbol_filter_t filter) |
1118 | { | 1166 | { |
1167 | u64 delta = 0; | ||
1168 | |||
1119 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | 1169 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) |
1120 | return -1; | 1170 | return -1; |
1121 | 1171 | ||
1122 | if (dso__load_all_kallsyms(dso, filename, map) < 0) | 1172 | if (dso__load_all_kallsyms(dso, filename, map) < 0) |
1123 | return -1; | 1173 | return -1; |
1124 | 1174 | ||
1175 | if (kallsyms__delta(map, filename, &delta)) | ||
1176 | return -1; | ||
1177 | |||
1125 | symbols__fixup_duplicate(&dso->symbols[map->type]); | 1178 | symbols__fixup_duplicate(&dso->symbols[map->type]); |
1126 | symbols__fixup_end(&dso->symbols[map->type]); | 1179 | symbols__fixup_end(&dso->symbols[map->type]); |
1127 | 1180 | ||
@@ -1133,7 +1186,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, | |||
1133 | if (!dso__load_kcore(dso, map, filename)) | 1186 | if (!dso__load_kcore(dso, map, filename)) |
1134 | return dso__split_kallsyms_for_kcore(dso, map, filter); | 1187 | return dso__split_kallsyms_for_kcore(dso, map, filter); |
1135 | else | 1188 | else |
1136 | return dso__split_kallsyms(dso, map, filter); | 1189 | return dso__split_kallsyms(dso, map, delta, filter); |
1137 | } | 1190 | } |
1138 | 1191 | ||
1139 | static int dso__load_perf_map(struct dso *dso, struct map *map, | 1192 | static int dso__load_perf_map(struct dso *dso, struct map *map, |
@@ -1424,7 +1477,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) | |||
1424 | continue; | 1477 | continue; |
1425 | scnprintf(kallsyms_filename, sizeof(kallsyms_filename), | 1478 | scnprintf(kallsyms_filename, sizeof(kallsyms_filename), |
1426 | "%s/%s/kallsyms", dir, dent->d_name); | 1479 | "%s/%s/kallsyms", dir, dent->d_name); |
1427 | if (!validate_kcore_modules(kallsyms_filename, map)) { | 1480 | if (!validate_kcore_addresses(kallsyms_filename, map)) { |
1428 | strlcpy(dir, kallsyms_filename, dir_sz); | 1481 | strlcpy(dir, kallsyms_filename, dir_sz); |
1429 | ret = 0; | 1482 | ret = 0; |
1430 | break; | 1483 | break; |
@@ -1479,7 +1532,7 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map) | |||
1479 | if (fd != -1) { | 1532 | if (fd != -1) { |
1480 | close(fd); | 1533 | close(fd); |
1481 | /* If module maps match go with /proc/kallsyms */ | 1534 | /* If module maps match go with /proc/kallsyms */ |
1482 | if (!validate_kcore_modules("/proc/kallsyms", map)) | 1535 | if (!validate_kcore_addresses("/proc/kallsyms", map)) |
1483 | goto proc_kallsyms; | 1536 | goto proc_kallsyms; |
1484 | } | 1537 | } |
1485 | 1538 | ||