diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 382 |
1 files changed, 317 insertions, 65 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index f3d4151e46a1..e782e7db16c5 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -28,6 +28,8 @@ static void dsos__add(struct list_head *head, struct dso *dso); | |||
28 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); | 28 | static struct map *map__new2(u64 start, struct dso *dso, enum map_type type); |
29 | static int dso__load_kernel_sym(struct dso *self, struct map *map, | 29 | static int dso__load_kernel_sym(struct dso *self, struct map *map, |
30 | symbol_filter_t filter); | 30 | symbol_filter_t filter); |
31 | static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, | ||
32 | symbol_filter_t filter); | ||
31 | static int vmlinux_path__nr_entries; | 33 | static int vmlinux_path__nr_entries; |
32 | static char **vmlinux_path; | 34 | static char **vmlinux_path; |
33 | 35 | ||
@@ -186,6 +188,7 @@ struct dso *dso__new(const char *name) | |||
186 | self->loaded = 0; | 188 | self->loaded = 0; |
187 | self->sorted_by_name = 0; | 189 | self->sorted_by_name = 0; |
188 | self->has_build_id = 0; | 190 | self->has_build_id = 0; |
191 | self->kernel = DSO_TYPE_USER; | ||
189 | } | 192 | } |
190 | 193 | ||
191 | return self; | 194 | return self; |
@@ -402,12 +405,9 @@ int kallsyms__parse(const char *filename, void *arg, | |||
402 | char *symbol_name; | 405 | char *symbol_name; |
403 | 406 | ||
404 | line_len = getline(&line, &n, file); | 407 | line_len = getline(&line, &n, file); |
405 | if (line_len < 0) | 408 | if (line_len < 0 || !line) |
406 | break; | 409 | break; |
407 | 410 | ||
408 | if (!line) | ||
409 | goto out_failure; | ||
410 | |||
411 | line[--line_len] = '\0'; /* \n */ | 411 | line[--line_len] = '\0'; /* \n */ |
412 | 412 | ||
413 | len = hex2u64(line, &start); | 413 | len = hex2u64(line, &start); |
@@ -459,6 +459,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name, | |||
459 | * map__split_kallsyms, when we have split the maps per module | 459 | * map__split_kallsyms, when we have split the maps per module |
460 | */ | 460 | */ |
461 | symbols__insert(root, sym); | 461 | symbols__insert(root, sym); |
462 | |||
462 | return 0; | 463 | return 0; |
463 | } | 464 | } |
464 | 465 | ||
@@ -483,6 +484,7 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
483 | symbol_filter_t filter) | 484 | symbol_filter_t filter) |
484 | { | 485 | { |
485 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 486 | struct map_groups *kmaps = map__kmap(map)->kmaps; |
487 | struct kernel_info *kerninfo = kmaps->this_kerninfo; | ||
486 | struct map *curr_map = map; | 488 | struct map *curr_map = map; |
487 | struct symbol *pos; | 489 | struct symbol *pos; |
488 | int count = 0; | 490 | int count = 0; |
@@ -504,15 +506,33 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
504 | *module++ = '\0'; | 506 | *module++ = '\0'; |
505 | 507 | ||
506 | if (strcmp(curr_map->dso->short_name, module)) { | 508 | if (strcmp(curr_map->dso->short_name, module)) { |
507 | curr_map = map_groups__find_by_name(kmaps, map->type, module); | 509 | if (curr_map != map && |
510 | self->kernel == DSO_TYPE_GUEST_KERNEL && | ||
511 | is_default_guest(kerninfo)) { | ||
512 | /* | ||
513 | * We assume all symbols of a module are | ||
514 | * continuous in * kallsyms, so curr_map | ||
515 | * points to a module and all its | ||
516 | * symbols are in its kmap. Mark it as | ||
517 | * loaded. | ||
518 | */ | ||
519 | dso__set_loaded(curr_map->dso, | ||
520 | curr_map->type); | ||
521 | } | ||
522 | |||
523 | curr_map = map_groups__find_by_name(kmaps, | ||
524 | map->type, module); | ||
508 | if (curr_map == NULL) { | 525 | if (curr_map == NULL) { |
509 | pr_debug("/proc/{kallsyms,modules} " | 526 | pr_err("%s/proc/{kallsyms,modules} " |
510 | "inconsistency while looking " | 527 | "inconsistency while looking " |
511 | "for \"%s\" module!\n", module); | 528 | "for \"%s\" module!\n", |
512 | return -1; | 529 | kerninfo->root_dir, module); |
530 | curr_map = map; | ||
531 | goto discard_symbol; | ||
513 | } | 532 | } |
514 | 533 | ||
515 | if (curr_map->dso->loaded) | 534 | if (curr_map->dso->loaded && |
535 | !is_default_guest(kmaps->this_kerninfo)) | ||
516 | goto discard_symbol; | 536 | goto discard_symbol; |
517 | } | 537 | } |
518 | /* | 538 | /* |
@@ -525,13 +545,21 @@ static int dso__split_kallsyms(struct dso *self, struct map *map, | |||
525 | char dso_name[PATH_MAX]; | 545 | char dso_name[PATH_MAX]; |
526 | struct dso *dso; | 546 | struct dso *dso; |
527 | 547 | ||
528 | snprintf(dso_name, sizeof(dso_name), "[kernel].%d", | 548 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) |
529 | kernel_range++); | 549 | snprintf(dso_name, sizeof(dso_name), |
550 | "[guest.kernel].%d", | ||
551 | kernel_range++); | ||
552 | else | ||
553 | snprintf(dso_name, sizeof(dso_name), | ||
554 | "[kernel].%d", | ||
555 | kernel_range++); | ||
530 | 556 | ||
531 | dso = dso__new(dso_name); | 557 | dso = dso__new(dso_name); |
532 | if (dso == NULL) | 558 | if (dso == NULL) |
533 | return -1; | 559 | return -1; |
534 | 560 | ||
561 | dso->kernel = self->kernel; | ||
562 | |||
535 | curr_map = map__new2(pos->start, dso, map->type); | 563 | curr_map = map__new2(pos->start, dso, map->type); |
536 | if (curr_map == NULL) { | 564 | if (curr_map == NULL) { |
537 | dso__delete(dso); | 565 | dso__delete(dso); |
@@ -555,6 +583,12 @@ discard_symbol: rb_erase(&pos->rb_node, root); | |||
555 | } | 583 | } |
556 | } | 584 | } |
557 | 585 | ||
586 | if (curr_map != map && | ||
587 | self->kernel == DSO_TYPE_GUEST_KERNEL && | ||
588 | is_default_guest(kmaps->this_kerninfo)) { | ||
589 | dso__set_loaded(curr_map->dso, curr_map->type); | ||
590 | } | ||
591 | |||
558 | return count; | 592 | return count; |
559 | } | 593 | } |
560 | 594 | ||
@@ -565,7 +599,10 @@ int dso__load_kallsyms(struct dso *self, const char *filename, | |||
565 | return -1; | 599 | return -1; |
566 | 600 | ||
567 | symbols__fixup_end(&self->symbols[map->type]); | 601 | symbols__fixup_end(&self->symbols[map->type]); |
568 | self->origin = DSO__ORIG_KERNEL; | 602 | if (self->kernel == DSO_TYPE_GUEST_KERNEL) |
603 | self->origin = DSO__ORIG_GUEST_KERNEL; | ||
604 | else | ||
605 | self->origin = DSO__ORIG_KERNEL; | ||
569 | 606 | ||
570 | return dso__split_kallsyms(self, map, filter); | 607 | return dso__split_kallsyms(self, map, filter); |
571 | } | 608 | } |
@@ -952,7 +989,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
952 | nr_syms = shdr.sh_size / shdr.sh_entsize; | 989 | nr_syms = shdr.sh_size / shdr.sh_entsize; |
953 | 990 | ||
954 | memset(&sym, 0, sizeof(sym)); | 991 | memset(&sym, 0, sizeof(sym)); |
955 | if (!self->kernel) { | 992 | if (self->kernel == DSO_TYPE_USER) { |
956 | self->adjust_symbols = (ehdr.e_type == ET_EXEC || | 993 | self->adjust_symbols = (ehdr.e_type == ET_EXEC || |
957 | elf_section_by_name(elf, &ehdr, &shdr, | 994 | elf_section_by_name(elf, &ehdr, &shdr, |
958 | ".gnu.prelink_undo", | 995 | ".gnu.prelink_undo", |
@@ -984,7 +1021,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
984 | 1021 | ||
985 | section_name = elf_sec__name(&shdr, secstrs); | 1022 | section_name = elf_sec__name(&shdr, secstrs); |
986 | 1023 | ||
987 | if (self->kernel || kmodule) { | 1024 | if (self->kernel != DSO_TYPE_USER || kmodule) { |
988 | char dso_name[PATH_MAX]; | 1025 | char dso_name[PATH_MAX]; |
989 | 1026 | ||
990 | if (strcmp(section_name, | 1027 | if (strcmp(section_name, |
@@ -1011,6 +1048,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1011 | curr_dso = dso__new(dso_name); | 1048 | curr_dso = dso__new(dso_name); |
1012 | if (curr_dso == NULL) | 1049 | if (curr_dso == NULL) |
1013 | goto out_elf_end; | 1050 | goto out_elf_end; |
1051 | curr_dso->kernel = self->kernel; | ||
1014 | curr_map = map__new2(start, curr_dso, | 1052 | curr_map = map__new2(start, curr_dso, |
1015 | map->type); | 1053 | map->type); |
1016 | if (curr_map == NULL) { | 1054 | if (curr_map == NULL) { |
@@ -1021,7 +1059,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name, | |||
1021 | curr_map->unmap_ip = identity__map_ip; | 1059 | curr_map->unmap_ip = identity__map_ip; |
1022 | curr_dso->origin = self->origin; | 1060 | curr_dso->origin = self->origin; |
1023 | map_groups__insert(kmap->kmaps, curr_map); | 1061 | map_groups__insert(kmap->kmaps, curr_map); |
1024 | dsos__add(&dsos__kernel, curr_dso); | 1062 | dsos__add(&self->node, curr_dso); |
1025 | dso__set_loaded(curr_dso, map->type); | 1063 | dso__set_loaded(curr_dso, map->type); |
1026 | } else | 1064 | } else |
1027 | curr_dso = curr_map->dso; | 1065 | curr_dso = curr_map->dso; |
@@ -1083,7 +1121,7 @@ static bool dso__build_id_equal(const struct dso *self, u8 *build_id) | |||
1083 | return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; | 1121 | return memcmp(self->build_id, build_id, sizeof(self->build_id)) == 0; |
1084 | } | 1122 | } |
1085 | 1123 | ||
1086 | static bool __dsos__read_build_ids(struct list_head *head, bool with_hits) | 1124 | bool __dsos__read_build_ids(struct list_head *head, bool with_hits) |
1087 | { | 1125 | { |
1088 | bool have_build_id = false; | 1126 | bool have_build_id = false; |
1089 | struct dso *pos; | 1127 | struct dso *pos; |
@@ -1101,13 +1139,6 @@ static bool __dsos__read_build_ids(struct list_head *head, bool with_hits) | |||
1101 | return have_build_id; | 1139 | return have_build_id; |
1102 | } | 1140 | } |
1103 | 1141 | ||
1104 | bool dsos__read_build_ids(bool with_hits) | ||
1105 | { | ||
1106 | bool kbuildids = __dsos__read_build_ids(&dsos__kernel, with_hits), | ||
1107 | ubuildids = __dsos__read_build_ids(&dsos__user, with_hits); | ||
1108 | return kbuildids || ubuildids; | ||
1109 | } | ||
1110 | |||
1111 | /* | 1142 | /* |
1112 | * Align offset to 4 bytes as needed for note name and descriptor data. | 1143 | * Align offset to 4 bytes as needed for note name and descriptor data. |
1113 | */ | 1144 | */ |
@@ -1242,6 +1273,8 @@ char dso__symtab_origin(const struct dso *self) | |||
1242 | [DSO__ORIG_BUILDID] = 'b', | 1273 | [DSO__ORIG_BUILDID] = 'b', |
1243 | [DSO__ORIG_DSO] = 'd', | 1274 | [DSO__ORIG_DSO] = 'd', |
1244 | [DSO__ORIG_KMODULE] = 'K', | 1275 | [DSO__ORIG_KMODULE] = 'K', |
1276 | [DSO__ORIG_GUEST_KERNEL] = 'g', | ||
1277 | [DSO__ORIG_GUEST_KMODULE] = 'G', | ||
1245 | }; | 1278 | }; |
1246 | 1279 | ||
1247 | if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) | 1280 | if (self == NULL || self->origin == DSO__ORIG_NOT_FOUND) |
@@ -1257,11 +1290,20 @@ int dso__load(struct dso *self, struct map *map, symbol_filter_t filter) | |||
1257 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; | 1290 | char build_id_hex[BUILD_ID_SIZE * 2 + 1]; |
1258 | int ret = -1; | 1291 | int ret = -1; |
1259 | int fd; | 1292 | int fd; |
1293 | struct kernel_info *kerninfo; | ||
1294 | const char *root_dir; | ||
1260 | 1295 | ||
1261 | dso__set_loaded(self, map->type); | 1296 | dso__set_loaded(self, map->type); |
1262 | 1297 | ||
1263 | if (self->kernel) | 1298 | if (self->kernel == DSO_TYPE_KERNEL) |
1264 | return dso__load_kernel_sym(self, map, filter); | 1299 | return dso__load_kernel_sym(self, map, filter); |
1300 | else if (self->kernel == DSO_TYPE_GUEST_KERNEL) | ||
1301 | return dso__load_guest_kernel_sym(self, map, filter); | ||
1302 | |||
1303 | if (map->groups && map->groups->this_kerninfo) | ||
1304 | kerninfo = map->groups->this_kerninfo; | ||
1305 | else | ||
1306 | kerninfo = NULL; | ||
1265 | 1307 | ||
1266 | name = malloc(size); | 1308 | name = malloc(size); |
1267 | if (!name) | 1309 | if (!name) |
@@ -1315,6 +1357,13 @@ more: | |||
1315 | case DSO__ORIG_DSO: | 1357 | case DSO__ORIG_DSO: |
1316 | snprintf(name, size, "%s", self->long_name); | 1358 | snprintf(name, size, "%s", self->long_name); |
1317 | break; | 1359 | break; |
1360 | case DSO__ORIG_GUEST_KMODULE: | ||
1361 | if (map->groups && map->groups->this_kerninfo) | ||
1362 | root_dir = map->groups->this_kerninfo->root_dir; | ||
1363 | else | ||
1364 | root_dir = ""; | ||
1365 | snprintf(name, size, "%s%s", root_dir, self->long_name); | ||
1366 | break; | ||
1318 | 1367 | ||
1319 | default: | 1368 | default: |
1320 | goto out; | 1369 | goto out; |
@@ -1368,7 +1417,8 @@ struct map *map_groups__find_by_name(struct map_groups *self, | |||
1368 | return NULL; | 1417 | return NULL; |
1369 | } | 1418 | } |
1370 | 1419 | ||
1371 | static int dso__kernel_module_get_build_id(struct dso *self) | 1420 | static int dso__kernel_module_get_build_id(struct dso *self, |
1421 | const char *root_dir) | ||
1372 | { | 1422 | { |
1373 | char filename[PATH_MAX]; | 1423 | char filename[PATH_MAX]; |
1374 | /* | 1424 | /* |
@@ -1378,8 +1428,8 @@ static int dso__kernel_module_get_build_id(struct dso *self) | |||
1378 | const char *name = self->short_name + 1; | 1428 | const char *name = self->short_name + 1; |
1379 | 1429 | ||
1380 | snprintf(filename, sizeof(filename), | 1430 | snprintf(filename, sizeof(filename), |
1381 | "/sys/module/%.*s/notes/.note.gnu.build-id", | 1431 | "%s/sys/module/%.*s/notes/.note.gnu.build-id", |
1382 | (int)strlen(name - 1), name); | 1432 | root_dir, (int)strlen(name) - 1, name); |
1383 | 1433 | ||
1384 | if (sysfs__read_build_id(filename, self->build_id, | 1434 | if (sysfs__read_build_id(filename, self->build_id, |
1385 | sizeof(self->build_id)) == 0) | 1435 | sizeof(self->build_id)) == 0) |
@@ -1388,7 +1438,8 @@ static int dso__kernel_module_get_build_id(struct dso *self) | |||
1388 | return 0; | 1438 | return 0; |
1389 | } | 1439 | } |
1390 | 1440 | ||
1391 | static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_name) | 1441 | static int map_groups__set_modules_path_dir(struct map_groups *self, |
1442 | const char *dir_name) | ||
1392 | { | 1443 | { |
1393 | struct dirent *dent; | 1444 | struct dirent *dent; |
1394 | DIR *dir = opendir(dir_name); | 1445 | DIR *dir = opendir(dir_name); |
@@ -1400,8 +1451,14 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_n | |||
1400 | 1451 | ||
1401 | while ((dent = readdir(dir)) != NULL) { | 1452 | while ((dent = readdir(dir)) != NULL) { |
1402 | char path[PATH_MAX]; | 1453 | char path[PATH_MAX]; |
1454 | struct stat st; | ||
1455 | |||
1456 | /*sshfs might return bad dent->d_type, so we have to stat*/ | ||
1457 | sprintf(path, "%s/%s", dir_name, dent->d_name); | ||
1458 | if (stat(path, &st)) | ||
1459 | continue; | ||
1403 | 1460 | ||
1404 | if (dent->d_type == DT_DIR) { | 1461 | if (S_ISDIR(st.st_mode)) { |
1405 | if (!strcmp(dent->d_name, ".") || | 1462 | if (!strcmp(dent->d_name, ".") || |
1406 | !strcmp(dent->d_name, "..")) | 1463 | !strcmp(dent->d_name, "..")) |
1407 | continue; | 1464 | continue; |
@@ -1433,7 +1490,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *self, char *dir_n | |||
1433 | if (long_name == NULL) | 1490 | if (long_name == NULL) |
1434 | goto failure; | 1491 | goto failure; |
1435 | dso__set_long_name(map->dso, long_name); | 1492 | dso__set_long_name(map->dso, long_name); |
1436 | dso__kernel_module_get_build_id(map->dso); | 1493 | dso__kernel_module_get_build_id(map->dso, ""); |
1437 | } | 1494 | } |
1438 | } | 1495 | } |
1439 | 1496 | ||
@@ -1443,16 +1500,46 @@ failure: | |||
1443 | return -1; | 1500 | return -1; |
1444 | } | 1501 | } |
1445 | 1502 | ||
1446 | static int map_groups__set_modules_path(struct map_groups *self) | 1503 | static char *get_kernel_version(const char *root_dir) |
1447 | { | 1504 | { |
1448 | struct utsname uts; | 1505 | char version[PATH_MAX]; |
1506 | FILE *file; | ||
1507 | char *name, *tmp; | ||
1508 | const char *prefix = "Linux version "; | ||
1509 | |||
1510 | sprintf(version, "%s/proc/version", root_dir); | ||
1511 | file = fopen(version, "r"); | ||
1512 | if (!file) | ||
1513 | return NULL; | ||
1514 | |||
1515 | version[0] = '\0'; | ||
1516 | tmp = fgets(version, sizeof(version), file); | ||
1517 | fclose(file); | ||
1518 | |||
1519 | name = strstr(version, prefix); | ||
1520 | if (!name) | ||
1521 | return NULL; | ||
1522 | name += strlen(prefix); | ||
1523 | tmp = strchr(name, ' '); | ||
1524 | if (tmp) | ||
1525 | *tmp = '\0'; | ||
1526 | |||
1527 | return strdup(name); | ||
1528 | } | ||
1529 | |||
1530 | static int map_groups__set_modules_path(struct map_groups *self, | ||
1531 | const char *root_dir) | ||
1532 | { | ||
1533 | char *version; | ||
1449 | char modules_path[PATH_MAX]; | 1534 | char modules_path[PATH_MAX]; |
1450 | 1535 | ||
1451 | if (uname(&uts) < 0) | 1536 | version = get_kernel_version(root_dir); |
1537 | if (!version) | ||
1452 | return -1; | 1538 | return -1; |
1453 | 1539 | ||
1454 | snprintf(modules_path, sizeof(modules_path), "/lib/modules/%s/kernel", | 1540 | snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel", |
1455 | uts.release); | 1541 | root_dir, version); |
1542 | free(version); | ||
1456 | 1543 | ||
1457 | return map_groups__set_modules_path_dir(self, modules_path); | 1544 | return map_groups__set_modules_path_dir(self, modules_path); |
1458 | } | 1545 | } |
@@ -1477,11 +1564,13 @@ static struct map *map__new2(u64 start, struct dso *dso, enum map_type type) | |||
1477 | } | 1564 | } |
1478 | 1565 | ||
1479 | struct map *map_groups__new_module(struct map_groups *self, u64 start, | 1566 | struct map *map_groups__new_module(struct map_groups *self, u64 start, |
1480 | const char *filename) | 1567 | const char *filename, |
1568 | struct kernel_info *kerninfo) | ||
1481 | { | 1569 | { |
1482 | struct map *map; | 1570 | struct map *map; |
1483 | struct dso *dso = __dsos__findnew(&dsos__kernel, filename); | 1571 | struct dso *dso; |
1484 | 1572 | ||
1573 | dso = __dsos__findnew(&kerninfo->dsos__kernel, filename); | ||
1485 | if (dso == NULL) | 1574 | if (dso == NULL) |
1486 | return NULL; | 1575 | return NULL; |
1487 | 1576 | ||
@@ -1489,21 +1578,37 @@ struct map *map_groups__new_module(struct map_groups *self, u64 start, | |||
1489 | if (map == NULL) | 1578 | if (map == NULL) |
1490 | return NULL; | 1579 | return NULL; |
1491 | 1580 | ||
1492 | dso->origin = DSO__ORIG_KMODULE; | 1581 | if (is_host_kernel(kerninfo)) |
1582 | dso->origin = DSO__ORIG_KMODULE; | ||
1583 | else | ||
1584 | dso->origin = DSO__ORIG_GUEST_KMODULE; | ||
1493 | map_groups__insert(self, map); | 1585 | map_groups__insert(self, map); |
1494 | return map; | 1586 | return map; |
1495 | } | 1587 | } |
1496 | 1588 | ||
1497 | static int map_groups__create_modules(struct map_groups *self) | 1589 | static int map_groups__create_modules(struct kernel_info *kerninfo) |
1498 | { | 1590 | { |
1499 | char *line = NULL; | 1591 | char *line = NULL; |
1500 | size_t n; | 1592 | size_t n; |
1501 | FILE *file = fopen("/proc/modules", "r"); | 1593 | FILE *file; |
1502 | struct map *map; | 1594 | struct map *map; |
1595 | const char *root_dir; | ||
1596 | const char *modules; | ||
1597 | char path[PATH_MAX]; | ||
1598 | |||
1599 | if (is_default_guest(kerninfo)) | ||
1600 | modules = symbol_conf.default_guest_modules; | ||
1601 | else { | ||
1602 | sprintf(path, "%s/proc/modules", kerninfo->root_dir); | ||
1603 | modules = path; | ||
1604 | } | ||
1503 | 1605 | ||
1606 | file = fopen(modules, "r"); | ||
1504 | if (file == NULL) | 1607 | if (file == NULL) |
1505 | return -1; | 1608 | return -1; |
1506 | 1609 | ||
1610 | root_dir = kerninfo->root_dir; | ||
1611 | |||
1507 | while (!feof(file)) { | 1612 | while (!feof(file)) { |
1508 | char name[PATH_MAX]; | 1613 | char name[PATH_MAX]; |
1509 | u64 start; | 1614 | u64 start; |
@@ -1532,16 +1637,17 @@ static int map_groups__create_modules(struct map_groups *self) | |||
1532 | *sep = '\0'; | 1637 | *sep = '\0'; |
1533 | 1638 | ||
1534 | snprintf(name, sizeof(name), "[%s]", line); | 1639 | snprintf(name, sizeof(name), "[%s]", line); |
1535 | map = map_groups__new_module(self, start, name); | 1640 | map = map_groups__new_module(&kerninfo->kmaps, |
1641 | start, name, kerninfo); | ||
1536 | if (map == NULL) | 1642 | if (map == NULL) |
1537 | goto out_delete_line; | 1643 | goto out_delete_line; |
1538 | dso__kernel_module_get_build_id(map->dso); | 1644 | dso__kernel_module_get_build_id(map->dso, root_dir); |
1539 | } | 1645 | } |
1540 | 1646 | ||
1541 | free(line); | 1647 | free(line); |
1542 | fclose(file); | 1648 | fclose(file); |
1543 | 1649 | ||
1544 | return map_groups__set_modules_path(self); | 1650 | return map_groups__set_modules_path(&kerninfo->kmaps, root_dir); |
1545 | 1651 | ||
1546 | out_delete_line: | 1652 | out_delete_line: |
1547 | free(line); | 1653 | free(line); |
@@ -1708,8 +1814,57 @@ out_fixup: | |||
1708 | return err; | 1814 | return err; |
1709 | } | 1815 | } |
1710 | 1816 | ||
1711 | LIST_HEAD(dsos__user); | 1817 | static int dso__load_guest_kernel_sym(struct dso *self, struct map *map, |
1712 | LIST_HEAD(dsos__kernel); | 1818 | symbol_filter_t filter) |
1819 | { | ||
1820 | int err; | ||
1821 | const char *kallsyms_filename = NULL; | ||
1822 | struct kernel_info *kerninfo; | ||
1823 | char path[PATH_MAX]; | ||
1824 | |||
1825 | if (!map->groups) { | ||
1826 | pr_debug("Guest kernel map hasn't the point to groups\n"); | ||
1827 | return -1; | ||
1828 | } | ||
1829 | kerninfo = map->groups->this_kerninfo; | ||
1830 | |||
1831 | if (is_default_guest(kerninfo)) { | ||
1832 | /* | ||
1833 | * if the user specified a vmlinux filename, use it and only | ||
1834 | * it, reporting errors to the user if it cannot be used. | ||
1835 | * Or use file guest_kallsyms inputted by user on commandline | ||
1836 | */ | ||
1837 | if (symbol_conf.default_guest_vmlinux_name != NULL) { | ||
1838 | err = dso__load_vmlinux(self, map, | ||
1839 | symbol_conf.default_guest_vmlinux_name, filter); | ||
1840 | goto out_try_fixup; | ||
1841 | } | ||
1842 | |||
1843 | kallsyms_filename = symbol_conf.default_guest_kallsyms; | ||
1844 | if (!kallsyms_filename) | ||
1845 | return -1; | ||
1846 | } else { | ||
1847 | sprintf(path, "%s/proc/kallsyms", kerninfo->root_dir); | ||
1848 | kallsyms_filename = path; | ||
1849 | } | ||
1850 | |||
1851 | err = dso__load_kallsyms(self, kallsyms_filename, map, filter); | ||
1852 | if (err > 0) | ||
1853 | pr_debug("Using %s for symbols\n", kallsyms_filename); | ||
1854 | |||
1855 | out_try_fixup: | ||
1856 | if (err > 0) { | ||
1857 | if (kallsyms_filename != NULL) { | ||
1858 | kern_mmap_name(kerninfo, path); | ||
1859 | dso__set_long_name(self, | ||
1860 | strdup(path)); | ||
1861 | } | ||
1862 | map__fixup_start(map); | ||
1863 | map__fixup_end(map); | ||
1864 | } | ||
1865 | |||
1866 | return err; | ||
1867 | } | ||
1713 | 1868 | ||
1714 | static void dsos__add(struct list_head *head, struct dso *dso) | 1869 | static void dsos__add(struct list_head *head, struct dso *dso) |
1715 | { | 1870 | { |
@@ -1752,10 +1907,16 @@ static void __dsos__fprintf(struct list_head *head, FILE *fp) | |||
1752 | } | 1907 | } |
1753 | } | 1908 | } |
1754 | 1909 | ||
1755 | void dsos__fprintf(FILE *fp) | 1910 | void dsos__fprintf(struct rb_root *kerninfo_root, FILE *fp) |
1756 | { | 1911 | { |
1757 | __dsos__fprintf(&dsos__kernel, fp); | 1912 | struct rb_node *nd; |
1758 | __dsos__fprintf(&dsos__user, fp); | 1913 | |
1914 | for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { | ||
1915 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
1916 | rb_node); | ||
1917 | __dsos__fprintf(&pos->dsos__kernel, fp); | ||
1918 | __dsos__fprintf(&pos->dsos__user, fp); | ||
1919 | } | ||
1759 | } | 1920 | } |
1760 | 1921 | ||
1761 | static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, | 1922 | static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, |
@@ -1773,10 +1934,21 @@ static size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp, | |||
1773 | return ret; | 1934 | return ret; |
1774 | } | 1935 | } |
1775 | 1936 | ||
1776 | size_t dsos__fprintf_buildid(FILE *fp, bool with_hits) | 1937 | size_t dsos__fprintf_buildid(struct rb_root *kerninfo_root, |
1938 | FILE *fp, bool with_hits) | ||
1777 | { | 1939 | { |
1778 | return (__dsos__fprintf_buildid(&dsos__kernel, fp, with_hits) + | 1940 | struct rb_node *nd; |
1779 | __dsos__fprintf_buildid(&dsos__user, fp, with_hits)); | 1941 | size_t ret = 0; |
1942 | |||
1943 | for (nd = rb_first(kerninfo_root); nd; nd = rb_next(nd)) { | ||
1944 | struct kernel_info *pos = rb_entry(nd, struct kernel_info, | ||
1945 | rb_node); | ||
1946 | ret += __dsos__fprintf_buildid(&pos->dsos__kernel, | ||
1947 | fp, with_hits); | ||
1948 | ret += __dsos__fprintf_buildid(&pos->dsos__user, | ||
1949 | fp, with_hits); | ||
1950 | } | ||
1951 | return ret; | ||
1780 | } | 1952 | } |
1781 | 1953 | ||
1782 | struct dso *dso__new_kernel(const char *name) | 1954 | struct dso *dso__new_kernel(const char *name) |
@@ -1785,28 +1957,59 @@ struct dso *dso__new_kernel(const char *name) | |||
1785 | 1957 | ||
1786 | if (self != NULL) { | 1958 | if (self != NULL) { |
1787 | dso__set_short_name(self, "[kernel]"); | 1959 | dso__set_short_name(self, "[kernel]"); |
1788 | self->kernel = 1; | 1960 | self->kernel = DSO_TYPE_KERNEL; |
1961 | } | ||
1962 | |||
1963 | return self; | ||
1964 | } | ||
1965 | |||
1966 | static struct dso *dso__new_guest_kernel(struct kernel_info *kerninfo, | ||
1967 | const char *name) | ||
1968 | { | ||
1969 | char buff[PATH_MAX]; | ||
1970 | struct dso *self; | ||
1971 | |||
1972 | kern_mmap_name(kerninfo, buff); | ||
1973 | self = dso__new(name ?: buff); | ||
1974 | if (self != NULL) { | ||
1975 | dso__set_short_name(self, "[guest.kernel]"); | ||
1976 | self->kernel = DSO_TYPE_GUEST_KERNEL; | ||
1789 | } | 1977 | } |
1790 | 1978 | ||
1791 | return self; | 1979 | return self; |
1792 | } | 1980 | } |
1793 | 1981 | ||
1794 | void dso__read_running_kernel_build_id(struct dso *self) | 1982 | void dso__read_running_kernel_build_id(struct dso *self, |
1983 | struct kernel_info *kerninfo) | ||
1795 | { | 1984 | { |
1796 | if (sysfs__read_build_id("/sys/kernel/notes", self->build_id, | 1985 | char path[PATH_MAX]; |
1986 | |||
1987 | if (is_default_guest(kerninfo)) | ||
1988 | return; | ||
1989 | sprintf(path, "%s/sys/kernel/notes", kerninfo->root_dir); | ||
1990 | if (sysfs__read_build_id(path, self->build_id, | ||
1797 | sizeof(self->build_id)) == 0) | 1991 | sizeof(self->build_id)) == 0) |
1798 | self->has_build_id = true; | 1992 | self->has_build_id = true; |
1799 | } | 1993 | } |
1800 | 1994 | ||
1801 | static struct dso *dsos__create_kernel(const char *vmlinux) | 1995 | static struct dso *dsos__create_kernel(struct kernel_info *kerninfo) |
1802 | { | 1996 | { |
1803 | struct dso *kernel = dso__new_kernel(vmlinux); | 1997 | const char *vmlinux_name = NULL; |
1998 | struct dso *kernel; | ||
1804 | 1999 | ||
1805 | if (kernel != NULL) { | 2000 | if (is_host_kernel(kerninfo)) { |
1806 | dso__read_running_kernel_build_id(kernel); | 2001 | vmlinux_name = symbol_conf.vmlinux_name; |
1807 | dsos__add(&dsos__kernel, kernel); | 2002 | kernel = dso__new_kernel(vmlinux_name); |
2003 | } else { | ||
2004 | if (is_default_guest(kerninfo)) | ||
2005 | vmlinux_name = symbol_conf.default_guest_vmlinux_name; | ||
2006 | kernel = dso__new_guest_kernel(kerninfo, vmlinux_name); | ||
1808 | } | 2007 | } |
1809 | 2008 | ||
2009 | if (kernel != NULL) { | ||
2010 | dso__read_running_kernel_build_id(kernel, kerninfo); | ||
2011 | dsos__add(&kerninfo->dsos__kernel, kernel); | ||
2012 | } | ||
1810 | return kernel; | 2013 | return kernel; |
1811 | } | 2014 | } |
1812 | 2015 | ||
@@ -1950,23 +2153,29 @@ out_free_comm_list: | |||
1950 | return -1; | 2153 | return -1; |
1951 | } | 2154 | } |
1952 | 2155 | ||
1953 | int map_groups__create_kernel_maps(struct map_groups *self, | 2156 | int map_groups__create_kernel_maps(struct rb_root *kerninfo_root, pid_t pid) |
1954 | struct map *vmlinux_maps[MAP__NR_TYPES]) | ||
1955 | { | 2157 | { |
1956 | struct dso *kernel = dsos__create_kernel(symbol_conf.vmlinux_name); | 2158 | struct kernel_info *kerninfo; |
2159 | struct dso *kernel; | ||
1957 | 2160 | ||
2161 | kerninfo = kerninfo__findnew(kerninfo_root, pid); | ||
2162 | if (kerninfo == NULL) | ||
2163 | return -1; | ||
2164 | kernel = dsos__create_kernel(kerninfo); | ||
1958 | if (kernel == NULL) | 2165 | if (kernel == NULL) |
1959 | return -1; | 2166 | return -1; |
1960 | 2167 | ||
1961 | if (__map_groups__create_kernel_maps(self, vmlinux_maps, kernel) < 0) | 2168 | if (__map_groups__create_kernel_maps(&kerninfo->kmaps, |
2169 | kerninfo->vmlinux_maps, kernel) < 0) | ||
1962 | return -1; | 2170 | return -1; |
1963 | 2171 | ||
1964 | if (symbol_conf.use_modules && map_groups__create_modules(self) < 0) | 2172 | if (symbol_conf.use_modules && |
2173 | map_groups__create_modules(kerninfo) < 0) | ||
1965 | pr_debug("Problems creating module maps, continuing anyway...\n"); | 2174 | pr_debug("Problems creating module maps, continuing anyway...\n"); |
1966 | /* | 2175 | /* |
1967 | * Now that we have all the maps created, just set the ->end of them: | 2176 | * Now that we have all the maps created, just set the ->end of them: |
1968 | */ | 2177 | */ |
1969 | map_groups__fixup_end(self); | 2178 | map_groups__fixup_end(&kerninfo->kmaps); |
1970 | return 0; | 2179 | return 0; |
1971 | } | 2180 | } |
1972 | 2181 | ||
@@ -2012,3 +2221,46 @@ char *strxfrchar(char *s, char from, char to) | |||
2012 | 2221 | ||
2013 | return s; | 2222 | return s; |
2014 | } | 2223 | } |
2224 | |||
2225 | int map_groups__create_guest_kernel_maps(struct rb_root *kerninfo_root) | ||
2226 | { | ||
2227 | int ret = 0; | ||
2228 | struct dirent **namelist = NULL; | ||
2229 | int i, items = 0; | ||
2230 | char path[PATH_MAX]; | ||
2231 | pid_t pid; | ||
2232 | |||
2233 | if (symbol_conf.default_guest_vmlinux_name || | ||
2234 | symbol_conf.default_guest_modules || | ||
2235 | symbol_conf.default_guest_kallsyms) { | ||
2236 | map_groups__create_kernel_maps(kerninfo_root, | ||
2237 | DEFAULT_GUEST_KERNEL_ID); | ||
2238 | } | ||
2239 | |||
2240 | if (symbol_conf.guestmount) { | ||
2241 | items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL); | ||
2242 | if (items <= 0) | ||
2243 | return -ENOENT; | ||
2244 | for (i = 0; i < items; i++) { | ||
2245 | if (!isdigit(namelist[i]->d_name[0])) { | ||
2246 | /* Filter out . and .. */ | ||
2247 | continue; | ||
2248 | } | ||
2249 | pid = atoi(namelist[i]->d_name); | ||
2250 | sprintf(path, "%s/%s/proc/kallsyms", | ||
2251 | symbol_conf.guestmount, | ||
2252 | namelist[i]->d_name); | ||
2253 | ret = access(path, R_OK); | ||
2254 | if (ret) { | ||
2255 | pr_debug("Can't access file %s\n", path); | ||
2256 | goto failure; | ||
2257 | } | ||
2258 | map_groups__create_kernel_maps(kerninfo_root, | ||
2259 | pid); | ||
2260 | } | ||
2261 | failure: | ||
2262 | free(namelist); | ||
2263 | } | ||
2264 | |||
2265 | return ret; | ||
2266 | } | ||