aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/symbol-elf.c119
-rw-r--r--tools/perf/util/symbol-minimal.c30
-rw-r--r--tools/perf/util/symbol.c22
-rw-r--r--tools/perf/util/symbol.h36
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
539int 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) 540void symsrc__destroy(struct symsrc *ss)
541{
542 free(ss->name);
543 elf_end(ss->elf);
544 close(ss->fd);
545}
546
547int 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
622out_elf_end:
623 elf_end(elf);
624out_close:
625 close(fd);
626 return err;
627}
628
629int 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;
772out_elf_end: 835out_elf_end:
773 elf_end(elf);
774out_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
244int 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;
258out_close:
259 close(fd);
260 return -1;
261}
262
263void symsrc__destroy(struct symsrc *ss)
264{
265 free(ss->name);
266 close(ss->fd);
267}
268
244int dso__synthesize_plt_symbols(struct dso *dso __used, char *name __used, 269int 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
251int dso__load_sym(struct dso *dso, struct map *map __used, 276int 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:
1359int dso__load_vmlinux(struct dso *dso, struct map *map, 1358int 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
15extern char *cplus_demangle(const char *, int); 21extern 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
228struct 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
252void symsrc__destroy(struct symsrc *ss);
253int 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);
336int dso__test_data(void); 370int dso__test_data(void);
337int dso__load_sym(struct dso *dso, struct map *map, const char *name, int fd, 371int 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);
339int dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map, 373int dso__synthesize_plt_symbols(struct dso *dso, char *name, struct map *map,
340 symbol_filter_t filter); 374 symbol_filter_t filter);