diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e2ba8858f3e1..3e2e5ea0f03f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -323,6 +323,7 @@ struct dso *dso__new(const char *name) | |||
323 | dso->sorted_by_name = 0; | 323 | dso->sorted_by_name = 0; |
324 | dso->has_build_id = 0; | 324 | dso->has_build_id = 0; |
325 | dso->kernel = DSO_TYPE_USER; | 325 | dso->kernel = DSO_TYPE_USER; |
326 | dso->needs_swap = DSO_SWAP__UNSET; | ||
326 | INIT_LIST_HEAD(&dso->node); | 327 | INIT_LIST_HEAD(&dso->node); |
327 | } | 328 | } |
328 | 329 | ||
@@ -1156,6 +1157,33 @@ static size_t elf_addr_to_index(Elf *elf, GElf_Addr addr) | |||
1156 | return -1; | 1157 | return -1; |
1157 | } | 1158 | } |
1158 | 1159 | ||
1160 | static int dso__swap_init(struct dso *dso, unsigned char eidata) | ||
1161 | { | ||
1162 | static unsigned int const endian = 1; | ||
1163 | |||
1164 | dso->needs_swap = DSO_SWAP__NO; | ||
1165 | |||
1166 | switch (eidata) { | ||
1167 | case ELFDATA2LSB: | ||
1168 | /* We are big endian, DSO is little endian. */ | ||
1169 | if (*(unsigned char const *)&endian != 1) | ||
1170 | dso->needs_swap = DSO_SWAP__YES; | ||
1171 | break; | ||
1172 | |||
1173 | case ELFDATA2MSB: | ||
1174 | /* We are little endian, DSO is big endian. */ | ||
1175 | if (*(unsigned char const *)&endian != 0) | ||
1176 | dso->needs_swap = DSO_SWAP__YES; | ||
1177 | break; | ||
1178 | |||
1179 | default: | ||
1180 | pr_err("unrecognized DSO data encoding %d\n", eidata); | ||
1181 | return -EINVAL; | ||
1182 | } | ||
1183 | |||
1184 | return 0; | ||
1185 | } | ||
1186 | |||
1159 | static int dso__load_sym(struct dso *dso, struct map *map, const char *name, | 1187 | static int dso__load_sym(struct dso *dso, struct map *map, const char *name, |
1160 | int fd, symbol_filter_t filter, int kmodule, | 1188 | int fd, symbol_filter_t filter, int kmodule, |
1161 | int want_symtab) | 1189 | int want_symtab) |
@@ -1187,6 +1215,9 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, | |||
1187 | goto out_elf_end; | 1215 | goto out_elf_end; |
1188 | } | 1216 | } |
1189 | 1217 | ||
1218 | if (dso__swap_init(dso, ehdr.e_ident[EI_DATA])) | ||
1219 | goto out_elf_end; | ||
1220 | |||
1190 | /* Always reject images with a mismatched build-id: */ | 1221 | /* Always reject images with a mismatched build-id: */ |
1191 | if (dso->has_build_id) { | 1222 | if (dso->has_build_id) { |
1192 | u8 build_id[BUILD_ID_SIZE]; | 1223 | u8 build_id[BUILD_ID_SIZE]; |
@@ -1272,7 +1303,7 @@ static int dso__load_sym(struct dso *dso, struct map *map, const char *name, | |||
1272 | if (opdsec && sym.st_shndx == opdidx) { | 1303 | if (opdsec && sym.st_shndx == opdidx) { |
1273 | u32 offset = sym.st_value - opdshdr.sh_addr; | 1304 | u32 offset = sym.st_value - opdshdr.sh_addr; |
1274 | u64 *opd = opddata->d_buf + offset; | 1305 | u64 *opd = opddata->d_buf + offset; |
1275 | sym.st_value = *opd; | 1306 | sym.st_value = DSO__SWAP(dso, u64, *opd); |
1276 | sym.st_shndx = elf_addr_to_index(elf, sym.st_value); | 1307 | sym.st_shndx = elf_addr_to_index(elf, sym.st_value); |
1277 | } | 1308 | } |
1278 | 1309 | ||
@@ -2786,8 +2817,11 @@ int machine__load_vmlinux_path(struct machine *machine, enum map_type type, | |||
2786 | 2817 | ||
2787 | struct map *dso__new_map(const char *name) | 2818 | struct map *dso__new_map(const char *name) |
2788 | { | 2819 | { |
2820 | struct map *map = NULL; | ||
2789 | struct dso *dso = dso__new(name); | 2821 | struct dso *dso = dso__new(name); |
2790 | struct map *map = map__new2(0, dso, MAP__FUNCTION); | 2822 | |
2823 | if (dso) | ||
2824 | map = map__new2(0, dso, MAP__FUNCTION); | ||
2791 | 2825 | ||
2792 | return map; | 2826 | return map; |
2793 | } | 2827 | } |