diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/util/symbol-elf.c | 119 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 30 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 22 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 36 |
4 files changed, 163 insertions, 44 deletions
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index a9a194d49c1b..6974b2a44ee7 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -536,24 +536,25 @@ static int dso__swap_init(struct dso *dso, unsigned char eidata) | |||
536 | return 0; | 536 | return 0; |
537 | } | 537 | } |
538 | 538 | ||
539 | int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd, | 539 | |
540 | symbol_filter_t filter, int kmodule, int want_symtab) | 540 | void symsrc__destroy(struct symsrc *ss) |
541 | { | ||
542 | free(ss->name); | ||
543 | elf_end(ss->elf); | ||
544 | close(ss->fd); | ||
545 | } | ||
546 | |||
547 | int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, | ||
548 | enum dso_binary_type type) | ||
541 | { | 549 | { |
542 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; | ||
543 | struct map *curr_map = map; | ||
544 | struct dso *curr_dso = dso; | ||
545 | Elf_Data *symstrs, *secstrs; | ||
546 | uint32_t nr_syms; | ||
547 | int err = -1; | 550 | int err = -1; |
548 | uint32_t idx; | ||
549 | GElf_Ehdr ehdr; | 551 | GElf_Ehdr ehdr; |
550 | GElf_Shdr shdr, opdshdr; | ||
551 | Elf_Data *syms, *opddata = NULL; | ||
552 | GElf_Sym sym; | ||
553 | Elf_Scn *sec, *sec_strndx, *opdsec; | ||
554 | Elf *elf; | 552 | Elf *elf; |
555 | int nr = 0; | 553 | int fd; |
556 | size_t opdidx = 0; | 554 | |
555 | fd = open(name, O_RDONLY); | ||
556 | if (fd < 0) | ||
557 | return -1; | ||
557 | 558 | ||
558 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); | 559 | elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); |
559 | if (elf == NULL) { | 560 | if (elf == NULL) { |
@@ -580,19 +581,88 @@ int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd, | |||
580 | goto out_elf_end; | 581 | goto out_elf_end; |
581 | } | 582 | } |
582 | 583 | ||
583 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".symtab", NULL); | 584 | ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab", |
585 | NULL); | ||
586 | if (ss->symshdr.sh_type != SHT_SYMTAB) | ||
587 | ss->symtab = NULL; | ||
588 | |||
589 | ss->dynsym_idx = 0; | ||
590 | ss->dynsym = elf_section_by_name(elf, &ehdr, &ss->dynshdr, ".dynsym", | ||
591 | &ss->dynsym_idx); | ||
592 | if (ss->dynshdr.sh_type != SHT_DYNSYM) | ||
593 | ss->dynsym = NULL; | ||
594 | |||
595 | ss->opdidx = 0; | ||
596 | ss->opdsec = elf_section_by_name(elf, &ehdr, &ss->opdshdr, ".opd", | ||
597 | &ss->opdidx); | ||
598 | if (ss->opdshdr.sh_type != SHT_PROGBITS) | ||
599 | ss->opdsec = NULL; | ||
600 | |||
601 | if (dso->kernel == DSO_TYPE_USER) { | ||
602 | GElf_Shdr shdr; | ||
603 | ss->adjust_symbols = (ehdr.e_type == ET_EXEC || | ||
604 | elf_section_by_name(elf, &ehdr, &shdr, | ||
605 | ".gnu.prelink_undo", | ||
606 | NULL) != NULL); | ||
607 | } else { | ||
608 | ss->adjust_symbols = 0; | ||
609 | } | ||
610 | |||
611 | ss->name = strdup(name); | ||
612 | if (!ss->name) | ||
613 | goto out_elf_end; | ||
614 | |||
615 | ss->elf = elf; | ||
616 | ss->fd = fd; | ||
617 | ss->ehdr = ehdr; | ||
618 | ss->type = type; | ||
619 | |||
620 | return 0; | ||
621 | |||
622 | out_elf_end: | ||
623 | elf_end(elf); | ||
624 | out_close: | ||
625 | close(fd); | ||
626 | return err; | ||
627 | } | ||
628 | |||
629 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | ||
630 | symbol_filter_t filter, int kmodule, int want_symtab) | ||
631 | { | ||
632 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; | ||
633 | struct map *curr_map = map; | ||
634 | struct dso *curr_dso = dso; | ||
635 | Elf_Data *symstrs, *secstrs; | ||
636 | uint32_t nr_syms; | ||
637 | int err = -1; | ||
638 | uint32_t idx; | ||
639 | GElf_Ehdr ehdr; | ||
640 | GElf_Shdr shdr, opdshdr; | ||
641 | Elf_Data *syms, *opddata = NULL; | ||
642 | GElf_Sym sym; | ||
643 | Elf_Scn *sec, *sec_strndx, *opdsec; | ||
644 | Elf *elf; | ||
645 | int nr = 0; | ||
646 | size_t opdidx = 0; | ||
647 | |||
648 | elf = ss->elf; | ||
649 | ehdr = ss->ehdr; | ||
650 | sec = ss->symtab; | ||
651 | shdr = ss->symshdr; | ||
652 | |||
584 | if (sec == NULL) { | 653 | if (sec == NULL) { |
585 | if (want_symtab) | 654 | if (want_symtab) |
586 | goto out_elf_end; | 655 | goto out_elf_end; |
587 | 656 | ||
588 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".dynsym", NULL); | 657 | sec = ss->dynsym; |
658 | shdr = ss->dynshdr; | ||
589 | if (sec == NULL) | 659 | if (sec == NULL) |
590 | goto out_elf_end; | 660 | goto out_elf_end; |
591 | } | 661 | } |
592 | 662 | ||
593 | opdsec = elf_section_by_name(elf, &ehdr, &opdshdr, ".opd", &opdidx); | 663 | opdsec = ss->opdsec; |
594 | if (opdshdr.sh_type != SHT_PROGBITS) | 664 | opdshdr = ss->opdshdr; |
595 | opdsec = NULL; | 665 | opdidx = ss->opdidx; |
596 | if (opdsec) | 666 | if (opdsec) |
597 | opddata = elf_rawdata(opdsec, NULL); | 667 | opddata = elf_rawdata(opdsec, NULL); |
598 | 668 | ||
@@ -619,14 +689,7 @@ int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd, | |||
619 | nr_syms = shdr.sh_size / shdr.sh_entsize; | 689 | nr_syms = shdr.sh_size / shdr.sh_entsize; |
620 | 690 | ||
621 | memset(&sym, 0, sizeof(sym)); | 691 | memset(&sym, 0, sizeof(sym)); |
622 | if (dso->kernel == DSO_TYPE_USER) { | 692 | dso->adjust_symbols = ss->adjust_symbols; |
623 | dso->adjust_symbols = (ehdr.e_type == ET_EXEC || | ||
624 | elf_section_by_name(elf, &ehdr, &shdr, | ||
625 | ".gnu.prelink_undo", | ||
626 | NULL) != NULL); | ||
627 | } else { | ||
628 | dso->adjust_symbols = 0; | ||
629 | } | ||
630 | elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { | 693 | elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { |
631 | struct symbol *f; | 694 | struct symbol *f; |
632 | const char *elf_name = elf_sym__name(&sym, symstrs); | 695 | const char *elf_name = elf_sym__name(&sym, symstrs); |
@@ -770,8 +833,6 @@ new_symbol: | |||
770 | } | 833 | } |
771 | err = nr; | 834 | err = nr; |
772 | out_elf_end: | 835 | out_elf_end: |
773 | elf_end(elf); | ||
774 | out_close: | ||
775 | return err; | 836 | return err; |
776 | } | 837 | } |
777 | 838 | ||
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index bd8720b6780c..1b16c2729a36 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -241,6 +241,31 @@ out: | |||
241 | return ret; | 241 | return ret; |
242 | } | 242 | } |
243 | 243 | ||
244 | int symsrc__init(struct symsrc *ss, struct dso *dso __used, const char *name, | ||
245 | enum dso_binary_type type) | ||
246 | { | ||
247 | int fd = open(name, O_RDONLY); | ||
248 | if (fd < 0) | ||
249 | return -1; | ||
250 | |||
251 | ss->name = strdup(name); | ||
252 | if (!ss->name) | ||
253 | goto out_close; | ||
254 | |||
255 | ss->type = type; | ||
256 | |||
257 | return 0; | ||
258 | out_close: | ||
259 | close(fd); | ||
260 | return -1; | ||
261 | } | ||
262 | |||
263 | void symsrc__destroy(struct symsrc *ss) | ||
264 | { | ||
265 | free(ss->name); | ||
266 | close(ss->fd); | ||
267 | } | ||
268 | |||
244 | int dso__synthesize_plt_symbols(struct dso *dso __used, char *name __used, | 269 | int dso__synthesize_plt_symbols(struct dso *dso __used, char *name __used, |
245 | struct map *map __used, | 270 | struct map *map __used, |
246 | symbol_filter_t filter __used) | 271 | symbol_filter_t filter __used) |
@@ -248,14 +273,13 @@ int dso__synthesize_plt_symbols(struct dso *dso __used, char *name __used, | |||
248 | return 0; | 273 | return 0; |
249 | } | 274 | } |
250 | 275 | ||
251 | int dso__load_sym(struct dso *dso, struct map *map __used, | 276 | int dso__load_sym(struct dso *dso, struct map *map __used, struct symsrc *ss, |
252 | const char *name, int fd __used, | ||
253 | symbol_filter_t filter __used, int kmodule __used, | 277 | symbol_filter_t filter __used, int kmodule __used, |
254 | int want_symtab __used) | 278 | int want_symtab __used) |
255 | { | 279 | { |
256 | unsigned char *build_id[BUILD_ID_SIZE]; | 280 | unsigned char *build_id[BUILD_ID_SIZE]; |
257 | 281 | ||
258 | if (filename__read_build_id(name, build_id, BUILD_ID_SIZE) > 0) { | 282 | if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) { |
259 | dso__set_build_id(dso, build_id); | 283 | dso__set_build_id(dso, build_id); |
260 | return 1; | 284 | return 1; |
261 | } | 285 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 8f5cabbfc8bd..afec3f048a94 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1026,7 +1026,7 @@ 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 | int fd; | 1029 | struct symsrc ss; |
1030 | u_int i; | 1030 | u_int i; |
1031 | struct machine *machine; | 1031 | struct machine *machine; |
1032 | char *root_dir = (char *) ""; | 1032 | char *root_dir = (char *) ""; |
@@ -1086,13 +1086,12 @@ restart: | |||
1086 | continue; | 1086 | continue; |
1087 | 1087 | ||
1088 | /* Name is now the name of the next image to try */ | 1088 | /* Name is now the name of the next image to try */ |
1089 | fd = open(name, O_RDONLY); | 1089 | if (symsrc__init(&ss, dso, name, dso->symtab_type) < 0) |
1090 | if (fd < 0) | ||
1091 | continue; | 1090 | continue; |
1092 | 1091 | ||
1093 | ret = dso__load_sym(dso, map, name, fd, filter, 0, | 1092 | ret = dso__load_sym(dso, map, &ss, filter, 0, |
1094 | want_symtab); | 1093 | want_symtab); |
1095 | close(fd); | 1094 | symsrc__destroy(&ss); |
1096 | 1095 | ||
1097 | /* | 1096 | /* |
1098 | * Some people seem to have debuginfo files _WITHOUT_ debug | 1097 | * Some people seem to have debuginfo files _WITHOUT_ debug |
@@ -1359,22 +1358,23 @@ out_failure: | |||
1359 | int dso__load_vmlinux(struct dso *dso, struct map *map, | 1358 | int dso__load_vmlinux(struct dso *dso, struct map *map, |
1360 | const char *vmlinux, symbol_filter_t filter) | 1359 | const char *vmlinux, symbol_filter_t filter) |
1361 | { | 1360 | { |
1362 | int err = -1, fd; | 1361 | int err = -1; |
1362 | struct symsrc ss; | ||
1363 | char symfs_vmlinux[PATH_MAX]; | 1363 | char symfs_vmlinux[PATH_MAX]; |
1364 | 1364 | ||
1365 | snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", | 1365 | snprintf(symfs_vmlinux, sizeof(symfs_vmlinux), "%s%s", |
1366 | symbol_conf.symfs, vmlinux); | 1366 | symbol_conf.symfs, vmlinux); |
1367 | fd = open(symfs_vmlinux, O_RDONLY); | ||
1368 | if (fd < 0) | ||
1369 | return -1; | ||
1370 | 1367 | ||
1371 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) | 1368 | if (dso->kernel == DSO_TYPE_GUEST_KERNEL) |
1372 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; | 1369 | dso->symtab_type = DSO_BINARY_TYPE__GUEST_VMLINUX; |
1373 | else | 1370 | else |
1374 | dso->symtab_type = DSO_BINARY_TYPE__VMLINUX; | 1371 | dso->symtab_type = DSO_BINARY_TYPE__VMLINUX; |
1375 | 1372 | ||
1376 | err = dso__load_sym(dso, map, symfs_vmlinux, fd, filter, 0, 0); | 1373 | if (symsrc__init(&ss, dso, symfs_vmlinux, dso->symtab_type)) |
1377 | close(fd); | 1374 | return -1; |
1375 | |||
1376 | err = dso__load_sym(dso, map, &ss, filter, 0, 0); | ||
1377 | symsrc__destroy(&ss); | ||
1378 | 1378 | ||
1379 | if (err > 0) { | 1379 | if (err > 0) { |
1380 | dso__set_long_name(dso, (char *)vmlinux); | 1380 | dso__set_long_name(dso, (char *)vmlinux); |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 37f1ea146c16..dd9e8678b355 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -11,6 +11,12 @@ | |||
11 | #include <stdio.h> | 11 | #include <stdio.h> |
12 | #include <byteswap.h> | 12 | #include <byteswap.h> |
13 | 13 | ||
14 | #ifndef NO_LIBELF_SUPPORT | ||
15 | #include <libelf.h> | ||
16 | #include <gelf.h> | ||
17 | #include <elf.h> | ||
18 | #endif | ||
19 | |||
14 | #ifdef HAVE_CPLUS_DEMANGLE | 20 | #ifdef HAVE_CPLUS_DEMANGLE |
15 | extern char *cplus_demangle(const char *, int); | 21 | extern char *cplus_demangle(const char *, int); |
16 | 22 | ||
@@ -219,6 +225,34 @@ struct dso { | |||
219 | char name[0]; | 225 | char name[0]; |
220 | }; | 226 | }; |
221 | 227 | ||
228 | struct symsrc { | ||
229 | char *name; | ||
230 | int fd; | ||
231 | enum dso_binary_type type; | ||
232 | |||
233 | #ifndef NO_LIBELF_SUPPORT | ||
234 | Elf *elf; | ||
235 | GElf_Ehdr ehdr; | ||
236 | |||
237 | Elf_Scn *opdsec; | ||
238 | size_t opdidx; | ||
239 | GElf_Shdr opdshdr; | ||
240 | |||
241 | Elf_Scn *symtab; | ||
242 | GElf_Shdr symshdr; | ||
243 | |||
244 | Elf_Scn *dynsym; | ||
245 | size_t dynsym_idx; | ||
246 | GElf_Shdr dynshdr; | ||
247 | |||
248 | bool adjust_symbols; | ||
249 | #endif | ||
250 | }; | ||
251 | |||
252 | void symsrc__destroy(struct symsrc *ss); | ||
253 | int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, | ||
254 | enum dso_binary_type type); | ||
255 | |||
222 | #define DSO__SWAP(dso, type, val) \ | 256 | #define DSO__SWAP(dso, type, val) \ |
223 | ({ \ | 257 | ({ \ |
224 | type ____r = val; \ | 258 | type ____r = val; \ |
@@ -334,7 +368,7 @@ ssize_t dso__data_read_addr(struct dso *dso, struct map *map, | |||
334 | struct machine *machine, u64 addr, | 368 | struct machine *machine, u64 addr, |
335 | u8 *data, ssize_t size); | 369 | u8 *data, ssize_t size); |
336 | int dso__test_data(void); | 370 | int dso__test_data(void); |
337 | int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd, | 371 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, |
338 | symbol_filter_t filter, int kmodule, int want_symtab); | 372 | symbol_filter_t filter, int kmodule, int want_symtab); |
339 | int dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map, | 373 | int dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map, |
340 | symbol_filter_t filter); | 374 | symbol_filter_t filter); |