diff options
author | Cody P Schafer <cody@linux.vnet.ibm.com> | 2012-08-10 18:23:02 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-08-13 13:46:55 -0400 |
commit | 3aafe5ae08f2aed378e06d78b207883879d25cbe (patch) | |
tree | cf1eeeefb542e6abe0d52346193a5d64f3dce4f2 /tools | |
parent | 261360b6e90a782f0a63d8f61a67683c376c88cf (diff) |
perf symbols: Use both runtime and debug images
We keep both a 'runtime' elf image as well as a 'debug' elf image around
and generate symbols by looking at both of these.
This eliminates the need for the want_symtab/goto restart mechanism
combined with iterating over and reopening the elf images a second time.
Also give dso__synthsize_plt_symbols() the runtime image (which has
dynsyms) instead of the symbol image (which may only have a symtab and
no dynsyms).
Previously if a debug image was found all runtime images were ignored.
This fixes 2 issues:
- Symbol resolution to failure on PowerPC systems with debug symbols
installed, as the debug images lack a '.opd' section which contains
function descriptors.
- On all archs, plt synthesis failed when a debug image was loaded and
that debug image lacks a dynsym section while a runtime image has a
dynsym section.
Assumptions:
- If a .opd section exists, it is contained in the highest priority
image with a dynsym section.
- This generally implies that the debug image lacks a dynsym section
(ie: it is marked as NO_BITS).
Signed-off-by: Cody P Schafer <cody@linux.vnet.ibm.com>
Cc: David Hansen <dave@linux.vnet.ibm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Matt Hellsley <matthltc@us.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/1344637382-22789-17-git-send-email-cody@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/symbol-elf.c | 5 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 6 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 77 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 |
4 files changed, 56 insertions, 33 deletions
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 36e4a458e7a1..5b37e13f08fb 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -525,6 +525,11 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) | |||
525 | return 0; | 525 | return 0; |
526 | } | 526 | } |
527 | 527 | ||
528 | bool symsrc__possibly_runtime(struct symsrc *ss) | ||
529 | { | ||
530 | return ss->dynsym || ss->opdsec; | ||
531 | } | ||
532 | |||
528 | bool symsrc__has_symtab(struct symsrc *ss) | 533 | bool symsrc__has_symtab(struct symsrc *ss) |
529 | { | 534 | { |
530 | return ss->symtab != NULL; | 535 | return ss->symtab != NULL; |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 7747ea6d7e97..6738ea128c90 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -260,6 +260,12 @@ out_close: | |||
260 | return -1; | 260 | return -1; |
261 | } | 261 | } |
262 | 262 | ||
263 | bool symsrc__possibly_runtime(struct symsrc *ss __used) | ||
264 | { | ||
265 | /* Assume all sym sources could be a runtime image. */ | ||
266 | return true; | ||
267 | } | ||
268 | |||
263 | bool symsrc__has_symtab(struct symsrc *ss __used) | 269 | bool symsrc__has_symtab(struct symsrc *ss __used) |
264 | { | 270 | { |
265 | return false; | 271 | return false; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 739e5a32366a..2293a4a5af96 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1026,11 +1026,12 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1026 | { | 1026 | { |
1027 | char *name; | 1027 | char *name; |
1028 | int ret = -1; | 1028 | int ret = -1; |
1029 | struct symsrc ss; | ||
1030 | u_int i; | 1029 | u_int i; |
1031 | struct machine *machine; | 1030 | struct machine *machine; |
1032 | char *root_dir = (char *) ""; | 1031 | char *root_dir = (char *) ""; |
1033 | int want_symtab; | 1032 | int ss_pos = 0; |
1033 | struct symsrc ss_[2]; | ||
1034 | struct symsrc *syms_ss = NULL, *runtime_ss = NULL; | ||
1034 | 1035 | ||
1035 | dso__set_loaded(dso, map->type); | 1036 | dso__set_loaded(dso, map->type); |
1036 | 1037 | ||
@@ -1072,12 +1073,12 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) | |||
1072 | root_dir = machine->root_dir; | 1073 | root_dir = machine->root_dir; |
1073 | 1074 | ||
1074 | /* Iterate over candidate debug images. | 1075 | /* Iterate over candidate debug images. |
1075 | * On the first pass, only load images if they have a full symtab. | 1076 | * Keep track of "interesting" ones (those which have a symtab, dynsym, |
1076 | * Failing that, do a second pass where we accept .dynsym also | 1077 | * and/or opd section) for processing. |
1077 | */ | 1078 | */ |
1078 | want_symtab = 1; | ||
1079 | restart: | ||
1080 | for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { | 1079 | for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) { |
1080 | struct symsrc *ss = &ss_[ss_pos]; | ||
1081 | bool next_slot = false; | ||
1081 | 1082 | ||
1082 | enum dso_binary_type symtab_type = binary_type_symtab[i]; | 1083 | enum dso_binary_type symtab_type = binary_type_symtab[i]; |
1083 | 1084 | ||
@@ -1086,45 +1087,55 @@ restart: | |||
1086 | continue; | 1087 | continue; |
1087 | 1088 | ||
1088 | /* Name is now the name of the next image to try */ | 1089 | /* Name is now the name of the next image to try */ |
1089 | if (symsrc__init(&ss, dso, name, symtab_type) < 0) | 1090 | if (symsrc__init(ss, dso, name, symtab_type) < 0) |
1090 | continue; | 1091 | continue; |
1091 | 1092 | ||
1092 | if (want_symtab && !symsrc__has_symtab(&ss)) { | 1093 | if (!syms_ss && symsrc__has_symtab(ss)) { |
1093 | symsrc__destroy(&ss); | 1094 | syms_ss = ss; |
1094 | continue; | 1095 | next_slot = true; |
1095 | } | 1096 | } |
1096 | 1097 | ||
1097 | ret = dso__load_sym(dso, map, &ss, &ss, filter, 0); | 1098 | if (!runtime_ss && symsrc__possibly_runtime(ss)) { |
1098 | 1099 | runtime_ss = ss; | |
1099 | /* | 1100 | next_slot = true; |
1100 | * Some people seem to have debuginfo files _WITHOUT_ debug | ||
1101 | * info!?!? | ||
1102 | */ | ||
1103 | if (!ret) { | ||
1104 | symsrc__destroy(&ss); | ||
1105 | continue; | ||
1106 | } | 1101 | } |
1107 | 1102 | ||
1108 | if (ret > 0) { | 1103 | if (next_slot) { |
1109 | int nr_plt; | 1104 | ss_pos++; |
1110 | 1105 | ||
1111 | nr_plt = dso__synthesize_plt_symbols(dso, &ss, map, filter); | 1106 | if (syms_ss && runtime_ss) |
1112 | if (nr_plt > 0) | 1107 | break; |
1113 | ret += nr_plt; | ||
1114 | symsrc__destroy(&ss); | ||
1115 | break; | ||
1116 | } | 1108 | } |
1109 | |||
1117 | } | 1110 | } |
1118 | 1111 | ||
1119 | /* | 1112 | if (!runtime_ss && !syms_ss) |
1120 | * If we wanted a full symtab but no image had one, | 1113 | goto out_free; |
1121 | * relax our requirements and repeat the search. | 1114 | |
1122 | */ | 1115 | if (runtime_ss && !syms_ss) { |
1123 | if (ret <= 0 && want_symtab) { | 1116 | syms_ss = runtime_ss; |
1124 | want_symtab = 0; | 1117 | } |
1125 | goto restart; | 1118 | |
1119 | /* We'll have to hope for the best */ | ||
1120 | if (!runtime_ss && syms_ss) | ||
1121 | runtime_ss = syms_ss; | ||
1122 | |||
1123 | if (syms_ss) | ||
1124 | ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, 0); | ||
1125 | else | ||
1126 | ret = -1; | ||
1127 | |||
1128 | if (ret > 0 && runtime_ss->dynsym) { | ||
1129 | int nr_plt; | ||
1130 | |||
1131 | nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter); | ||
1132 | if (nr_plt > 0) | ||
1133 | ret += nr_plt; | ||
1126 | } | 1134 | } |
1127 | 1135 | ||
1136 | for (; ss_pos > 0; ss_pos--) | ||
1137 | symsrc__destroy(&ss_[ss_pos - 1]); | ||
1138 | out_free: | ||
1128 | free(name); | 1139 | free(name); |
1129 | if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) | 1140 | if (ret < 0 && strstr(dso->name, " (deleted)") != NULL) |
1130 | return 0; | 1141 | return 0; |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 1f3eed21f35d..fc4b1e630fd9 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -253,6 +253,7 @@ void symsrc__destroy(struct symsrc *ss); | |||
253 | int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, | 253 | int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, |
254 | enum dso_binary_type type); | 254 | enum dso_binary_type type); |
255 | bool symsrc__has_symtab(struct symsrc *ss); | 255 | bool symsrc__has_symtab(struct symsrc *ss); |
256 | bool symsrc__possibly_runtime(struct symsrc *ss); | ||
256 | 257 | ||
257 | #define DSO__SWAP(dso, type, val) \ | 258 | #define DSO__SWAP(dso, type, val) \ |
258 | ({ \ | 259 | ({ \ |