aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2017-04-27 20:21:09 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2017-05-02 17:23:04 -0400
commitb843f62ad942f3879c2d7acd27b44f931c609685 (patch)
tree5367408cae8262e00b559250bbfc6f8f222f5c38 /tools
parent96395cbbc7e94cbbe4f76cf64cf122fabc19123d (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.c13
-rw-r--r--tools/perf/util/event.c9
-rw-r--r--tools/perf/util/event.h4
-rw-r--r--tools/perf/util/machine.c28
-rw-r--r--tools/perf/util/symbol.c11
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
771u64 kallsyms__get_function_start(const char *kallsyms_filename, 771int 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
782int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 783int 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);
675size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp); 675size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
676size_t perf_event__fprintf(union perf_event *event, FILE *fp); 676size_t perf_event__fprintf(union perf_event *event, FILE *fp);
677 677
678u64 kallsyms__get_function_start(const char *kallsyms_filename, 678int kallsyms__get_function_start(const char *kallsyms_filename,
679 const char *symbol_name); 679 const char *symbol_name, u64 *addr);
680 680
681void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max); 681void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
682void cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map, 682void 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 */
799static u64 machine__get_running_kernel_start(struct machine *machine, 799static 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
824int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel) 828int __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)
1185int machine__create_kernel_maps(struct machine *machine) 1192int 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)
466struct symbol *dso__find_symbol(struct dso *dso, 466struct 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;