diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 536 |
1 files changed, 13 insertions, 523 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 295f8d4feedf..e6432d85b43d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -28,8 +28,8 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, | |||
28 | symbol_filter_t filter); | 28 | symbol_filter_t filter); |
29 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | 29 | static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, |
30 | symbol_filter_t filter); | 30 | symbol_filter_t filter); |
31 | static int vmlinux_path__nr_entries; | 31 | int vmlinux_path__nr_entries; |
32 | static char **vmlinux_path; | 32 | char **vmlinux_path; |
33 | 33 | ||
34 | struct symbol_conf symbol_conf = { | 34 | struct symbol_conf symbol_conf = { |
35 | .exclude_other = true, | 35 | .exclude_other = true, |
@@ -202,13 +202,6 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type) | |||
202 | curr->end = ~0ULL; | 202 | curr->end = ~0ULL; |
203 | } | 203 | } |
204 | 204 | ||
205 | static void map_groups__fixup_end(struct map_groups *mg) | ||
206 | { | ||
207 | int i; | ||
208 | for (i = 0; i < MAP__NR_TYPES; ++i) | ||
209 | __map_groups__fixup_end(mg, i); | ||
210 | } | ||
211 | |||
212 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) | 205 | struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) |
213 | { | 206 | { |
214 | size_t namelen = strlen(name) + 1; | 207 | size_t namelen = strlen(name) + 1; |
@@ -652,8 +645,8 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
652 | return count + moved; | 645 | return count + moved; |
653 | } | 646 | } |
654 | 647 | ||
655 | static bool symbol__restricted_filename(const char *filename, | 648 | bool symbol__restricted_filename(const char *filename, |
656 | const char *restricted_filename) | 649 | const char *restricted_filename) |
657 | { | 650 | { |
658 | bool restricted = false; | 651 | bool restricted = false; |
659 | 652 | ||
@@ -775,10 +768,6 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
775 | else | 768 | else |
776 | machine = NULL; | 769 | machine = NULL; |
777 | 770 | ||
778 | name = malloc(PATH_MAX); | ||
779 | if (!name) | ||
780 | return -1; | ||
781 | |||
782 | dso->adjust_symbols = 0; | 771 | dso->adjust_symbols = 0; |
783 | 772 | ||
784 | if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { | 773 | if (strncmp(dso->name, "/tmp/perf-", 10) == 0) { |
@@ -802,6 +791,10 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
802 | if (machine) | 791 | if (machine) |
803 | root_dir = machine->root_dir; | 792 | root_dir = machine->root_dir; |
804 | 793 | ||
794 | name = malloc(PATH_MAX); | ||
795 | if (!name) | ||
796 | return -1; | ||
797 | |||
805 | /* Iterate over candidate debug images. | 798 | /* Iterate over candidate debug images. |
806 | * Keep track of "interesting" ones (those which have a symtab, dynsym, | 799 | * Keep track of "interesting" ones (those which have a symtab, dynsym, |
807 | * and/or opd section) for processing. | 800 | * and/or opd section) for processing. |
@@ -887,200 +880,6 @@ struct map *map_groups__find_by_name(struct map_groups *mg, | |||
887 | return NULL; | 880 | return NULL; |
888 | } | 881 | } |
889 | 882 | ||
890 | static int map_groups__set_modules_path_dir(struct map_groups *mg, | ||
891 | const char *dir_name) | ||
892 | { | ||
893 | struct dirent *dent; | ||
894 | DIR *dir = opendir(dir_name); | ||
895 | int ret = 0; | ||
896 | |||
897 | if (!dir) { | ||
898 | pr_debug("%s: cannot open %s dir\n", __func__, dir_name); | ||
899 | return -1; | ||
900 | } | ||
901 | |||
902 | while ((dent = readdir(dir)) != NULL) { | ||
903 | char path[PATH_MAX]; | ||
904 | struct stat st; | ||
905 | |||
906 | /*sshfs might return bad dent->d_type, so we have to stat*/ | ||
907 | snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name); | ||
908 | if (stat(path, &st)) | ||
909 | continue; | ||
910 | |||
911 | if (S_ISDIR(st.st_mode)) { | ||
912 | if (!strcmp(dent->d_name, ".") || | ||
913 | !strcmp(dent->d_name, "..")) | ||
914 | continue; | ||
915 | |||
916 | ret = map_groups__set_modules_path_dir(mg, path); | ||
917 | if (ret < 0) | ||
918 | goto out; | ||
919 | } else { | ||
920 | char *dot = strrchr(dent->d_name, '.'), | ||
921 | dso_name[PATH_MAX]; | ||
922 | struct map *map; | ||
923 | char *long_name; | ||
924 | |||
925 | if (dot == NULL || strcmp(dot, ".ko")) | ||
926 | continue; | ||
927 | snprintf(dso_name, sizeof(dso_name), "[%.*s]", | ||
928 | (int)(dot - dent->d_name), dent->d_name); | ||
929 | |||
930 | strxfrchar(dso_name, '-', '_'); | ||
931 | map = map_groups__find_by_name(mg, MAP__FUNCTION, | ||
932 | dso_name); | ||
933 | if (map == NULL) | ||
934 | continue; | ||
935 | |||
936 | long_name = strdup(path); | ||
937 | if (long_name == NULL) { | ||
938 | ret = -1; | ||
939 | goto out; | ||
940 | } | ||
941 | dso__set_long_name(map->dso, long_name); | ||
942 | map->dso->lname_alloc = 1; | ||
943 | dso__kernel_module_get_build_id(map->dso, ""); | ||
944 | } | ||
945 | } | ||
946 | |||
947 | out: | ||
948 | closedir(dir); | ||
949 | return ret; | ||
950 | } | ||
951 | |||
952 | static char *get_kernel_version(const char *root_dir) | ||
953 | { | ||
954 | char version[PATH_MAX]; | ||
955 | FILE *file; | ||
956 | char *name, *tmp; | ||
957 | const char *prefix = "Linux version "; | ||
958 | |||
959 | sprintf(version, "%s/proc/version", root_dir); | ||
960 | file = fopen(version, "r"); | ||
961 | if (!file) | ||
962 | return NULL; | ||
963 | |||
964 | version[0] = '\0'; | ||
965 | tmp = fgets(version, sizeof(version), file); | ||
966 | fclose(file); | ||
967 | |||
968 | name = strstr(version, prefix); | ||
969 | if (!name) | ||
970 | return NULL; | ||
971 | name += strlen(prefix); | ||
972 | tmp = strchr(name, ' '); | ||
973 | if (tmp) | ||
974 | *tmp = '\0'; | ||
975 | |||
976 | return strdup(name); | ||
977 | } | ||
978 | |||
979 | static int machine__set_modules_path(struct machine *machine) | ||
980 | { | ||
981 | char *version; | ||
982 | char modules_path[PATH_MAX]; | ||
983 | |||
984 | version = get_kernel_version(machine->root_dir); | ||
985 | if (!version) | ||
986 | return -1; | ||
987 | |||
988 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", | ||
989 | machine->root_dir, version); | ||
990 | free(version); | ||
991 | |||
992 | return map_groups__set_modules_path_dir(&machine->kmaps, modules_path); | ||
993 | } | ||
994 | |||
995 | struct map *machine__new_module(struct machine *machine, u64 start, | ||
996 | const char *filename) | ||
997 | { | ||
998 | struct map *map; | ||
999 | struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename); | ||
1000 | |||
1001 | if (dso == NULL) | ||
1002 | return NULL; | ||
1003 | |||
1004 | map = map__new2(start, dso, MAP__FUNCTION); | ||
1005 | if (map == NULL) | ||
1006 | return NULL; | ||
1007 | |||
1008 | if (machine__is_host(machine)) | ||
1009 | dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE; | ||
1010 | else | ||
1011 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE; | ||
1012 | map_groups__insert(&machine->kmaps, map); | ||
1013 | return map; | ||
1014 | } | ||
1015 | |||
1016 | static int machine__create_modules(struct machine *machine) | ||
1017 | { | ||
1018 | char *line = NULL; | ||
1019 | size_t n; | ||
1020 | FILE *file; | ||
1021 | struct map *map; | ||
1022 | const char *modules; | ||
1023 | char path[PATH_MAX]; | ||
1024 | |||
1025 | if (machine__is_default_guest(machine)) | ||
1026 | modules = symbol_conf.default_guest_modules; | ||
1027 | else { | ||
1028 | sprintf(path, "%s/proc/modules", machine->root_dir); | ||
1029 | modules = path; | ||
1030 | } | ||
1031 | |||
1032 | if (symbol__restricted_filename(path, "/proc/modules")) | ||
1033 | return -1; | ||
1034 | |||
1035 | file = fopen(modules, "r"); | ||
1036 | if (file == NULL) | ||
1037 | return -1; | ||
1038 | |||
1039 | while (!feof(file)) { | ||
1040 | char name[PATH_MAX]; | ||
1041 | u64 start; | ||
1042 | char *sep; | ||
1043 | int line_len; | ||
1044 | |||
1045 | line_len = getline(&line, &n, file); | ||
1046 | if (line_len < 0) | ||
1047 | break; | ||
1048 | |||
1049 | if (!line) | ||
1050 | goto out_failure; | ||
1051 | |||
1052 | line[--line_len] = '\0'; /* \n */ | ||
1053 | |||
1054 | sep = strrchr(line, 'x'); | ||
1055 | if (sep == NULL) | ||
1056 | continue; | ||
1057 | |||
1058 | hex2u64(sep + 1, &start); | ||
1059 | |||
1060 | sep = strchr(line, ' '); | ||
1061 | if (sep == NULL) | ||
1062 | continue; | ||
1063 | |||
1064 | *sep = '\0'; | ||
1065 | |||
1066 | snprintf(name, sizeof(name), "[%s]", line); | ||
1067 | map = machine__new_module(machine, start, name); | ||
1068 | if (map == NULL) | ||
1069 | goto out_delete_line; | ||
1070 | dso__kernel_module_get_build_id(map->dso, machine->root_dir); | ||
1071 | } | ||
1072 | |||
1073 | free(line); | ||
1074 | fclose(file); | ||
1075 | |||
1076 | return machine__set_modules_path(machine); | ||
1077 | |||
1078 | out_delete_line: | ||
1079 | free(line); | ||
1080 | out_failure: | ||
1081 | return -1; | ||
1082 | } | ||
1083 | |||
1084 | int dso__load_vmlinux(struct dso *dso, struct map *map, | 883 | int dso__load_vmlinux(struct dso *dso, struct map *map, |
1085 | const char *vmlinux, symbol_filter_t filter) | 884 | const char *vmlinux, symbol_filter_t filter) |
1086 | { | 885 | { |
@@ -1124,8 +923,10 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1124 | filename = dso__build_id_filename(dso, NULL, 0); | 923 | filename = dso__build_id_filename(dso, NULL, 0); |
1125 | if (filename != NULL) { | 924 | if (filename != NULL) { |
1126 | err = dso__load_vmlinux(dso, map, filename, filter); | 925 | err = dso__load_vmlinux(dso, map, filename, filter); |
1127 | if (err > 0) | 926 | if (err > 0) { |
927 | dso->lname_alloc = 1; | ||
1128 | goto out; | 928 | goto out; |
929 | } | ||
1129 | free(filename); | 930 | free(filename); |
1130 | } | 931 | } |
1131 | 932 | ||
@@ -1133,6 +934,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map, | |||
1133 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); | 934 | err = dso__load_vmlinux(dso, map, vmlinux_path[i], filter); |
1134 | if (err > 0) { | 935 | if (err > 0) { |
1135 | dso__set_long_name(dso, strdup(vmlinux_path[i])); | 936 | dso__set_long_name(dso, strdup(vmlinux_path[i])); |
937 | dso->lname_alloc = 1; | ||
1136 | break; | 938 | break; |
1137 | } | 939 | } |
1138 | } | 940 | } |
@@ -1172,6 +974,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map, | |||
1172 | if (err > 0) { | 974 | if (err > 0) { |
1173 | dso__set_long_name(dso, | 975 | dso__set_long_name(dso, |
1174 | strdup(symbol_conf.vmlinux_name)); | 976 | strdup(symbol_conf.vmlinux_name)); |
977 | dso->lname_alloc = 1; | ||
1175 | goto out_fixup; | 978 | goto out_fixup; |
1176 | } | 979 | } |
1177 | return err; | 980 | return err; |
@@ -1300,195 +1103,6 @@ out_try_fixup: | |||
1300 | return err; | 1103 | return err; |
1301 | } | 1104 | } |
1302 | 1105 | ||
1303 | size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp) | ||
1304 | { | ||
1305 | struct rb_node *nd; | ||
1306 | size_t ret = 0; | ||
1307 | |||
1308 | for (nd = rb_first(machines); nd; nd = rb_next(nd)) { | ||
1309 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
1310 | ret += __dsos__fprintf(&pos->kernel_dsos, fp); | ||
1311 | ret += __dsos__fprintf(&pos->user_dsos, fp); | ||
1312 | } | ||
1313 | |||
1314 | return ret; | ||
1315 | } | ||
1316 | |||
1317 | size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, | ||
1318 | bool with_hits) | ||
1319 | { | ||
1320 | return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, with_hits) + | ||
1321 | __dsos__fprintf_buildid(&machine->user_dsos, fp, with_hits); | ||
1322 | } | ||
1323 | |||
1324 | size_t machines__fprintf_dsos_buildid(struct rb_root *machines, | ||
1325 | FILE *fp, bool with_hits) | ||
1326 | { | ||
1327 | struct rb_node *nd; | ||
1328 | size_t ret = 0; | ||
1329 | |||
1330 | for (nd = rb_first(machines); nd; nd = rb_next(nd)) { | ||
1331 | struct machine *pos = rb_entry(nd, struct machine, rb_node); | ||
1332 | ret += machine__fprintf_dsos_buildid(pos, fp, with_hits); | ||
1333 | } | ||
1334 | return ret; | ||
1335 | } | ||
1336 | |||
1337 | static struct dso *machine__get_kernel(struct machine *machine) | ||
1338 | { | ||
1339 | const char *vmlinux_name = NULL; | ||
1340 | struct dso *kernel; | ||
1341 | |||
1342 | if (machine__is_host(machine)) { | ||
1343 | vmlinux_name = symbol_conf.vmlinux_name; | ||
1344 | if (!vmlinux_name) | ||
1345 | vmlinux_name = "[kernel.kallsyms]"; | ||
1346 | |||
1347 | kernel = dso__kernel_findnew(machine, vmlinux_name, | ||
1348 | "[kernel]", | ||
1349 | DSO_TYPE_KERNEL); | ||
1350 | } else { | ||
1351 | char bf[PATH_MAX]; | ||
1352 | |||
1353 | if (machine__is_default_guest(machine)) | ||
1354 | vmlinux_name = symbol_conf.default_guest_vmlinux_name; | ||
1355 | if (!vmlinux_name) | ||
1356 | vmlinux_name = machine__mmap_name(machine, bf, | ||
1357 | sizeof(bf)); | ||
1358 | |||
1359 | kernel = dso__kernel_findnew(machine, vmlinux_name, | ||
1360 | "[guest.kernel]", | ||
1361 | DSO_TYPE_GUEST_KERNEL); | ||
1362 | } | ||
1363 | |||
1364 | if (kernel != NULL && (!kernel->has_build_id)) | ||
1365 | dso__read_running_kernel_build_id(kernel, machine); | ||
1366 | |||
1367 | return kernel; | ||
1368 | } | ||
1369 | |||
1370 | struct process_args { | ||
1371 | u64 start; | ||
1372 | }; | ||
1373 | |||
1374 | static int symbol__in_kernel(void *arg, const char *name, | ||
1375 | char type __maybe_unused, u64 start) | ||
1376 | { | ||
1377 | struct process_args *args = arg; | ||
1378 | |||
1379 | if (strchr(name, '[')) | ||
1380 | return 0; | ||
1381 | |||
1382 | args->start = start; | ||
1383 | return 1; | ||
1384 | } | ||
1385 | |||
1386 | /* Figure out the start address of kernel map from /proc/kallsyms */ | ||
1387 | static u64 machine__get_kernel_start_addr(struct machine *machine) | ||
1388 | { | ||
1389 | const char *filename; | ||
1390 | char path[PATH_MAX]; | ||
1391 | struct process_args args; | ||
1392 | |||
1393 | if (machine__is_host(machine)) { | ||
1394 | filename = "/proc/kallsyms"; | ||
1395 | } else { | ||
1396 | if (machine__is_default_guest(machine)) | ||
1397 | filename = (char *)symbol_conf.default_guest_kallsyms; | ||
1398 | else { | ||
1399 | sprintf(path, "%s/proc/kallsyms", machine->root_dir); | ||
1400 | filename = path; | ||
1401 | } | ||
1402 | } | ||
1403 | |||
1404 | if (symbol__restricted_filename(filename, "/proc/kallsyms")) | ||
1405 | return 0; | ||
1406 | |||
1407 | if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0) | ||
1408 | return 0; | ||
1409 | |||
1410 | return args.start; | ||
1411 | } | ||
1412 | |||
1413 | int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | ||
1414 | { | ||
1415 | enum map_type type; | ||
1416 | u64 start = machine__get_kernel_start_addr(machine); | ||
1417 | |||
1418 | for (type = 0; type < MAP__NR_TYPES; ++type) { | ||
1419 | struct kmap *kmap; | ||
1420 | |||
1421 | machine->vmlinux_maps[type] = map__new2(start, kernel, type); | ||
1422 | if (machine->vmlinux_maps[type] == NULL) | ||
1423 | return -1; | ||
1424 | |||
1425 | machine->vmlinux_maps[type]->map_ip = | ||
1426 | machine->vmlinux_maps[type]->unmap_ip = | ||
1427 | identity__map_ip; | ||
1428 | kmap = map__kmap(machine->vmlinux_maps[type]); | ||
1429 | kmap->kmaps = &machine->kmaps; | ||
1430 | map_groups__insert(&machine->kmaps, | ||
1431 | machine->vmlinux_maps[type]); | ||
1432 | } | ||
1433 | |||
1434 | return 0; | ||
1435 | } | ||
1436 | |||
1437 | void machine__destroy_kernel_maps(struct machine *machine) | ||
1438 | { | ||
1439 | enum map_type type; | ||
1440 | |||
1441 | for (type = 0; type < MAP__NR_TYPES; ++type) { | ||
1442 | struct kmap *kmap; | ||
1443 | |||
1444 | if (machine->vmlinux_maps[type] == NULL) | ||
1445 | continue; | ||
1446 | |||
1447 | kmap = map__kmap(machine->vmlinux_maps[type]); | ||
1448 | map_groups__remove(&machine->kmaps, | ||
1449 | machine->vmlinux_maps[type]); | ||
1450 | if (kmap->ref_reloc_sym) { | ||
1451 | /* | ||
1452 | * ref_reloc_sym is shared among all maps, so free just | ||
1453 | * on one of them. | ||
1454 | */ | ||
1455 | if (type == MAP__FUNCTION) { | ||
1456 | free((char *)kmap->ref_reloc_sym->name); | ||
1457 | kmap->ref_reloc_sym->name = NULL; | ||
1458 | free(kmap->ref_reloc_sym); | ||
1459 | } | ||
1460 | kmap->ref_reloc_sym = NULL; | ||
1461 | } | ||
1462 | |||
1463 | map__delete(machine->vmlinux_maps[type]); | ||
1464 | machine->vmlinux_maps[type] = NULL; | ||
1465 | } | ||
1466 | } | ||
1467 | |||
1468 | int machine__create_kernel_maps(struct machine *machine) | ||
1469 | { | ||
1470 | struct dso *kernel = machine__get_kernel(machine); | ||
1471 | |||
1472 | if (kernel == NULL || | ||
1473 | __machine__create_kernel_maps(machine, kernel) < 0) | ||
1474 | return -1; | ||
1475 | |||
1476 | if (symbol_conf.use_modules && machine__create_modules(machine) < 0) { | ||
1477 | if (machine__is_host(machine)) | ||
1478 | pr_debug("Problems creating module maps, " | ||
1479 | "continuing anyway...\n"); | ||
1480 | else | ||
1481 | pr_debug("Problems creating module maps for guest %d, " | ||
1482 | "continuing anyway...\n", machine->pid); | ||
1483 | } | ||
1484 | |||
1485 | /* | ||
1486 | * Now that we have all the maps created, just set the ->end of them: | ||
1487 | */ | ||
1488 | map_groups__fixup_end(&machine->kmaps); | ||
1489 | return 0; | ||
1490 | } | ||
1491 | |||
1492 | static void vmlinux_path__exit(void) | 1106 | static void vmlinux_path__exit(void) |
1493 | { | 1107 | { |
1494 | while (--vmlinux_path__nr_entries >= 0) { | 1108 | while (--vmlinux_path__nr_entries >= 0) { |
@@ -1549,25 +1163,6 @@ out_fail: | |||
1549 | return -1; | 1163 | return -1; |
1550 | } | 1164 | } |
1551 | 1165 | ||
1552 | size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) | ||
1553 | { | ||
1554 | int i; | ||
1555 | size_t printed = 0; | ||
1556 | struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso; | ||
1557 | |||
1558 | if (kdso->has_build_id) { | ||
1559 | char filename[PATH_MAX]; | ||
1560 | if (dso__build_id_filename(kdso, filename, sizeof(filename))) | ||
1561 | printed += fprintf(fp, "[0] %s\n", filename); | ||
1562 | } | ||
1563 | |||
1564 | for (i = 0; i < vmlinux_path__nr_entries; ++i) | ||
1565 | printed += fprintf(fp, "[%d] %s\n", | ||
1566 | i + kdso->has_build_id, vmlinux_path[i]); | ||
1567 | |||
1568 | return printed; | ||
1569 | } | ||
1570 | |||
1571 | static int setup_list(struct strlist **list, const char *list_str, | 1166 | static int setup_list(struct strlist **list, const char *list_str, |
1572 | const char *list_name) | 1167 | const char *list_name) |
1573 | { | 1168 | { |
@@ -1671,108 +1266,3 @@ void symbol__exit(void) | |||
1671 | symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; | 1266 | symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; |
1672 | symbol_conf.initialized = false; | 1267 | symbol_conf.initialized = false; |
1673 | } | 1268 | } |
1674 | |||
1675 | int machines__create_kernel_maps(struct rb_root *machines, pid_t pid) | ||
1676 | { | ||
1677 | struct machine *machine = machines__findnew(machines, pid); | ||
1678 | |||
1679 | if (machine == NULL) | ||
1680 | return -1; | ||
1681 | |||
1682 | return machine__create_kernel_maps(machine); | ||
1683 | } | ||
1684 | |||
1685 | int machines__create_guest_kernel_maps(struct rb_root *machines) | ||
1686 | { | ||
1687 | int ret = 0; | ||
1688 | struct dirent **namelist = NULL; | ||
1689 | int i, items = 0; | ||
1690 | char path[PATH_MAX]; | ||
1691 | pid_t pid; | ||
1692 | char *endp; | ||
1693 | |||
1694 | if (symbol_conf.default_guest_vmlinux_name || | ||
1695 | symbol_conf.default_guest_modules || | ||
1696 | symbol_conf.default_guest_kallsyms) { | ||
1697 | machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID); | ||
1698 | } | ||
1699 | |||
1700 | if (symbol_conf.guestmount) { | ||
1701 | items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL); | ||
1702 | if (items <= 0) | ||
1703 | return -ENOENT; | ||
1704 | for (i = 0; i < items; i++) { | ||
1705 | if (!isdigit(namelist[i]->d_name[0])) { | ||
1706 | /* Filter out . and .. */ | ||
1707 | continue; | ||
1708 | } | ||
1709 | pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10); | ||
1710 | if ((*endp != '\0') || | ||
1711 | (endp == namelist[i]->d_name) || | ||
1712 | (errno == ERANGE)) { | ||
1713 | pr_debug("invalid directory (%s). Skipping.\n", | ||
1714 | namelist[i]->d_name); | ||
1715 | continue; | ||
1716 | } | ||
1717 | sprintf(path, "%s/%s/proc/kallsyms", | ||
1718 | symbol_conf.guestmount, | ||
1719 | namelist[i]->d_name); | ||
1720 | ret = access(path, R_OK); | ||
1721 | if (ret) { | ||
1722 | pr_debug("Can't access file %s\n", path); | ||
1723 | goto failure; | ||
1724 | } | ||
1725 | machines__create_kernel_maps(machines, pid); | ||
1726 | } | ||
1727 | failure: | ||
1728 | free(namelist); | ||
1729 | } | ||
1730 | |||
1731 | return ret; | ||
1732 | } | ||
1733 | |||
1734 | void machines__destroy_guest_kernel_maps(struct rb_root *machines) | ||
1735 | { | ||
1736 | struct rb_node *next = rb_first(machines); | ||
1737 | |||
1738 | while (next) { | ||
1739 | struct machine *pos = rb_entry(next, struct machine, rb_node); | ||
1740 | |||
1741 | next = rb_next(&pos->rb_node); | ||
1742 | rb_erase(&pos->rb_node, machines); | ||
1743 | machine__delete(pos); | ||
1744 | } | ||
1745 | } | ||
1746 | |||
1747 | int machine__load_kallsyms(struct machine *machine, const char *filename, | ||
1748 | enum map_type type, symbol_filter_t filter) | ||
1749 | { | ||
1750 | struct map *map = machine->vmlinux_maps[type]; | ||
1751 | int ret = dso__load_kallsyms(map->dso, filename, map, filter); | ||
1752 | |||
1753 | if (ret > 0) { | ||
1754 | dso__set_loaded(map->dso, type); | ||
1755 | /* | ||
1756 | * Since /proc/kallsyms will have multiple sessions for the | ||
1757 | * kernel, with modules between them, fixup the end of all | ||
1758 | * sections. | ||
1759 | */ | ||
1760 | __map_groups__fixup_end(&machine->kmaps, type); | ||
1761 | } | ||
1762 | |||
1763 | return ret; | ||
1764 | } | ||
1765 | |||
1766 | int machine__load_vmlinux_path(struct machine *machine, enum map_type type, | ||
1767 | symbol_filter_t filter) | ||
1768 | { | ||
1769 | struct map *map = machine->vmlinux_maps[type]; | ||
1770 | int ret = dso__load_vmlinux_path(map->dso, map, filter); | ||
1771 | |||
1772 | if (ret > 0) { | ||
1773 | dso__set_loaded(map->dso, type); | ||
1774 | map__reloc_vmlinux(map); | ||
1775 | } | ||
1776 | |||
1777 | return ret; | ||
1778 | } | ||