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/util | |
| 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/util')
| -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 | ||
