diff options
author | Wang Nan <wangnan0@huawei.com> | 2015-04-07 04:22:45 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2015-04-08 08:07:03 -0400 |
commit | ba92732e9808df679ddf75c5ea1c0caae6d7dce2 (patch) | |
tree | f00303efe3ed8cd3f2c5508d8af87db9b0137a82 /tools/perf | |
parent | 8ea92ceb748535799e3e9f35afb85bdc23bf6d7c (diff) |
perf kmaps: Check kmaps to make code more robust
This patch add checks in places where map__kmap is used to get kmaps
from struct kmap.
Error messages are added at map__kmap to warn invalid accessing of kmap
(for the case of !map->dso->kernel, kmap(map) does not exists at all).
Also, introduces map__kmaps() to warn uninitialized kmaps.
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: pi3orama@163.com
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/1428394966-131044-2-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r-- | tools/perf/util/machine.c | 5 | ||||
-rw-r--r-- | tools/perf/util/map.c | 20 | ||||
-rw-r--r-- | tools/perf/util/map.h | 6 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 2 | ||||
-rw-r--r-- | tools/perf/util/session.c | 3 | ||||
-rw-r--r-- | tools/perf/util/symbol-elf.c | 16 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 34 |
7 files changed, 70 insertions, 16 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index e45c8f33a8fd..9c380a2caa54 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -679,6 +679,9 @@ int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | |||
679 | machine->vmlinux_maps[type]->unmap_ip = | 679 | machine->vmlinux_maps[type]->unmap_ip = |
680 | identity__map_ip; | 680 | identity__map_ip; |
681 | kmap = map__kmap(machine->vmlinux_maps[type]); | 681 | kmap = map__kmap(machine->vmlinux_maps[type]); |
682 | if (!kmap) | ||
683 | return -1; | ||
684 | |||
682 | kmap->kmaps = &machine->kmaps; | 685 | kmap->kmaps = &machine->kmaps; |
683 | map_groups__insert(&machine->kmaps, | 686 | map_groups__insert(&machine->kmaps, |
684 | machine->vmlinux_maps[type]); | 687 | machine->vmlinux_maps[type]); |
@@ -700,7 +703,7 @@ void machine__destroy_kernel_maps(struct machine *machine) | |||
700 | kmap = map__kmap(machine->vmlinux_maps[type]); | 703 | kmap = map__kmap(machine->vmlinux_maps[type]); |
701 | map_groups__remove(&machine->kmaps, | 704 | map_groups__remove(&machine->kmaps, |
702 | machine->vmlinux_maps[type]); | 705 | machine->vmlinux_maps[type]); |
703 | if (kmap->ref_reloc_sym) { | 706 | if (kmap && kmap->ref_reloc_sym) { |
704 | /* | 707 | /* |
705 | * ref_reloc_sym is shared among all maps, so free just | 708 | * ref_reloc_sym is shared among all maps, so free just |
706 | * on one of them. | 709 | * on one of them. |
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 62ca9f2607d5..a14f08f41686 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c | |||
@@ -778,3 +778,23 @@ struct map *maps__next(struct map *map) | |||
778 | return rb_entry(next, struct map, rb_node); | 778 | return rb_entry(next, struct map, rb_node); |
779 | return NULL; | 779 | return NULL; |
780 | } | 780 | } |
781 | |||
782 | struct kmap *map__kmap(struct map *map) | ||
783 | { | ||
784 | if (!map->dso || !map->dso->kernel) { | ||
785 | pr_err("Internal error: map__kmap with a non-kernel map\n"); | ||
786 | return NULL; | ||
787 | } | ||
788 | return (struct kmap *)(map + 1); | ||
789 | } | ||
790 | |||
791 | struct map_groups *map__kmaps(struct map *map) | ||
792 | { | ||
793 | struct kmap *kmap = map__kmap(map); | ||
794 | |||
795 | if (!kmap || !kmap->kmaps) { | ||
796 | pr_err("Internal error: map__kmaps with a non-kernel map\n"); | ||
797 | return NULL; | ||
798 | } | ||
799 | return kmap->kmaps; | ||
800 | } | ||
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h index 0e42438b1e59..ec19c59ca38e 100644 --- a/tools/perf/util/map.h +++ b/tools/perf/util/map.h | |||
@@ -76,10 +76,8 @@ static inline struct map_groups *map_groups__get(struct map_groups *mg) | |||
76 | 76 | ||
77 | void map_groups__put(struct map_groups *mg); | 77 | void map_groups__put(struct map_groups *mg); |
78 | 78 | ||
79 | static inline struct kmap *map__kmap(struct map *map) | 79 | struct kmap *map__kmap(struct map *map); |
80 | { | 80 | struct map_groups *map__kmaps(struct map *map); |
81 | return (struct kmap *)(map + 1); | ||
82 | } | ||
83 | 81 | ||
84 | static inline u64 map__map_ip(struct map *map, u64 ip) | 82 | static inline u64 map__map_ip(struct map *map, u64 ip) |
85 | { | 83 | { |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 8feac0774c41..4fd49f021073 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -135,6 +135,8 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | |||
135 | return NULL; | 135 | return NULL; |
136 | 136 | ||
137 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); | 137 | kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]); |
138 | if (!kmap) | ||
139 | return NULL; | ||
138 | return kmap->ref_reloc_sym; | 140 | return kmap->ref_reloc_sym; |
139 | } | 141 | } |
140 | 142 | ||
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index dfacf1d50162..0c74012575ac 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -1466,6 +1466,9 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps, | |||
1466 | 1466 | ||
1467 | for (i = 0; i < MAP__NR_TYPES; ++i) { | 1467 | for (i = 0; i < MAP__NR_TYPES; ++i) { |
1468 | struct kmap *kmap = map__kmap(maps[i]); | 1468 | struct kmap *kmap = map__kmap(maps[i]); |
1469 | |||
1470 | if (!kmap) | ||
1471 | continue; | ||
1469 | kmap->ref_reloc_sym = ref; | 1472 | kmap->ref_reloc_sym = ref; |
1470 | } | 1473 | } |
1471 | 1474 | ||
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 476268c99431..a7ab6063e038 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -776,6 +776,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
776 | symbol_filter_t filter, int kmodule) | 776 | symbol_filter_t filter, int kmodule) |
777 | { | 777 | { |
778 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; | 778 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; |
779 | struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; | ||
779 | struct map *curr_map = map; | 780 | struct map *curr_map = map; |
780 | struct dso *curr_dso = dso; | 781 | struct dso *curr_dso = dso; |
781 | Elf_Data *symstrs, *secstrs; | 782 | Elf_Data *symstrs, *secstrs; |
@@ -791,6 +792,9 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
791 | int nr = 0; | 792 | int nr = 0; |
792 | bool remap_kernel = false, adjust_kernel_syms = false; | 793 | bool remap_kernel = false, adjust_kernel_syms = false; |
793 | 794 | ||
795 | if (kmap && !kmaps) | ||
796 | return -1; | ||
797 | |||
794 | dso->symtab_type = syms_ss->type; | 798 | dso->symtab_type = syms_ss->type; |
795 | dso->is_64_bit = syms_ss->is_64_bit; | 799 | dso->is_64_bit = syms_ss->is_64_bit; |
796 | dso->rel = syms_ss->ehdr.e_type == ET_REL; | 800 | dso->rel = syms_ss->ehdr.e_type == ET_REL; |
@@ -958,8 +962,10 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
958 | map->map_ip = map__map_ip; | 962 | map->map_ip = map__map_ip; |
959 | map->unmap_ip = map__unmap_ip; | 963 | map->unmap_ip = map__unmap_ip; |
960 | /* Ensure maps are correctly ordered */ | 964 | /* Ensure maps are correctly ordered */ |
961 | map_groups__remove(kmap->kmaps, map); | 965 | if (kmaps) { |
962 | map_groups__insert(kmap->kmaps, map); | 966 | map_groups__remove(kmaps, map); |
967 | map_groups__insert(kmaps, map); | ||
968 | } | ||
963 | } | 969 | } |
964 | 970 | ||
965 | /* | 971 | /* |
@@ -983,7 +989,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
983 | snprintf(dso_name, sizeof(dso_name), | 989 | snprintf(dso_name, sizeof(dso_name), |
984 | "%s%s", dso->short_name, section_name); | 990 | "%s%s", dso->short_name, section_name); |
985 | 991 | ||
986 | curr_map = map_groups__find_by_name(kmap->kmaps, map->type, dso_name); | 992 | curr_map = map_groups__find_by_name(kmaps, map->type, dso_name); |
987 | if (curr_map == NULL) { | 993 | if (curr_map == NULL) { |
988 | u64 start = sym.st_value; | 994 | u64 start = sym.st_value; |
989 | 995 | ||
@@ -1013,7 +1019,7 @@ int dso__load_sym(struct dso *dso, struct map *map, | |||
1013 | curr_map->unmap_ip = identity__map_ip; | 1019 | curr_map->unmap_ip = identity__map_ip; |
1014 | } | 1020 | } |
1015 | curr_dso->symtab_type = dso->symtab_type; | 1021 | curr_dso->symtab_type = dso->symtab_type; |
1016 | map_groups__insert(kmap->kmaps, curr_map); | 1022 | map_groups__insert(kmaps, curr_map); |
1017 | /* | 1023 | /* |
1018 | * The new DSO should go to the kernel DSOS | 1024 | * The new DSO should go to the kernel DSOS |
1019 | */ | 1025 | */ |
@@ -1075,7 +1081,7 @@ new_symbol: | |||
1075 | * We need to fixup this here too because we create new | 1081 | * We need to fixup this here too because we create new |
1076 | * maps here, for things like vsyscall sections. | 1082 | * maps here, for things like vsyscall sections. |
1077 | */ | 1083 | */ |
1078 | __map_groups__fixup_end(kmap->kmaps, map->type); | 1084 | __map_groups__fixup_end(kmaps, map->type); |
1079 | } | 1085 | } |
1080 | } | 1086 | } |
1081 | err = nr; | 1087 | err = nr; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fddeb9073039..201f6c4ca738 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -630,13 +630,16 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename, | |||
630 | static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | 630 | static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, |
631 | symbol_filter_t filter) | 631 | symbol_filter_t filter) |
632 | { | 632 | { |
633 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 633 | struct map_groups *kmaps = map__kmaps(map); |
634 | struct map *curr_map; | 634 | struct map *curr_map; |
635 | struct symbol *pos; | 635 | struct symbol *pos; |
636 | int count = 0, moved = 0; | 636 | int count = 0, moved = 0; |
637 | struct rb_root *root = &dso->symbols[map->type]; | 637 | struct rb_root *root = &dso->symbols[map->type]; |
638 | struct rb_node *next = rb_first(root); | 638 | struct rb_node *next = rb_first(root); |
639 | 639 | ||
640 | if (!kmaps) | ||
641 | return -1; | ||
642 | |||
640 | while (next) { | 643 | while (next) { |
641 | char *module; | 644 | char *module; |
642 | 645 | ||
@@ -682,8 +685,8 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, | |||
682 | static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, | 685 | static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, |
683 | symbol_filter_t filter) | 686 | symbol_filter_t filter) |
684 | { | 687 | { |
685 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 688 | struct map_groups *kmaps = map__kmaps(map); |
686 | struct machine *machine = kmaps->machine; | 689 | struct machine *machine; |
687 | struct map *curr_map = map; | 690 | struct map *curr_map = map; |
688 | struct symbol *pos; | 691 | struct symbol *pos; |
689 | int count = 0, moved = 0; | 692 | int count = 0, moved = 0; |
@@ -691,6 +694,11 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, | |||
691 | struct rb_node *next = rb_first(root); | 694 | struct rb_node *next = rb_first(root); |
692 | int kernel_range = 0; | 695 | int kernel_range = 0; |
693 | 696 | ||
697 | if (!kmaps) | ||
698 | return -1; | ||
699 | |||
700 | machine = kmaps->machine; | ||
701 | |||
694 | while (next) { | 702 | while (next) { |
695 | char *module; | 703 | char *module; |
696 | 704 | ||
@@ -1025,9 +1033,12 @@ static bool filename_from_kallsyms_filename(char *filename, | |||
1025 | static int validate_kcore_modules(const char *kallsyms_filename, | 1033 | static int validate_kcore_modules(const char *kallsyms_filename, |
1026 | struct map *map) | 1034 | struct map *map) |
1027 | { | 1035 | { |
1028 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 1036 | struct map_groups *kmaps = map__kmaps(map); |
1029 | char modules_filename[PATH_MAX]; | 1037 | char modules_filename[PATH_MAX]; |
1030 | 1038 | ||
1039 | if (!kmaps) | ||
1040 | return -EINVAL; | ||
1041 | |||
1031 | if (!filename_from_kallsyms_filename(modules_filename, "modules", | 1042 | if (!filename_from_kallsyms_filename(modules_filename, "modules", |
1032 | kallsyms_filename)) | 1043 | kallsyms_filename)) |
1033 | return -EINVAL; | 1044 | return -EINVAL; |
@@ -1043,6 +1054,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename, | |||
1043 | { | 1054 | { |
1044 | struct kmap *kmap = map__kmap(map); | 1055 | struct kmap *kmap = map__kmap(map); |
1045 | 1056 | ||
1057 | if (!kmap) | ||
1058 | return -EINVAL; | ||
1059 | |||
1046 | if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { | 1060 | if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { |
1047 | u64 start; | 1061 | u64 start; |
1048 | 1062 | ||
@@ -1081,8 +1095,8 @@ static int kcore_mapfn(u64 start, u64 len, u64 pgoff, void *data) | |||
1081 | static int dso__load_kcore(struct dso *dso, struct map *map, | 1095 | static int dso__load_kcore(struct dso *dso, struct map *map, |
1082 | const char *kallsyms_filename) | 1096 | const char *kallsyms_filename) |
1083 | { | 1097 | { |
1084 | struct map_groups *kmaps = map__kmap(map)->kmaps; | 1098 | struct map_groups *kmaps = map__kmaps(map); |
1085 | struct machine *machine = kmaps->machine; | 1099 | struct machine *machine; |
1086 | struct kcore_mapfn_data md; | 1100 | struct kcore_mapfn_data md; |
1087 | struct map *old_map, *new_map, *replacement_map = NULL; | 1101 | struct map *old_map, *new_map, *replacement_map = NULL; |
1088 | bool is_64_bit; | 1102 | bool is_64_bit; |
@@ -1090,6 +1104,11 @@ static int dso__load_kcore(struct dso *dso, struct map *map, | |||
1090 | char kcore_filename[PATH_MAX]; | 1104 | char kcore_filename[PATH_MAX]; |
1091 | struct symbol *sym; | 1105 | struct symbol *sym; |
1092 | 1106 | ||
1107 | if (!kmaps) | ||
1108 | return -EINVAL; | ||
1109 | |||
1110 | machine = kmaps->machine; | ||
1111 | |||
1093 | /* This function requires that the map is the kernel map */ | 1112 | /* This function requires that the map is the kernel map */ |
1094 | if (map != machine->vmlinux_maps[map->type]) | 1113 | if (map != machine->vmlinux_maps[map->type]) |
1095 | return -EINVAL; | 1114 | return -EINVAL; |
@@ -1202,6 +1221,9 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) | |||
1202 | struct kmap *kmap = map__kmap(map); | 1221 | struct kmap *kmap = map__kmap(map); |
1203 | u64 addr; | 1222 | u64 addr; |
1204 | 1223 | ||
1224 | if (!kmap) | ||
1225 | return -1; | ||
1226 | |||
1205 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) | 1227 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) |
1206 | return 0; | 1228 | return 0; |
1207 | 1229 | ||