diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2013-08-07 07:38:51 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-08-07 16:35:33 -0400 |
commit | 8e0cf965f95edd41df11cca50b92b4cb6ea8d80a (patch) | |
tree | 08c55f2c5caaccf3c479a71fb730594164e8e23c | |
parent | 0131c4ec794a7409eafff0c79105309540aaca4d (diff) |
perf symbols: Add support for reading from /proc/kcore
In the absence of vmlinux, perf tools uses kallsyms for symbols. If the
user has access, now also map to /proc/kcore.
The dso data_type is now set to either DSO_BINARY_TYPE__KCORE or
DSO_BINARY_TYPE__GUEST_KCORE as approprite.
This patch breaks the "vmlinux symtab matches kallsyms" test. That is
fixed in a following patch.
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
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/r/1375875537-4509-8-git-send-email-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/util/dso.c | 5 | ||||
-rw-r--r-- | tools/perf/util/dso.h | 8 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 16 | ||||
-rw-r--r-- | tools/perf/util/map.c | 18 | ||||
-rw-r--r-- | tools/perf/util/map.h | 13 | ||||
-rw-r--r-- | tools/perf/util/symbol-elf.c | 51 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 7 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 227 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 5 |
9 files changed, 347 insertions, 3 deletions
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index 1955804e82ff..e3c1ff8512c8 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c | |||
@@ -95,6 +95,11 @@ int dso__binary_type_file(struct dso *dso, enum dso_binary_type type, | |||
95 | dso->long_name); | 95 | dso->long_name); |
96 | break; | 96 | break; |
97 | 97 | ||
98 | case DSO_BINARY_TYPE__KCORE: | ||
99 | case DSO_BINARY_TYPE__GUEST_KCORE: | ||
100 | snprintf(file, size, "%s", dso->long_name); | ||
101 | break; | ||
102 | |||
98 | default: | 103 | default: |
99 | case DSO_BINARY_TYPE__KALLSYMS: | 104 | case DSO_BINARY_TYPE__KALLSYMS: |
100 | case DSO_BINARY_TYPE__GUEST_KALLSYMS: | 105 | case DSO_BINARY_TYPE__GUEST_KALLSYMS: |
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 735a83751b19..b793053335d6 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h | |||
@@ -21,6 +21,8 @@ enum dso_binary_type { | |||
21 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, | 21 | DSO_BINARY_TYPE__SYSTEM_PATH_DSO, |
22 | DSO_BINARY_TYPE__GUEST_KMODULE, | 22 | DSO_BINARY_TYPE__GUEST_KMODULE, |
23 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, | 23 | DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE, |
24 | DSO_BINARY_TYPE__KCORE, | ||
25 | DSO_BINARY_TYPE__GUEST_KCORE, | ||
24 | DSO_BINARY_TYPE__NOT_FOUND, | 26 | DSO_BINARY_TYPE__NOT_FOUND, |
25 | }; | 27 | }; |
26 | 28 | ||
@@ -155,4 +157,10 @@ static inline bool dso__is_vmlinux(struct dso *dso) | |||
155 | dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX; | 157 | dso->data_type == DSO_BINARY_TYPE__GUEST_VMLINUX; |
156 | } | 158 | } |
157 | 159 | ||
160 | static inline bool dso__is_kcore(struct dso *dso) | ||
161 | { | ||
162 | return dso->data_type == DSO_BINARY_TYPE__KCORE || | ||
163 | dso->data_type == DSO_BINARY_TYPE__GUEST_KCORE; | ||
164 | } | ||
165 | |||
158 | #endif /* __PERF_DSO */ | 166 | #endif /* __PERF_DSO */ |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index dc35dcffbd05..ef3b49cde04e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -856,6 +856,18 @@ static void machine__set_kernel_mmap_len(struct machine *machine, | |||
856 | } | 856 | } |
857 | } | 857 | } |
858 | 858 | ||
859 | static bool machine__uses_kcore(struct machine *machine) | ||
860 | { | ||
861 | struct dso *dso; | ||
862 | |||
863 | list_for_each_entry(dso, &machine->kernel_dsos, node) { | ||
864 | if (dso__is_kcore(dso)) | ||
865 | return true; | ||
866 | } | ||
867 | |||
868 | return false; | ||
869 | } | ||
870 | |||
859 | static int machine__process_kernel_mmap_event(struct machine *machine, | 871 | static int machine__process_kernel_mmap_event(struct machine *machine, |
860 | union perf_event *event) | 872 | union perf_event *event) |
861 | { | 873 | { |
@@ -864,6 +876,10 @@ static int machine__process_kernel_mmap_event(struct machine *machine, | |||
864 | enum dso_kernel_type kernel_type; | 876 | enum dso_kernel_type kernel_type; |
865 | bool is_kernel_mmap; | 877 | bool is_kernel_mmap; |
866 | 878 | ||
879 | /* If we have maps from kcore then we do not need or want any others */ | ||
880 | if (machine__uses_kcore(machine)) | ||
881 | return 0; | ||
882 | |||
867 | machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); | 883 | machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix)); |
868 | if (machine__is_host(machine)) | 884 | if (machine__is_host(machine)) |
869 | kernel_type = DSO_TYPE_KERNEL; | 885 | kernel_type = DSO_TYPE_KERNEL; |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 4d599febfb0b..9e8304ca343e 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -555,3 +555,21 @@ struct map *maps__find(struct rb_root *maps, u64 ip) | |||
555 | 555 | ||
556 | return NULL; | 556 | return NULL; |
557 | } | 557 | } |
558 | |||
559 | struct map *maps__first(struct rb_root *maps) | ||
560 | { | ||
561 | struct rb_node *first = rb_first(maps); | ||
562 | |||
563 | if (first) | ||
564 | return rb_entry(first, struct map, rb_node); | ||
565 | return NULL; | ||
566 | } | ||
567 | |||
568 | struct map *maps__next(struct map *map) | ||
569 | { | ||
570 | struct rb_node *next = rb_next(&map->rb_node); | ||
571 | |||
572 | if (next) | ||
573 | return rb_entry(next, struct map, rb_node); | ||
574 | return NULL; | ||
575 | } | ||
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index a887f2c9dfbb..2cc93cbf0e17 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -112,6 +112,8 @@ size_t __map_groups__fprintf_maps(struct map_groups *mg, | |||
112 | void maps__insert(struct rb_root *maps, struct map *map); | 112 | void maps__insert(struct rb_root *maps, struct map *map); |
113 | void maps__remove(struct rb_root *maps, struct map *map); | 113 | void maps__remove(struct rb_root *maps, struct map *map); |
114 | struct map *maps__find(struct rb_root *maps, u64 addr); | 114 | struct map *maps__find(struct rb_root *maps, u64 addr); |
115 | struct map *maps__first(struct rb_root *maps); | ||
116 | struct map *maps__next(struct map *map); | ||
115 | void map_groups__init(struct map_groups *mg); | 117 | void map_groups__init(struct map_groups *mg); |
116 | void map_groups__exit(struct map_groups *mg); | 118 | void map_groups__exit(struct map_groups *mg); |
117 | int map_groups__clone(struct map_groups *mg, | 119 | int map_groups__clone(struct map_groups *mg, |
@@ -139,6 +141,17 @@ static inline struct map *map_groups__find(struct map_groups *mg, | |||
139 | return maps__find(&mg->maps[type], addr); | 141 | return maps__find(&mg->maps[type], addr); |
140 | } | 142 | } |
141 | 143 | ||
144 | static inline struct map *map_groups__first(struct map_groups *mg, | ||
145 | enum map_type type) | ||
146 | { | ||
147 | return maps__first(&mg->maps[type]); | ||
148 | } | ||
149 | |||
150 | static inline struct map *map_groups__next(struct map *map) | ||
151 | { | ||
152 | return maps__next(map); | ||
153 | } | ||
154 | |||
142 | struct symbol *map_groups__find_symbol(struct map_groups *mg, | 155 | struct symbol *map_groups__find_symbol(struct map_groups *mg, |
143 | enum map_type type, u64 addr, | 156 | enum map_type type, u64 addr, |
144 | struct map **mapp, | 157 | struct map **mapp, |
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 3eaa7b486e2e..a7b9ab557380 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -951,6 +951,57 @@ out_elf_end: | |||
951 | return err; | 951 | return err; |
952 | } | 952 | } |
953 | 953 | ||
954 | static int elf_read_maps(Elf *elf, bool exe, mapfn_t mapfn, void *data) | ||
955 | { | ||
956 | GElf_Phdr phdr; | ||
957 | size_t i, phdrnum; | ||
958 | int err; | ||
959 | u64 sz; | ||
960 | |||
961 | if (elf_getphdrnum(elf, &phdrnum)) | ||
962 | return -1; | ||
963 | |||
964 | for (i = 0; i < phdrnum; i++) { | ||
965 | if (gelf_getphdr(elf, i, &phdr) == NULL) | ||
966 | return -1; | ||
967 | if (phdr.p_type != PT_LOAD) | ||
968 | continue; | ||
969 | if (exe) { | ||
970 | if (!(phdr.p_flags & PF_X)) | ||
971 | continue; | ||
972 | } else { | ||
973 | if (!(phdr.p_flags & PF_R)) | ||
974 | continue; | ||
975 | } | ||
976 | sz = min(phdr.p_memsz, phdr.p_filesz); | ||
977 | if (!sz) | ||
978 | continue; | ||
979 | err = mapfn(phdr.p_vaddr, sz, phdr.p_offset, data); | ||
980 | if (err) | ||
981 | return err; | ||
982 | } | ||
983 | return 0; | ||
984 | } | ||
985 | |||
986 | int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, | ||
987 | bool *is_64_bit) | ||
988 | { | ||
989 | int err; | ||
990 | Elf *elf; | ||
991 | |||
992 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | ||
993 | if (elf == NULL) | ||
994 | return -1; | ||
995 | |||
996 | if (is_64_bit) | ||
997 | *is_64_bit = (gelf_getclass(elf) == ELFCLASS64); | ||
998 | |||
999 | err = elf_read_maps(elf, exe, mapfn, data); | ||
1000 | |||
1001 | elf_end(elf); | ||
1002 | return err; | ||
1003 | } | ||
1004 | |||
954 | void symbol__elf_init(void) | 1005 | void symbol__elf_init(void) |
955 | { | 1006 | { |
956 | elf_version(EV_CURRENT); | 1007 | elf_version(EV_CURRENT); |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index a7390cde63bc..3a802c300fc5 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -301,6 +301,13 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, | |||
301 | return 0; | 301 | return 0; |
302 | } | 302 | } |
303 | 303 | ||
304 | int file__read_maps(int fd __maybe_unused, bool exe __maybe_unused, | ||
305 | mapfn_t mapfn __maybe_unused, void *data __maybe_unused, | ||
306 | bool *is_64_bit __maybe_unused) | ||
307 | { | ||
308 | return -1; | ||
309 | } | ||
310 | |||
304 | void symbol__elf_init(void) | 311 | void symbol__elf_init(void) |
305 | { | 312 | { |
306 | } | 313 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index b9056a8c1620..77f3b95bb46d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -327,6 +327,16 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) | |||
327 | return NULL; | 327 | return NULL; |
328 | } | 328 | } |
329 | 329 | ||
330 | static struct symbol *symbols__first(struct rb_root *symbols) | ||
331 | { | ||
332 | struct rb_node *n = rb_first(symbols); | ||
333 | |||
334 | if (n) | ||
335 | return rb_entry(n, struct symbol, rb_node); | ||
336 | |||
337 | return NULL; | ||
338 | } | ||
339 | |||
330 | struct symbol_name_rb_node { | 340 | struct symbol_name_rb_node { |
331 | struct rb_node rb_node; | 341 | struct rb_node rb_node; |
332 | struct symbol sym; | 342 | struct symbol sym; |
@@ -397,6 +407,11 @@ struct symbol *dso__find_symbol(struct dso *dso, | |||
397 | return symbols__find(&dso->symbols[type], addr); | 407 | return symbols__find(&dso->symbols[type], addr); |
398 | } | 408 | } |
399 | 409 | ||
410 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type) | ||
411 | { | ||
412 | return symbols__first(&dso->symbols[type]); | ||
413 | } | ||
414 | |||
400 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 415 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
401 | const char *name) | 416 | const char *name) |
402 | { | 417 | { |
@@ -533,6 +548,53 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename, | |||
533 | return kallsyms__parse(filename, &args, map__process_kallsym_symbol); | 548 | return kallsyms__parse(filename, &args, map__process_kallsym_symbol); |
534 | } | 549 | } |
535 | 550 | ||
551 | static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | ||
552 | symbol_filter_t filter) | ||
553 | { | ||
554 | struct map_groups *kmaps = map__kmap(map)->kmaps; | ||
555 | struct map *curr_map; | ||
556 | struct symbol *pos; | ||
557 | int count = 0, moved = 0; | ||
558 | struct rb_root *root = &dso->symbols[map->type]; | ||
559 | struct rb_node *next = rb_first(root); | ||
560 | |||
561 | while (next) { | ||
562 | char *module; | ||
563 | |||
564 | pos = rb_entry(next, struct symbol, rb_node); | ||
565 | next = rb_next(&pos->rb_node); | ||
566 | |||
567 | module = strchr(pos->name, '\t'); | ||
568 | if (module) | ||
569 | *module = '\0'; | ||
570 | |||
571 | curr_map = map_groups__find(kmaps, map->type, pos->start); | ||
572 | |||
573 | if (!curr_map || (filter && filter(curr_map, pos))) { | ||
574 | rb_erase(&pos->rb_node, root); | ||
575 | symbol__delete(pos); | ||
576 | } else { | ||
577 | pos->start -= curr_map->start - curr_map->pgoff; | ||
578 | if (pos->end) | ||
579 | pos->end -= curr_map->start - curr_map->pgoff; | ||
580 | if (curr_map != map) { | ||
581 | rb_erase(&pos->rb_node, root); | ||
582 | symbols__insert( | ||
583 | &curr_map->dso->symbols[curr_map->type], | ||
584 | pos); | ||
585 | ++moved; | ||
586 | } else { | ||
587 | ++count; | ||
588 | } | ||
589 | } | ||
590 | } | ||
591 | |||
592 | /* Symbols have been adjusted */ | ||
593 | dso->adjust_symbols = 1; | ||
594 | |||
595 | return count + moved; | ||
596 | } | ||
597 | |||
536 | /* | 598 | /* |
537 | * Split the symbols into maps, making sure there are no overlaps, i.e. the | 599 | * Split the symbols into maps, making sure there are no overlaps, i.e. the |
538 | * kernel range is broken in several maps, named [kernel].N, as we don't have | 600 | * kernel range is broken in several maps, named [kernel].N, as we don't have |
@@ -674,6 +736,161 @@ bool symbol__restricted_filename(const char *filename, | |||
674 | return restricted; | 736 | return restricted; |
675 | } | 737 | } |
676 | 738 | ||
739 | struct kcore_mapfn_data { | ||
740 | struct dso *dso; | ||
741 | enum map_type type; | ||
742 | struct list_head maps; | ||
743 | }; | ||
744 | |||
745 | static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) | ||
746 | { | ||
747 | struct kcore_mapfn_data *md = data; | ||
748 | struct map *map; | ||
749 | |||
750 | map = map__new2(start, md->dso, md->type); | ||
751 | if (map == NULL) | ||
752 | return -ENOMEM; | ||
753 | |||
754 | map->end = map->start + len; | ||
755 | map->pgoff = pgoff; | ||
756 | |||
757 | list_add(&map->node, &md->maps); | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | /* | ||
763 | * If kallsyms is referenced by name then we look for kcore in the same | ||
764 | * directory. | ||
765 | */ | ||
766 | static bool kcore_filename_from_kallsyms_filename(char *kcore_filename, | ||
767 | const char *kallsyms_filename) | ||
768 | { | ||
769 | char *name; | ||
770 | |||
771 | strcpy(kcore_filename, kallsyms_filename); | ||
772 | name = strrchr(kcore_filename, '/'); | ||
773 | if (!name) | ||
774 | return false; | ||
775 | |||
776 | if (!strcmp(name, "/kallsyms")) { | ||
777 | strcpy(name, "/kcore"); | ||
778 | return true; | ||
779 | } | ||
780 | |||
781 | return false; | ||
782 | } | ||
783 | |||
784 | static int dso__load_kcore(struct dso *dso, struct map *map, | ||
785 | const char *kallsyms_filename) | ||
786 | { | ||
787 | struct map_groups *kmaps = map__kmap(map)->kmaps; | ||
788 | struct machine *machine = kmaps->machine; | ||
789 | struct kcore_mapfn_data md; | ||
790 | struct map *old_map, *new_map, *replacement_map = NULL; | ||
791 | bool is_64_bit; | ||
792 | int err, fd; | ||
793 | char kcore_filename[PATH_MAX]; | ||
794 | struct symbol *sym; | ||
795 | |||
796 | /* This function requires that the map is the kernel map */ | ||
797 | if (map != machine->vmlinux_maps[map->type]) | ||
798 | return -EINVAL; | ||
799 | |||
800 | if (!kcore_filename_from_kallsyms_filename(kcore_filename, | ||
801 | kallsyms_filename)) | ||
802 | return -EINVAL; | ||
803 | |||
804 | md.dso = dso; | ||
805 | md.type = map->type; | ||
806 | INIT_LIST_HEAD(&md.maps); | ||
807 | |||
808 | fd = open(kcore_filename, O_RDONLY); | ||
809 | if (fd < 0) | ||
810 | return -EINVAL; | ||
811 | |||
812 | /* Read new maps into temporary lists */ | ||
813 | err = file__read_maps(fd, md.type == MAP__FUNCTION, kcore_mapfn, &md, | ||
814 | &is_64_bit); | ||
815 | if (err) | ||
816 | goto out_err; | ||
817 | |||
818 | if (list_empty(&md.maps)) { | ||
819 | err = -EINVAL; | ||
820 | goto out_err; | ||
821 | } | ||
822 | |||
823 | /* Remove old maps */ | ||
824 | old_map = map_groups__first(kmaps, map->type); | ||
825 | while (old_map) { | ||
826 | struct map *next = map_groups__next(old_map); | ||
827 | |||
828 | if (old_map != map) | ||
829 | map_groups__remove(kmaps, old_map); | ||
830 | old_map = next; | ||
831 | } | ||
832 | |||
833 | /* Find the kernel map using the first symbol */ | ||
834 | sym = dso__first_symbol(dso, map->type); | ||
835 | list_for_each_entry(new_map, &md.maps, node) { | ||
836 | if (sym && sym->start >= new_map->start && | ||
837 | sym->start < new_map->end) { | ||
838 | replacement_map = new_map; | ||
839 | break; | ||
840 | } | ||
841 | } | ||
842 | |||
843 | if (!replacement_map) | ||
844 | replacement_map = list_entry(md.maps.next, struct map, node); | ||
845 | |||
846 | /* Add new maps */ | ||
847 | while (!list_empty(&md.maps)) { | ||
848 | new_map = list_entry(md.maps.next, struct map, node); | ||
849 | list_del(&new_map->node); | ||
850 | if (new_map == replacement_map) { | ||
851 | map->start = new_map->start; | ||
852 | map->end = new_map->end; | ||
853 | map->pgoff = new_map->pgoff; | ||
854 | map->map_ip = new_map->map_ip; | ||
855 | map->unmap_ip = new_map->unmap_ip; | ||
856 | map__delete(new_map); | ||
857 | /* Ensure maps are correctly ordered */ | ||
858 | map_groups__remove(kmaps, map); | ||
859 | map_groups__insert(kmaps, map); | ||
860 | } else { | ||
861 | map_groups__insert(kmaps, new_map); | ||
862 | } | ||
863 | } | ||
864 | |||
865 | /* | ||
866 | * Set the data type and long name so that kcore can be read via | ||
867 | * dso__data_read_addr(). | ||
868 | */ | ||
869 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | ||
870 | dso->data_type = DSO_BINARY_TYPE__GUEST_KCORE; | ||
871 | else | ||
872 | dso->data_type = DSO_BINARY_TYPE__KCORE; | ||
873 | dso__set_long_name(dso, strdup(kcore_filename)); | ||
874 | |||
875 | close(fd); | ||
876 | |||
877 | if (map->type == MAP__FUNCTION) | ||
878 | pr_debug("Using %s for kernel object code\n", kcore_filename); | ||
879 | else | ||
880 | pr_debug("Using %s for kernel data\n", kcore_filename); | ||
881 | |||
882 | return 0; | ||
883 | |||
884 | out_err: | ||
885 | while (!list_empty(&md.maps)) { | ||
886 | map = list_entry(md.maps.next, struct map, node); | ||
887 | list_del(&map->node); | ||
888 | map__delete(map); | ||
889 | } | ||
890 | close(fd); | ||
891 | return -EINVAL; | ||
892 | } | ||
893 | |||
677 | int dso__load_kallsyms(struct dso *dso, const char *filename, | 894 | int dso__load_kallsyms(struct dso *dso, const char *filename, |
678 | struct map *map, symbol_filter_t filter) | 895 | struct map *map, symbol_filter_t filter) |
679 | { | 896 | { |
@@ -691,7 +908,10 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, | |||
691 | else | 908 | else |
692 | dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; | 909 | dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; |
693 | 910 | ||
694 | return dso__split_kallsyms(dso, map, filter); | 911 | if (!dso__load_kcore(dso, map, filename)) |
912 | return dso__split_kallsyms_for_kcore(dso, map, filter); | ||
913 | else | ||
914 | return dso__split_kallsyms(dso, map, filter); | ||
695 | } | 915 | } |
696 | 916 | ||
697 | static int dso__load_perf_map(struct dso *dso, struct map *map, | 917 | static int dso__load_perf_map(struct dso *dso, struct map *map, |
@@ -1065,7 +1285,7 @@ do_kallsyms: | |||
1065 | pr_debug("Using %s for symbols\n", kallsyms_filename); | 1285 | pr_debug("Using %s for symbols\n", kallsyms_filename); |
1066 | free(kallsyms_allocated_filename); | 1286 | free(kallsyms_allocated_filename); |
1067 | 1287 | ||
1068 | if (err > 0) { | 1288 | if (err > 0 && !dso__is_kcore(dso)) { |
1069 | dso__set_long_name(dso, strdup("[kernel.kallsyms]")); | 1289 | dso__set_long_name(dso, strdup("[kernel.kallsyms]")); |
1070 | map__fixup_start(map); | 1290 | map__fixup_start(map); |
1071 | map__fixup_end(map); | 1291 | map__fixup_end(map); |
@@ -1109,8 +1329,9 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, | |||
1109 | } | 1329 | } |
1110 | 1330 | ||
1111 | err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); | 1331 | err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); |
1112 | if (err > 0) { | 1332 | if (err > 0) |
1113 | pr_debug("Using %s for symbols\n", kallsyms_filename); | 1333 | pr_debug("Using %s for symbols\n", kallsyms_filename); |
1334 | if (err > 0 && !dso__is_kcore(dso)) { | ||
1114 | machine__mmap_name(machine, path, sizeof(path)); | 1335 | machine__mmap_name(machine, path, sizeof(path)); |
1115 | dso__set_long_name(dso, strdup(path)); | 1336 | dso__set_long_name(dso, strdup(path)); |
1116 | map__fixup_start(map); | 1337 | map__fixup_start(map); |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 5f720dc076da..fd5b70ea2981 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -215,6 +215,7 @@ struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, | |||
215 | u64 addr); | 215 | u64 addr); |
216 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, | 216 | struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, |
217 | const char *name); | 217 | const char *name); |
218 | struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); | ||
218 | 219 | ||
219 | int filename__read_build_id(const char *filename, void *bf, size_t size); | 220 | int filename__read_build_id(const char *filename, void *bf, size_t size); |
220 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); | 221 | int sysfs__read_build_id(const char *filename, void *bf, size_t size); |
@@ -247,4 +248,8 @@ void symbols__fixup_duplicate(struct rb_root *symbols); | |||
247 | void symbols__fixup_end(struct rb_root *symbols); | 248 | void symbols__fixup_end(struct rb_root *symbols); |
248 | void __map_groups__fixup_end(struct map_groups *mg, enum map_type type); | 249 | void __map_groups__fixup_end(struct map_groups *mg, enum map_type type); |
249 | 250 | ||
251 | typedef int (*mapfn_t)(u64 start, u64 len, u64 pgoff, void *data); | ||
252 | int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data, | ||
253 | bool *is_64_bit); | ||
254 | |||
250 | #endif /* __PERF_SYMBOL */ | 255 | #endif /* __PERF_SYMBOL */ |