diff options
| -rw-r--r-- | tools/perf/util/symbol.c | 33 | ||||
| -rw-r--r-- | tools/perf/util/symbol.h | 30 |
2 files changed, 62 insertions, 1 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index e2ba8858f3e1..9d04dcd91815 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 | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 5649d63798cb..af0752b1aca1 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/list.h> | 9 | #include <linux/list.h> |
| 10 | #include <linux/rbtree.h> | 10 | #include <linux/rbtree.h> |
| 11 | #include <stdio.h> | 11 | #include <stdio.h> |
| 12 | #include <byteswap.h> | ||
| 12 | 13 | ||
| 13 | #ifdef HAVE_CPLUS_DEMANGLE | 14 | #ifdef HAVE_CPLUS_DEMANGLE |
| 14 | extern char *cplus_demangle(const char *, int); | 15 | extern char *cplus_demangle(const char *, int); |
| @@ -160,11 +161,18 @@ enum dso_kernel_type { | |||
| 160 | DSO_TYPE_GUEST_KERNEL | 161 | DSO_TYPE_GUEST_KERNEL |
| 161 | }; | 162 | }; |
| 162 | 163 | ||
| 164 | enum dso_swap_type { | ||
| 165 | DSO_SWAP__UNSET, | ||
| 166 | DSO_SWAP__NO, | ||
| 167 | DSO_SWAP__YES, | ||
| 168 | }; | ||
| 169 | |||
| 163 | struct dso { | 170 | struct dso { |
| 164 | struct list_head node; | 171 | struct list_head node; |
| 165 | struct rb_root symbols[MAP__NR_TYPES]; | 172 | struct rb_root symbols[MAP__NR_TYPES]; |
| 166 | struct rb_root symbol_names[MAP__NR_TYPES]; | 173 | struct rb_root symbol_names[MAP__NR_TYPES]; |
| 167 | enum dso_kernel_type kernel; | 174 | enum dso_kernel_type kernel; |
| 175 | enum dso_swap_type needs_swap; | ||
| 168 | u8 adjust_symbols:1; | 176 | u8 adjust_symbols:1; |
| 169 | u8 has_build_id:1; | 177 | u8 has_build_id:1; |
| 170 | u8 hit:1; | 178 | u8 hit:1; |
| @@ -182,6 +190,28 @@ struct dso { | |||
| 182 | char name[0]; | 190 | char name[0]; |
| 183 | }; | 191 | }; |
| 184 | 192 | ||
| 193 | #define DSO__SWAP(dso, type, val) \ | ||
| 194 | ({ \ | ||
| 195 | type ____r = val; \ | ||
| 196 | BUG_ON(dso->needs_swap == DSO_SWAP__UNSET); \ | ||
| 197 | if (dso->needs_swap == DSO_SWAP__YES) { \ | ||
| 198 | switch (sizeof(____r)) { \ | ||
| 199 | case 2: \ | ||
| 200 | ____r = bswap_16(val); \ | ||
| 201 | break; \ | ||
| 202 | case 4: \ | ||
| 203 | ____r = bswap_32(val); \ | ||
| 204 | break; \ | ||
| 205 | case 8: \ | ||
| 206 | ____r = bswap_64(val); \ | ||
| 207 | break; \ | ||
| 208 | default: \ | ||
| 209 | BUG_ON(1); \ | ||
| 210 | } \ | ||
| 211 | } \ | ||
| 212 | ____r; \ | ||
| 213 | }) | ||
| 214 | |||
| 185 | struct dso *dso__new(const char *name); | 215 | struct dso *dso__new(const char *name); |
| 186 | void dso__delete(struct dso *dso); | 216 | void dso__delete(struct dso *dso); |
| 187 | 217 | ||
