diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-04-27 20:21:09 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2017-05-02 17:23:04 -0400 |
commit | b843f62ad942f3879c2d7acd27b44f931c609685 (patch) | |
tree | 5367408cae8262e00b559250bbfc6f8f222f5c38 /tools | |
parent | 96395cbbc7e94cbbe4f76cf64cf122fabc19123d (diff) |
perf symbols: Accept symbols starting at address 0
That is the case of _text on s390, and we have some functions that return an
address, using address zero to report problems, oops.
This would lead the symbol loading routines to not use "_text" as the reference
relocation symbol, or the first symbol for the kernel, but use instead
"_stext", that is at the same address on x86_64 and others, but not on s390:
[acme@localhost perf-4.11.0-rc6]$ head -15 /proc/kallsyms
0000000000000000 T _text
0000000000000418 t iplstart
0000000000000800 T start
000000000000080a t .base
000000000000082e t .sk8x8
0000000000000834 t .gotr
0000000000000842 t .cmd
0000000000000846 t .parm
000000000000084a t .lowcase
0000000000010000 T startup
0000000000010010 T startup_kdump
0000000000010214 t startup_kdump_relocated
0000000000011000 T startup_continue
00000000000112a0 T _ehead
0000000000100000 T _stext
[acme@localhost perf-4.11.0-rc6]$
Which in turn would make 'perf test vmlinux' to fail because it wouldn't find
the symbols before "_stext" in kallsyms.
Fix it by using the return value only for errors and storing the
address, when the symbol is successfully found, in a provided pointer
arg.
Before this patch:
After:
[acme@localhost perf-4.11.0-rc6]$ tools/perf/perf test -v 1
1: vmlinux symtab matches kallsyms :
--- start ---
test child forked, pid 40693
Looking at the vmlinux_path (8 entries long)
Using /usr/lib/debug/lib/modules/3.10.0-654.el7.s390x/vmlinux for symbols
ERR : 0: _text not on kallsyms
ERR : 0x418: iplstart not on kallsyms
ERR : 0x800: start not on kallsyms
ERR : 0x80a: .base not on kallsyms
ERR : 0x82e: .sk8x8 not on kallsyms
ERR : 0x834: .gotr not on kallsyms
ERR : 0x842: .cmd not on kallsyms
ERR : 0x846: .parm not on kallsyms
ERR : 0x84a: .lowcase not on kallsyms
ERR : 0x10000: startup not on kallsyms
ERR : 0x10010: startup_kdump not on kallsyms
ERR : 0x10214: startup_kdump_relocated not on kallsyms
ERR : 0x11000: startup_continue not on kallsyms
ERR : 0x112a0: _ehead not on kallsyms
<SNIP warnings>
test child finished with -1
---- end ----
vmlinux symtab matches kallsyms: FAILED!
[acme@localhost perf-4.11.0-rc6]$
After:
[acme@localhost perf-4.11.0-rc6]$ tools/perf/perf test -v 1
1: vmlinux symtab matches kallsyms :
--- start ---
test child forked, pid 47160
<SNIP warnings>
test child finished with 0
---- end ----
vmlinux symtab matches kallsyms: Ok
[acme@localhost perf-4.11.0-rc6]$
Reported-by: Michael Petlan <mpetlan@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/n/tip-9x9bwgd3btwdk1u51xie93fz@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-buildid-cache.c | 13 | ||||
-rw-r--r-- | tools/perf/util/event.c | 9 | ||||
-rw-r--r-- | tools/perf/util/event.h | 4 | ||||
-rw-r--r-- | tools/perf/util/machine.c | 28 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 11 |
5 files changed, 37 insertions, 28 deletions
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c index 64b44e81c771..9eba7f1add1f 100644 --- a/tools/perf/builtin-buildid-cache.c +++ b/tools/perf/builtin-buildid-cache.c | |||
@@ -49,19 +49,22 @@ static bool same_kallsyms_reloc(const char *from_dir, char *to_dir) | |||
49 | char to[PATH_MAX]; | 49 | char to[PATH_MAX]; |
50 | const char *name; | 50 | const char *name; |
51 | u64 addr1 = 0, addr2 = 0; | 51 | u64 addr1 = 0, addr2 = 0; |
52 | int i; | 52 | int i, err = -1; |
53 | 53 | ||
54 | scnprintf(from, sizeof(from), "%s/kallsyms", from_dir); | 54 | scnprintf(from, sizeof(from), "%s/kallsyms", from_dir); |
55 | scnprintf(to, sizeof(to), "%s/kallsyms", to_dir); | 55 | scnprintf(to, sizeof(to), "%s/kallsyms", to_dir); |
56 | 56 | ||
57 | for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { | 57 | for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { |
58 | addr1 = kallsyms__get_function_start(from, name); | 58 | err = kallsyms__get_function_start(from, name, &addr1); |
59 | if (addr1) | 59 | if (!err) |
60 | break; | 60 | break; |
61 | } | 61 | } |
62 | 62 | ||
63 | if (name) | 63 | if (err) |
64 | addr2 = kallsyms__get_function_start(to, name); | 64 | return false; |
65 | |||
66 | if (kallsyms__get_function_start(to, name, &addr2)) | ||
67 | return false; | ||
65 | 68 | ||
66 | return addr1 == addr2; | 69 | return addr1 == addr2; |
67 | } | 70 | } |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 437194fe0434..dc5c3bb69d73 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -768,15 +768,16 @@ static int find_symbol_cb(void *arg, const char *name, char type, | |||
768 | return 1; | 768 | return 1; |
769 | } | 769 | } |
770 | 770 | ||
771 | u64 kallsyms__get_function_start(const char *kallsyms_filename, | 771 | int kallsyms__get_function_start(const char *kallsyms_filename, |
772 | const char *symbol_name) | 772 | const char *symbol_name, u64 *addr) |
773 | { | 773 | { |
774 | struct process_symbol_args args = { .name = symbol_name, }; | 774 | struct process_symbol_args args = { .name = symbol_name, }; |
775 | 775 | ||
776 | if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0) | 776 | if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0) |
777 | return 0; | 777 | return -1; |
778 | 778 | ||
779 | return args.start; | 779 | *addr = args.start; |
780 | return 0; | ||
780 | } | 781 | } |
781 | 782 | ||
782 | int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | 783 | int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index cfbe32bd7413..27ac047490c3 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -675,8 +675,8 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp); | |||
675 | size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp); | 675 | size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp); |
676 | size_t perf_event__fprintf(union perf_event *event, FILE *fp); | 676 | size_t perf_event__fprintf(union perf_event *event, FILE *fp); |
677 | 677 | ||
678 | u64 kallsyms__get_function_start(const char *kallsyms_filename, | 678 | int kallsyms__get_function_start(const char *kallsyms_filename, |
679 | const char *symbol_name); | 679 | const char *symbol_name, u64 *addr); |
680 | 680 | ||
681 | void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max); | 681 | void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max); |
682 | void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, | 682 | void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, |
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 7a47f52ccfcc..d97e014c3df3 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c | |||
@@ -796,11 +796,11 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL}; | |||
796 | * Returns the name of the start symbol in *symbol_name. Pass in NULL as | 796 | * Returns the name of the start symbol in *symbol_name. Pass in NULL as |
797 | * symbol_name if it's not that important. | 797 | * symbol_name if it's not that important. |
798 | */ | 798 | */ |
799 | static u64 machine__get_running_kernel_start(struct machine *machine, | 799 | static int machine__get_running_kernel_start(struct machine *machine, |
800 | const char **symbol_name) | 800 | const char **symbol_name, u64 *start) |
801 | { | 801 | { |
802 | char filename[PATH_MAX]; | 802 | char filename[PATH_MAX]; |
803 | int i; | 803 | int i, err = -1; |
804 | const char *name; | 804 | const char *name; |
805 | u64 addr = 0; | 805 | u64 addr = 0; |
806 | 806 | ||
@@ -810,21 +810,28 @@ static u64 machine__get_running_kernel_start(struct machine *machine, | |||
810 | return 0; | 810 | return 0; |
811 | 811 | ||
812 | for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { | 812 | for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) { |
813 | addr = kallsyms__get_function_start(filename, name); | 813 | err = kallsyms__get_function_start(filename, name, &addr); |
814 | if (addr) | 814 | if (!err) |
815 | break; | 815 | break; |
816 | } | 816 | } |
817 | 817 | ||
818 | if (err) | ||
819 | return -1; | ||
820 | |||
818 | if (symbol_name) | 821 | if (symbol_name) |
819 | *symbol_name = name; | 822 | *symbol_name = name; |
820 | 823 | ||
821 | return addr; | 824 | *start = addr; |
825 | return 0; | ||
822 | } | 826 | } |
823 | 827 | ||
824 | int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) | 828 | int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) |
825 | { | 829 | { |
826 | int type; | 830 | int type; |
827 | u64 start = machine__get_running_kernel_start(machine, NULL); | 831 | u64 start = 0; |
832 | |||
833 | if (machine__get_running_kernel_start(machine, NULL, &start)) | ||
834 | return -1; | ||
828 | 835 | ||
829 | /* In case of renewal the kernel map, destroy previous one */ | 836 | /* In case of renewal the kernel map, destroy previous one */ |
830 | machine__destroy_kernel_maps(machine); | 837 | machine__destroy_kernel_maps(machine); |
@@ -1185,8 +1192,8 @@ static int machine__create_modules(struct machine *machine) | |||
1185 | int machine__create_kernel_maps(struct machine *machine) | 1192 | int machine__create_kernel_maps(struct machine *machine) |
1186 | { | 1193 | { |
1187 | struct dso *kernel = machine__get_kernel(machine); | 1194 | struct dso *kernel = machine__get_kernel(machine); |
1188 | const char *name; | 1195 | const char *name = NULL; |
1189 | u64 addr; | 1196 | u64 addr = 0; |
1190 | int ret; | 1197 | int ret; |
1191 | 1198 | ||
1192 | if (kernel == NULL) | 1199 | if (kernel == NULL) |
@@ -1211,8 +1218,7 @@ int machine__create_kernel_maps(struct machine *machine) | |||
1211 | */ | 1218 | */ |
1212 | map_groups__fixup_end(&machine->kmaps); | 1219 | map_groups__fixup_end(&machine->kmaps); |
1213 | 1220 | ||
1214 | addr = machine__get_running_kernel_start(machine, &name); | 1221 | if (machine__get_running_kernel_start(machine, &name, &addr)) { |
1215 | if (!addr) { | ||
1216 | } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { | 1222 | } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) { |
1217 | machine__destroy_kernel_maps(machine); | 1223 | machine__destroy_kernel_maps(machine); |
1218 | return -1; | 1224 | return -1; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 2cb7665e9973..b349e8eda0e2 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -466,7 +466,7 @@ void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) | |||
466 | struct symbol *dso__find_symbol(struct dso *dso, | 466 | struct symbol *dso__find_symbol(struct dso *dso, |
467 | enum map_type type, u64 addr) | 467 | enum map_type type, u64 addr) |
468 | { | 468 | { |
469 | if (dso->last_find_result[type].addr != addr) { | 469 | if (dso->last_find_result[type].addr != addr || dso->last_find_result[type].symbol == NULL) { |
470 | dso->last_find_result[type].addr = addr; | 470 | dso->last_find_result[type].addr = addr; |
471 | dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr); | 471 | dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr); |
472 | } | 472 | } |
@@ -1075,8 +1075,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename, | |||
1075 | if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { | 1075 | if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) { |
1076 | u64 start; | 1076 | u64 start; |
1077 | 1077 | ||
1078 | start = kallsyms__get_function_start(kallsyms_filename, | 1078 | if (kallsyms__get_function_start(kallsyms_filename, |
1079 | kmap->ref_reloc_sym->name); | 1079 | kmap->ref_reloc_sym->name, &start)) |
1080 | return -ENOENT; | ||
1080 | if (start != kmap->ref_reloc_sym->addr) | 1081 | if (start != kmap->ref_reloc_sym->addr) |
1081 | return -EINVAL; | 1082 | return -EINVAL; |
1082 | } | 1083 | } |
@@ -1248,9 +1249,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) | |||
1248 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) | 1249 | if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name) |
1249 | return 0; | 1250 | return 0; |
1250 | 1251 | ||
1251 | addr = kallsyms__get_function_start(filename, | 1252 | if (kallsyms__get_function_start(filename, kmap->ref_reloc_sym->name, &addr)) |
1252 | kmap->ref_reloc_sym->name); | ||
1253 | if (!addr) | ||
1254 | return -1; | 1253 | return -1; |
1255 | 1254 | ||
1256 | *delta = addr - kmap->ref_reloc_sym->addr; | 1255 | *delta = addr - kmap->ref_reloc_sym->addr; |