aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2012-12-07 15:39:39 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2012-12-09 06:46:08 -0500
commit3f067dcab711c2df7eefcfc5b3aa9a0e2b5f7d42 (patch)
treee90233f6af32b64f6fa230e5bf270b3ceea418fe
parentfbb6976c2f7a6ab2c4d8511181d686f5f2aaf476 (diff)
perf machine: Move more machine methods to machine.c
Mechanical, no functional changes. Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/n/tip-9ib6qtqge1jmms2luwu4udbx@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/machine.c742
-rw-r--r--tools/perf/util/machine.h3
-rw-r--r--tools/perf/util/session.c210
-rw-r--r--tools/perf/util/symbol.c522
-rw-r--r--tools/perf/util/symbol.h4
-rw-r--r--tools/perf/util/thread.c20
-rw-r--r--tools/perf/util/thread.h1
7 files changed, 756 insertions, 746 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 1f09d0581e6b..71fa90391fe4 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,10 +1,15 @@
1#include "callchain.h"
1#include "debug.h" 2#include "debug.h"
2#include "event.h" 3#include "event.h"
4#include "evsel.h"
5#include "hist.h"
3#include "machine.h" 6#include "machine.h"
4#include "map.h" 7#include "map.h"
8#include "sort.h"
5#include "strlist.h" 9#include "strlist.h"
6#include "thread.h" 10#include "thread.h"
7#include <stdbool.h> 11#include <stdbool.h>
12#include "unwind.h"
8 13
9int machine__init(struct machine *machine, const char *root_dir, pid_t pid) 14int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
10{ 15{
@@ -48,6 +53,29 @@ static void dsos__delete(struct list_head *dsos)
48 } 53 }
49} 54}
50 55
56void machine__delete_dead_threads(struct machine *machine)
57{
58 struct thread *n, *t;
59
60 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
61 list_del(&t->node);
62 thread__delete(t);
63 }
64}
65
66void machine__delete_threads(struct machine *machine)
67{
68 struct rb_node *nd = rb_first(&machine->threads);
69
70 while (nd) {
71 struct thread *t = rb_entry(nd, struct thread, rb_node);
72
73 rb_erase(&t->rb_node, &machine->threads);
74 nd = rb_next(nd);
75 thread__delete(t);
76 }
77}
78
51void machine__exit(struct machine *machine) 79void machine__exit(struct machine *machine)
52{ 80{
53 map_groups__exit(&machine->kmaps); 81 map_groups__exit(&machine->kmaps);
@@ -264,6 +292,534 @@ int machine__process_lost_event(struct machine *machine __maybe_unused,
264 return 0; 292 return 0;
265} 293}
266 294
295struct map *machine__new_module(struct machine *machine, u64 start,
296 const char *filename)
297{
298 struct map *map;
299 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, filename);
300
301 if (dso == NULL)
302 return NULL;
303
304 map = map__new2(start, dso, MAP__FUNCTION);
305 if (map == NULL)
306 return NULL;
307
308 if (machine__is_host(machine))
309 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
310 else
311 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
312 map_groups__insert(&machine->kmaps, map);
313 return map;
314}
315
316size_t machines__fprintf_dsos(struct rb_root *machines, FILE *fp)
317{
318 struct rb_node *nd;
319 size_t ret = 0;
320
321 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
322 struct machine *pos = rb_entry(nd, struct machine, rb_node);
323 ret += __dsos__fprintf(&pos->kernel_dsos, fp);
324 ret += __dsos__fprintf(&pos->user_dsos, fp);
325 }
326
327 return ret;
328}
329
330size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
331 bool (skip)(struct dso *dso, int parm), int parm)
332{
333 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
334 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
335}
336
337size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
338 bool (skip)(struct dso *dso, int parm), int parm)
339{
340 struct rb_node *nd;
341 size_t ret = 0;
342
343 for (nd = rb_first(machines); nd; nd = rb_next(nd)) {
344 struct machine *pos = rb_entry(nd, struct machine, rb_node);
345 ret += machine__fprintf_dsos_buildid(pos, fp, skip, parm);
346 }
347 return ret;
348}
349
350size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
351{
352 int i;
353 size_t printed = 0;
354 struct dso *kdso = machine->vmlinux_maps[MAP__FUNCTION]->dso;
355
356 if (kdso->has_build_id) {
357 char filename[PATH_MAX];
358 if (dso__build_id_filename(kdso, filename, sizeof(filename)))
359 printed += fprintf(fp, "[0] %s\n", filename);
360 }
361
362 for (i = 0; i < vmlinux_path__nr_entries; ++i)
363 printed += fprintf(fp, "[%d] %s\n",
364 i + kdso->has_build_id, vmlinux_path[i]);
365
366 return printed;
367}
368
369size_t machine__fprintf(struct machine *machine, FILE *fp)
370{
371 size_t ret = 0;
372 struct rb_node *nd;
373
374 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
375 struct thread *pos = rb_entry(nd, struct thread, rb_node);
376
377 ret += thread__fprintf(pos, fp);
378 }
379
380 return ret;
381}
382
383static struct dso *machine__get_kernel(struct machine *machine)
384{
385 const char *vmlinux_name = NULL;
386 struct dso *kernel;
387
388 if (machine__is_host(machine)) {
389 vmlinux_name = symbol_conf.vmlinux_name;
390 if (!vmlinux_name)
391 vmlinux_name = "[kernel.kallsyms]";
392
393 kernel = dso__kernel_findnew(machine, vmlinux_name,
394 "[kernel]",
395 DSO_TYPE_KERNEL);
396 } else {
397 char bf[PATH_MAX];
398
399 if (machine__is_default_guest(machine))
400 vmlinux_name = symbol_conf.default_guest_vmlinux_name;
401 if (!vmlinux_name)
402 vmlinux_name = machine__mmap_name(machine, bf,
403 sizeof(bf));
404
405 kernel = dso__kernel_findnew(machine, vmlinux_name,
406 "[guest.kernel]",
407 DSO_TYPE_GUEST_KERNEL);
408 }
409
410 if (kernel != NULL && (!kernel->has_build_id))
411 dso__read_running_kernel_build_id(kernel, machine);
412
413 return kernel;
414}
415
416struct process_args {
417 u64 start;
418};
419
420static int symbol__in_kernel(void *arg, const char *name,
421 char type __maybe_unused, u64 start)
422{
423 struct process_args *args = arg;
424
425 if (strchr(name, '['))
426 return 0;
427
428 args->start = start;
429 return 1;
430}
431
432/* Figure out the start address of kernel map from /proc/kallsyms */
433static u64 machine__get_kernel_start_addr(struct machine *machine)
434{
435 const char *filename;
436 char path[PATH_MAX];
437 struct process_args args;
438
439 if (machine__is_host(machine)) {
440 filename = "/proc/kallsyms";
441 } else {
442 if (machine__is_default_guest(machine))
443 filename = (char *)symbol_conf.default_guest_kallsyms;
444 else {
445 sprintf(path, "%s/proc/kallsyms", machine->root_dir);
446 filename = path;
447 }
448 }
449
450 if (symbol__restricted_filename(filename, "/proc/kallsyms"))
451 return 0;
452
453 if (kallsyms__parse(filename, &args, symbol__in_kernel) <= 0)
454 return 0;
455
456 return args.start;
457}
458
459int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
460{
461 enum map_type type;
462 u64 start = machine__get_kernel_start_addr(machine);
463
464 for (type = 0; type < MAP__NR_TYPES; ++type) {
465 struct kmap *kmap;
466
467 machine->vmlinux_maps[type] = map__new2(start, kernel, type);
468 if (machine->vmlinux_maps[type] == NULL)
469 return -1;
470
471 machine->vmlinux_maps[type]->map_ip =
472 machine->vmlinux_maps[type]->unmap_ip =
473 identity__map_ip;
474 kmap = map__kmap(machine->vmlinux_maps[type]);
475 kmap->kmaps = &machine->kmaps;
476 map_groups__insert(&machine->kmaps,
477 machine->vmlinux_maps[type]);
478 }
479
480 return 0;
481}
482
483void machine__destroy_kernel_maps(struct machine *machine)
484{
485 enum map_type type;
486
487 for (type = 0; type < MAP__NR_TYPES; ++type) {
488 struct kmap *kmap;
489
490 if (machine->vmlinux_maps[type] == NULL)
491 continue;
492
493 kmap = map__kmap(machine->vmlinux_maps[type]);
494 map_groups__remove(&machine->kmaps,
495 machine->vmlinux_maps[type]);
496 if (kmap->ref_reloc_sym) {
497 /*
498 * ref_reloc_sym is shared among all maps, so free just
499 * on one of them.
500 */
501 if (type == MAP__FUNCTION) {
502 free((char *)kmap->ref_reloc_sym->name);
503 kmap->ref_reloc_sym->name = NULL;
504 free(kmap->ref_reloc_sym);
505 }
506 kmap->ref_reloc_sym = NULL;
507 }
508
509 map__delete(machine->vmlinux_maps[type]);
510 machine->vmlinux_maps[type] = NULL;
511 }
512}
513
514int machines__create_guest_kernel_maps(struct rb_root *machines)
515{
516 int ret = 0;
517 struct dirent **namelist = NULL;
518 int i, items = 0;
519 char path[PATH_MAX];
520 pid_t pid;
521 char *endp;
522
523 if (symbol_conf.default_guest_vmlinux_name ||
524 symbol_conf.default_guest_modules ||
525 symbol_conf.default_guest_kallsyms) {
526 machines__create_kernel_maps(machines, DEFAULT_GUEST_KERNEL_ID);
527 }
528
529 if (symbol_conf.guestmount) {
530 items = scandir(symbol_conf.guestmount, &namelist, NULL, NULL);
531 if (items <= 0)
532 return -ENOENT;
533 for (i = 0; i < items; i++) {
534 if (!isdigit(namelist[i]->d_name[0])) {
535 /* Filter out . and .. */
536 continue;
537 }
538 pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
539 if ((*endp != '\0') ||
540 (endp == namelist[i]->d_name) ||
541 (errno == ERANGE)) {
542 pr_debug("invalid directory (%s). Skipping.\n",
543 namelist[i]->d_name);
544 continue;
545 }
546 sprintf(path, "%s/%s/proc/kallsyms",
547 symbol_conf.guestmount,
548 namelist[i]->d_name);
549 ret = access(path, R_OK);
550 if (ret) {
551 pr_debug("Can't access file %s\n", path);
552 goto failure;
553 }
554 machines__create_kernel_maps(machines, pid);
555 }
556failure:
557 free(namelist);
558 }
559
560 return ret;
561}
562
563void machines__destroy_guest_kernel_maps(struct rb_root *machines)
564{
565 struct rb_node *next = rb_first(machines);
566
567 while (next) {
568 struct machine *pos = rb_entry(next, struct machine, rb_node);
569
570 next = rb_next(&pos->rb_node);
571 rb_erase(&pos->rb_node, machines);
572 machine__delete(pos);
573 }
574}
575
576int machines__create_kernel_maps(struct rb_root *machines, pid_t pid)
577{
578 struct machine *machine = machines__findnew(machines, pid);
579
580 if (machine == NULL)
581 return -1;
582
583 return machine__create_kernel_maps(machine);
584}
585
586int machine__load_kallsyms(struct machine *machine, const char *filename,
587 enum map_type type, symbol_filter_t filter)
588{
589 struct map *map = machine->vmlinux_maps[type];
590 int ret = dso__load_kallsyms(map->dso, filename, map, filter);
591
592 if (ret > 0) {
593 dso__set_loaded(map->dso, type);
594 /*
595 * Since /proc/kallsyms will have multiple sessions for the
596 * kernel, with modules between them, fixup the end of all
597 * sections.
598 */
599 __map_groups__fixup_end(&machine->kmaps, type);
600 }
601
602 return ret;
603}
604
605int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
606 symbol_filter_t filter)
607{
608 struct map *map = machine->vmlinux_maps[type];
609 int ret = dso__load_vmlinux_path(map->dso, map, filter);
610
611 if (ret > 0) {
612 dso__set_loaded(map->dso, type);
613 map__reloc_vmlinux(map);
614 }
615
616 return ret;
617}
618
619static void map_groups__fixup_end(struct map_groups *mg)
620{
621 int i;
622 for (i = 0; i < MAP__NR_TYPES; ++i)
623 __map_groups__fixup_end(mg, i);
624}
625
626static char *get_kernel_version(const char *root_dir)
627{
628 char version[PATH_MAX];
629 FILE *file;
630 char *name, *tmp;
631 const char *prefix = "Linux version ";
632
633 sprintf(version, "%s/proc/version", root_dir);
634 file = fopen(version, "r");
635 if (!file)
636 return NULL;
637
638 version[0] = '\0';
639 tmp = fgets(version, sizeof(version), file);
640 fclose(file);
641
642 name = strstr(version, prefix);
643 if (!name)
644 return NULL;
645 name += strlen(prefix);
646 tmp = strchr(name, ' ');
647 if (tmp)
648 *tmp = '\0';
649
650 return strdup(name);
651}
652
653static int map_groups__set_modules_path_dir(struct map_groups *mg,
654 const char *dir_name)
655{
656 struct dirent *dent;
657 DIR *dir = opendir(dir_name);
658 int ret = 0;
659
660 if (!dir) {
661 pr_debug("%s: cannot open %s dir\n", __func__, dir_name);
662 return -1;
663 }
664
665 while ((dent = readdir(dir)) != NULL) {
666 char path[PATH_MAX];
667 struct stat st;
668
669 /*sshfs might return bad dent->d_type, so we have to stat*/
670 snprintf(path, sizeof(path), "%s/%s", dir_name, dent->d_name);
671 if (stat(path, &st))
672 continue;
673
674 if (S_ISDIR(st.st_mode)) {
675 if (!strcmp(dent->d_name, ".") ||
676 !strcmp(dent->d_name, ".."))
677 continue;
678
679 ret = map_groups__set_modules_path_dir(mg, path);
680 if (ret < 0)
681 goto out;
682 } else {
683 char *dot = strrchr(dent->d_name, '.'),
684 dso_name[PATH_MAX];
685 struct map *map;
686 char *long_name;
687
688 if (dot == NULL || strcmp(dot, ".ko"))
689 continue;
690 snprintf(dso_name, sizeof(dso_name), "[%.*s]",
691 (int)(dot - dent->d_name), dent->d_name);
692
693 strxfrchar(dso_name, '-', '_');
694 map = map_groups__find_by_name(mg, MAP__FUNCTION,
695 dso_name);
696 if (map == NULL)
697 continue;
698
699 long_name = strdup(path);
700 if (long_name == NULL) {
701 ret = -1;
702 goto out;
703 }
704 dso__set_long_name(map->dso, long_name);
705 map->dso->lname_alloc = 1;
706 dso__kernel_module_get_build_id(map->dso, "");
707 }
708 }
709
710out:
711 closedir(dir);
712 return ret;
713}
714
715static int machine__set_modules_path(struct machine *machine)
716{
717 char *version;
718 char modules_path[PATH_MAX];
719
720 version = get_kernel_version(machine->root_dir);
721 if (!version)
722 return -1;
723
724 snprintf(modules_path, sizeof(modules_path), "%s/lib/modules/%s/kernel",
725 machine->root_dir, version);
726 free(version);
727
728 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);
729}
730
731static int machine__create_modules(struct machine *machine)
732{
733 char *line = NULL;
734 size_t n;
735 FILE *file;
736 struct map *map;
737 const char *modules;
738 char path[PATH_MAX];
739
740 if (machine__is_default_guest(machine))
741 modules = symbol_conf.default_guest_modules;
742 else {
743 sprintf(path, "%s/proc/modules", machine->root_dir);
744 modules = path;
745 }
746
747 if (symbol__restricted_filename(path, "/proc/modules"))
748 return -1;
749
750 file = fopen(modules, "r");
751 if (file == NULL)
752 return -1;
753
754 while (!feof(file)) {
755 char name[PATH_MAX];
756 u64 start;
757 char *sep;
758 int line_len;
759
760 line_len = getline(&line, &n, file);
761 if (line_len < 0)
762 break;
763
764 if (!line)
765 goto out_failure;
766
767 line[--line_len] = '\0'; /* \n */
768
769 sep = strrchr(line, 'x');
770 if (sep == NULL)
771 continue;
772
773 hex2u64(sep + 1, &start);
774
775 sep = strchr(line, ' ');
776 if (sep == NULL)
777 continue;
778
779 *sep = '\0';
780
781 snprintf(name, sizeof(name), "[%s]", line);
782 map = machine__new_module(machine, start, name);
783 if (map == NULL)
784 goto out_delete_line;
785 dso__kernel_module_get_build_id(map->dso, machine->root_dir);
786 }
787
788 free(line);
789 fclose(file);
790
791 return machine__set_modules_path(machine);
792
793out_delete_line:
794 free(line);
795out_failure:
796 return -1;
797}
798
799int machine__create_kernel_maps(struct machine *machine)
800{
801 struct dso *kernel = machine__get_kernel(machine);
802
803 if (kernel == NULL ||
804 __machine__create_kernel_maps(machine, kernel) < 0)
805 return -1;
806
807 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
808 if (machine__is_host(machine))
809 pr_debug("Problems creating module maps, "
810 "continuing anyway...\n");
811 else
812 pr_debug("Problems creating module maps for guest %d, "
813 "continuing anyway...\n", machine->pid);
814 }
815
816 /*
817 * Now that we have all the maps created, just set the ->end of them:
818 */
819 map_groups__fixup_end(&machine->kmaps);
820 return 0;
821}
822
267static void machine__set_kernel_mmap_len(struct machine *machine, 823static void machine__set_kernel_mmap_len(struct machine *machine,
268 union perf_event *event) 824 union perf_event *event)
269{ 825{
@@ -462,3 +1018,189 @@ int machine__process_event(struct machine *machine, union perf_event *event)
462 1018
463 return ret; 1019 return ret;
464} 1020}
1021
1022void machine__remove_thread(struct machine *machine, struct thread *th)
1023{
1024 machine->last_match = NULL;
1025 rb_erase(&th->rb_node, &machine->threads);
1026 /*
1027 * We may have references to this thread, for instance in some hist_entry
1028 * instances, so just move them to a separate list.
1029 */
1030 list_add_tail(&th->node, &machine->dead_threads);
1031}
1032
1033static bool symbol__match_parent_regex(struct symbol *sym)
1034{
1035 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
1036 return 1;
1037
1038 return 0;
1039}
1040
1041static const u8 cpumodes[] = {
1042 PERF_RECORD_MISC_USER,
1043 PERF_RECORD_MISC_KERNEL,
1044 PERF_RECORD_MISC_GUEST_USER,
1045 PERF_RECORD_MISC_GUEST_KERNEL
1046};
1047#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
1048
1049static void ip__resolve_ams(struct machine *machine, struct thread *thread,
1050 struct addr_map_symbol *ams,
1051 u64 ip)
1052{
1053 struct addr_location al;
1054 size_t i;
1055 u8 m;
1056
1057 memset(&al, 0, sizeof(al));
1058
1059 for (i = 0; i < NCPUMODES; i++) {
1060 m = cpumodes[i];
1061 /*
1062 * We cannot use the header.misc hint to determine whether a
1063 * branch stack address is user, kernel, guest, hypervisor.
1064 * Branches may straddle the kernel/user/hypervisor boundaries.
1065 * Thus, we have to try consecutively until we find a match
1066 * or else, the symbol is unknown
1067 */
1068 thread__find_addr_location(thread, machine, m, MAP__FUNCTION,
1069 ip, &al, NULL);
1070 if (al.sym)
1071 goto found;
1072 }
1073found:
1074 ams->addr = ip;
1075 ams->al_addr = al.addr;
1076 ams->sym = al.sym;
1077 ams->map = al.map;
1078}
1079
1080struct branch_info *machine__resolve_bstack(struct machine *machine,
1081 struct thread *thr,
1082 struct branch_stack *bs)
1083{
1084 struct branch_info *bi;
1085 unsigned int i;
1086
1087 bi = calloc(bs->nr, sizeof(struct branch_info));
1088 if (!bi)
1089 return NULL;
1090
1091 for (i = 0; i < bs->nr; i++) {
1092 ip__resolve_ams(machine, thr, &bi[i].to, bs->entries[i].to);
1093 ip__resolve_ams(machine, thr, &bi[i].from, bs->entries[i].from);
1094 bi[i].flags = bs->entries[i].flags;
1095 }
1096 return bi;
1097}
1098
1099static int machine__resolve_callchain_sample(struct machine *machine,
1100 struct thread *thread,
1101 struct ip_callchain *chain,
1102 struct symbol **parent)
1103
1104{
1105 u8 cpumode = PERF_RECORD_MISC_USER;
1106 unsigned int i;
1107 int err;
1108
1109 callchain_cursor_reset(&callchain_cursor);
1110
1111 if (chain->nr > PERF_MAX_STACK_DEPTH) {
1112 pr_warning("corrupted callchain. skipping...\n");
1113 return 0;
1114 }
1115
1116 for (i = 0; i < chain->nr; i++) {
1117 u64 ip;
1118 struct addr_location al;
1119
1120 if (callchain_param.order == ORDER_CALLEE)
1121 ip = chain->ips[i];
1122 else
1123 ip = chain->ips[chain->nr - i - 1];
1124
1125 if (ip >= PERF_CONTEXT_MAX) {
1126 switch (ip) {
1127 case PERF_CONTEXT_HV:
1128 cpumode = PERF_RECORD_MISC_HYPERVISOR;
1129 break;
1130 case PERF_CONTEXT_KERNEL:
1131 cpumode = PERF_RECORD_MISC_KERNEL;
1132 break;
1133 case PERF_CONTEXT_USER:
1134 cpumode = PERF_RECORD_MISC_USER;
1135 break;
1136 default:
1137 pr_debug("invalid callchain context: "
1138 "%"PRId64"\n", (s64) ip);
1139 /*
1140 * It seems the callchain is corrupted.
1141 * Discard all.
1142 */
1143 callchain_cursor_reset(&callchain_cursor);
1144 return 0;
1145 }
1146 continue;
1147 }
1148
1149 al.filtered = false;
1150 thread__find_addr_location(thread, machine, cpumode,
1151 MAP__FUNCTION, ip, &al, NULL);
1152 if (al.sym != NULL) {
1153 if (sort__has_parent && !*parent &&
1154 symbol__match_parent_regex(al.sym))
1155 *parent = al.sym;
1156 if (!symbol_conf.use_callchain)
1157 break;
1158 }
1159
1160 err = callchain_cursor_append(&callchain_cursor,
1161 ip, al.map, al.sym);
1162 if (err)
1163 return err;
1164 }
1165
1166 return 0;
1167}
1168
1169static int unwind_entry(struct unwind_entry *entry, void *arg)
1170{
1171 struct callchain_cursor *cursor = arg;
1172 return callchain_cursor_append(cursor, entry->ip,
1173 entry->map, entry->sym);
1174}
1175
1176int machine__resolve_callchain(struct machine *machine,
1177 struct perf_evsel *evsel,
1178 struct thread *thread,
1179 struct perf_sample *sample,
1180 struct symbol **parent)
1181
1182{
1183 int ret;
1184
1185 callchain_cursor_reset(&callchain_cursor);
1186
1187 ret = machine__resolve_callchain_sample(machine, thread,
1188 sample->callchain, parent);
1189 if (ret)
1190 return ret;
1191
1192 /* Can we do dwarf post unwind? */
1193 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
1194 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
1195 return 0;
1196
1197 /* Bail out if nothing was captured. */
1198 if ((!sample->user_regs.regs) ||
1199 (!sample->user_stack.size))
1200 return 0;
1201
1202 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
1203 thread, evsel->attr.sample_regs_user,
1204 sample);
1205
1206}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 646ad13005d3..e11236878ec1 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -61,9 +61,10 @@ char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
61 61
62int machine__init(struct machine *machine, const char *root_dir, pid_t pid); 62int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
63void machine__exit(struct machine *machine); 63void machine__exit(struct machine *machine);
64void machine__delete_dead_threads(struct machine *machine);
65void machine__delete_threads(struct machine *machine);
64void machine__delete(struct machine *machine); 66void machine__delete(struct machine *machine);
65 67
66
67struct branch_info *machine__resolve_bstack(struct machine *machine, 68struct branch_info *machine__resolve_bstack(struct machine *machine,
68 struct thread *thread, 69 struct thread *thread,
69 struct branch_stack *bs); 70 struct branch_stack *bs);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8d04dfbc205c..76d6e257b8a4 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -16,7 +16,6 @@
16#include "cpumap.h" 16#include "cpumap.h"
17#include "event-parse.h" 17#include "event-parse.h"
18#include "perf_regs.h" 18#include "perf_regs.h"
19#include "unwind.h"
20#include "vdso.h" 19#include "vdso.h"
21 20
22static int perf_session__open(struct perf_session *self, bool force) 21static int perf_session__open(struct perf_session *self, bool force)
@@ -162,34 +161,11 @@ out_delete:
162 return NULL; 161 return NULL;
163} 162}
164 163
165static void machine__delete_dead_threads(struct machine *machine)
166{
167 struct thread *n, *t;
168
169 list_for_each_entry_safe(t, n, &machine->dead_threads, node) {
170 list_del(&t->node);
171 thread__delete(t);
172 }
173}
174
175static void perf_session__delete_dead_threads(struct perf_session *session) 164static void perf_session__delete_dead_threads(struct perf_session *session)
176{ 165{
177 machine__delete_dead_threads(&session->host_machine); 166 machine__delete_dead_threads(&session->host_machine);
178} 167}
179 168
180static void machine__delete_threads(struct machine *self)
181{
182 struct rb_node *nd = rb_first(&self->threads);
183
184 while (nd) {
185 struct thread *t = rb_entry(nd, struct thread, rb_node);
186
187 rb_erase(&t->rb_node, &self->threads);
188 nd = rb_next(nd);
189 thread__delete(t);
190 }
191}
192
193static void perf_session__delete_threads(struct perf_session *session) 169static void perf_session__delete_threads(struct perf_session *session)
194{ 170{
195 machine__delete_threads(&session->host_machine); 171 machine__delete_threads(&session->host_machine);
@@ -223,192 +199,6 @@ void perf_session__delete(struct perf_session *self)
223 vdso__exit(); 199 vdso__exit();
224} 200}
225 201
226void machine__remove_thread(struct machine *self, struct thread *th)
227{
228 self->last_match = NULL;
229 rb_erase(&th->rb_node, &self->threads);
230 /*
231 * We may have references to this thread, for instance in some hist_entry
232 * instances, so just move them to a separate list.
233 */
234 list_add_tail(&th->node, &self->dead_threads);
235}
236
237static bool symbol__match_parent_regex(struct symbol *sym)
238{
239 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
240 return 1;
241
242 return 0;
243}
244
245static const u8 cpumodes[] = {
246 PERF_RECORD_MISC_USER,
247 PERF_RECORD_MISC_KERNEL,
248 PERF_RECORD_MISC_GUEST_USER,
249 PERF_RECORD_MISC_GUEST_KERNEL
250};
251#define NCPUMODES (sizeof(cpumodes)/sizeof(u8))
252
253static void ip__resolve_ams(struct machine *self, struct thread *thread,
254 struct addr_map_symbol *ams,
255 u64 ip)
256{
257 struct addr_location al;
258 size_t i;
259 u8 m;
260
261 memset(&al, 0, sizeof(al));
262
263 for (i = 0; i < NCPUMODES; i++) {
264 m = cpumodes[i];
265 /*
266 * We cannot use the header.misc hint to determine whether a
267 * branch stack address is user, kernel, guest, hypervisor.
268 * Branches may straddle the kernel/user/hypervisor boundaries.
269 * Thus, we have to try consecutively until we find a match
270 * or else, the symbol is unknown
271 */
272 thread__find_addr_location(thread, self, m, MAP__FUNCTION,
273 ip, &al, NULL);
274 if (al.sym)
275 goto found;
276 }
277found:
278 ams->addr = ip;
279 ams->al_addr = al.addr;
280 ams->sym = al.sym;
281 ams->map = al.map;
282}
283
284struct branch_info *machine__resolve_bstack(struct machine *self,
285 struct thread *thr,
286 struct branch_stack *bs)
287{
288 struct branch_info *bi;
289 unsigned int i;
290
291 bi = calloc(bs->nr, sizeof(struct branch_info));
292 if (!bi)
293 return NULL;
294
295 for (i = 0; i < bs->nr; i++) {
296 ip__resolve_ams(self, thr, &bi[i].to, bs->entries[i].to);
297 ip__resolve_ams(self, thr, &bi[i].from, bs->entries[i].from);
298 bi[i].flags = bs->entries[i].flags;
299 }
300 return bi;
301}
302
303static int machine__resolve_callchain_sample(struct machine *machine,
304 struct thread *thread,
305 struct ip_callchain *chain,
306 struct symbol **parent)
307
308{
309 u8 cpumode = PERF_RECORD_MISC_USER;
310 unsigned int i;
311 int err;
312
313 callchain_cursor_reset(&callchain_cursor);
314
315 if (chain->nr > PERF_MAX_STACK_DEPTH) {
316 pr_warning("corrupted callchain. skipping...\n");
317 return 0;
318 }
319
320 for (i = 0; i < chain->nr; i++) {
321 u64 ip;
322 struct addr_location al;
323
324 if (callchain_param.order == ORDER_CALLEE)
325 ip = chain->ips[i];
326 else
327 ip = chain->ips[chain->nr - i - 1];
328
329 if (ip >= PERF_CONTEXT_MAX) {
330 switch (ip) {
331 case PERF_CONTEXT_HV:
332 cpumode = PERF_RECORD_MISC_HYPERVISOR;
333 break;
334 case PERF_CONTEXT_KERNEL:
335 cpumode = PERF_RECORD_MISC_KERNEL;
336 break;
337 case PERF_CONTEXT_USER:
338 cpumode = PERF_RECORD_MISC_USER;
339 break;
340 default:
341 pr_debug("invalid callchain context: "
342 "%"PRId64"\n", (s64) ip);
343 /*
344 * It seems the callchain is corrupted.
345 * Discard all.
346 */
347 callchain_cursor_reset(&callchain_cursor);
348 return 0;
349 }
350 continue;
351 }
352
353 al.filtered = false;
354 thread__find_addr_location(thread, machine, cpumode,
355 MAP__FUNCTION, ip, &al, NULL);
356 if (al.sym != NULL) {
357 if (sort__has_parent && !*parent &&
358 symbol__match_parent_regex(al.sym))
359 *parent = al.sym;
360 if (!symbol_conf.use_callchain)
361 break;
362 }
363
364 err = callchain_cursor_append(&callchain_cursor,
365 ip, al.map, al.sym);
366 if (err)
367 return err;
368 }
369
370 return 0;
371}
372
373static int unwind_entry(struct unwind_entry *entry, void *arg)
374{
375 struct callchain_cursor *cursor = arg;
376 return callchain_cursor_append(cursor, entry->ip,
377 entry->map, entry->sym);
378}
379
380int machine__resolve_callchain(struct machine *machine,
381 struct perf_evsel *evsel,
382 struct thread *thread,
383 struct perf_sample *sample,
384 struct symbol **parent)
385
386{
387 int ret;
388
389 callchain_cursor_reset(&callchain_cursor);
390
391 ret = machine__resolve_callchain_sample(machine, thread,
392 sample->callchain, parent);
393 if (ret)
394 return ret;
395
396 /* Can we do dwarf post unwind? */
397 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
398 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
399 return 0;
400
401 /* Bail out if nothing was captured. */
402 if ((!sample->user_regs.regs) ||
403 (!sample->user_stack.size))
404 return 0;
405
406 return unwind__get_entries(unwind_entry, &callchain_cursor, machine,
407 thread, evsel->attr.sample_regs_user,
408 sample);
409
410}
411
412static int process_event_synth_tracing_data_stub(union perf_event *event 202static int process_event_synth_tracing_data_stub(union perf_event *event
413 __maybe_unused, 203 __maybe_unused,
414 struct perf_session *session 204 struct perf_session *session
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e5ba9840ac22..2960284d6ae1 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);
29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 29static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
30 symbol_filter_t filter); 30 symbol_filter_t filter);
31static int vmlinux_path__nr_entries; 31int vmlinux_path__nr_entries;
32static char **vmlinux_path; 32char **vmlinux_path;
33 33
34struct symbol_conf symbol_conf = { 34struct 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
205static 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
212struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) 205struct 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
655static bool symbol__restricted_filename(const char *filename, 648bool 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
@@ -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
890static 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
947out:
948 closedir(dir);
949 return ret;
950}
951
952static 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
979static 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
995struct 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
1016static 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
1078out_delete_line:
1079 free(line);
1080out_failure:
1081 return -1;
1082}
1083
1084int dso__load_vmlinux(struct dso *dso, struct map *map, 883int 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{
@@ -1300,195 +1099,6 @@ out_try_fixup:
1300 return err; 1099 return err;
1301} 1100}
1302 1101
1303size_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
1317size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
1318 bool (skip)(struct dso *dso, int parm), int parm)
1319{
1320 return __dsos__fprintf_buildid(&machine->kernel_dsos, fp, skip, parm) +
1321 __dsos__fprintf_buildid(&machine->user_dsos, fp, skip, parm);
1322}
1323
1324size_t machines__fprintf_dsos_buildid(struct rb_root *machines, FILE *fp,
1325 bool (skip)(struct dso *dso, int parm), int parm)
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, skip, parm);
1333 }
1334 return ret;
1335}
1336
1337static 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
1370struct process_args {
1371 u64 start;
1372};
1373
1374static 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 */
1387static 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
1413int __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
1437void 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
1468int 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
1492static void vmlinux_path__exit(void) 1102static void vmlinux_path__exit(void)
1493{ 1103{
1494 while (--vmlinux_path__nr_entries >= 0) { 1104 while (--vmlinux_path__nr_entries >= 0) {
@@ -1549,25 +1159,6 @@ out_fail:
1549 return -1; 1159 return -1;
1550} 1160}
1551 1161
1552size_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
1571static int setup_list(struct strlist **list, const char *list_str, 1162static int setup_list(struct strlist **list, const char *list_str,
1572 const char *list_name) 1163 const char *list_name)
1573{ 1164{
@@ -1671,108 +1262,3 @@ void symbol__exit(void)
1671 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 1262 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
1672 symbol_conf.initialized = false; 1263 symbol_conf.initialized = false;
1673} 1264}
1674
1675int 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
1685int 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 }
1727failure:
1728 free(namelist);
1729 }
1730
1731 return ret;
1732}
1733
1734void 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
1747int 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
1766int 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}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index de68f98b236d..ec7b2405c377 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -120,6 +120,8 @@ struct symbol_conf {
120}; 120};
121 121
122extern struct symbol_conf symbol_conf; 122extern struct symbol_conf symbol_conf;
123extern int vmlinux_path__nr_entries;
124extern char **vmlinux_path;
123 125
124static inline void *symbol__priv(struct symbol *sym) 126static inline void *symbol__priv(struct symbol *sym)
125{ 127{
@@ -223,6 +225,8 @@ size_t symbol__fprintf_symname_offs(const struct symbol *sym,
223size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 225size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
224size_t symbol__fprintf(struct symbol *sym, FILE *fp); 226size_t symbol__fprintf(struct symbol *sym, FILE *fp);
225bool symbol_type__is_a(char symbol_type, enum map_type map_type); 227bool symbol_type__is_a(char symbol_type, enum map_type map_type);
228bool symbol__restricted_filename(const char *filename,
229 const char *restricted_filename);
226 230
227int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 231int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
228 struct symsrc *runtime_ss, symbol_filter_t filter, 232 struct symsrc *runtime_ss, symbol_filter_t filter,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index df59623ac763..632e40e5ceca 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -54,10 +54,10 @@ int thread__comm_len(struct thread *self)
54 return self->comm_len; 54 return self->comm_len;
55} 55}
56 56
57static size_t thread__fprintf(struct thread *self, FILE *fp) 57size_t thread__fprintf(struct thread *thread, FILE *fp)
58{ 58{
59 return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + 59 return fprintf(fp, "Thread %d %s\n", thread->pid, thread->comm) +
60 map_groups__fprintf(&self->mg, verbose, fp); 60 map_groups__fprintf(&thread->mg, verbose, fp);
61} 61}
62 62
63void thread__insert_map(struct thread *self, struct map *map) 63void thread__insert_map(struct thread *self, struct map *map)
@@ -84,17 +84,3 @@ int thread__fork(struct thread *self, struct thread *parent)
84 return -ENOMEM; 84 return -ENOMEM;
85 return 0; 85 return 0;
86} 86}
87
88size_t machine__fprintf(struct machine *machine, FILE *fp)
89{
90 size_t ret = 0;
91 struct rb_node *nd;
92
93 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
94 struct thread *pos = rb_entry(nd, struct thread, rb_node);
95
96 ret += thread__fprintf(pos, fp);
97 }
98
99 return ret;
100}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index f2fa17caa7d5..5ad266403098 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -30,6 +30,7 @@ int thread__set_comm(struct thread *self, const char *comm);
30int thread__comm_len(struct thread *self); 30int thread__comm_len(struct thread *self);
31void thread__insert_map(struct thread *self, struct map *map); 31void thread__insert_map(struct thread *self, struct map *map);
32int thread__fork(struct thread *self, struct thread *parent); 32int thread__fork(struct thread *self, struct thread *parent);
33size_t thread__fprintf(struct thread *thread, FILE *fp);
33 34
34static inline struct map *thread__find_map(struct thread *self, 35static inline struct map *thread__find_map(struct thread *self,
35 enum map_type type, u64 addr) 36 enum map_type type, u64 addr)