diff options
author | Cody P Schafer <cody@linux.vnet.ibm.com> | 2012-08-10 18:23:01 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-08-13 13:41:33 -0400 |
commit | 261360b6e90a782f0a63d8f61a67683c376c88cf (patch) | |
tree | 81df91bf3b8f5f9133b105db5037850817284747 /tools | |
parent | d26cd12b46cb6b5595143804b43ba5aa7968551e (diff) |
perf symbols: Convert dso__load_syms to take 2 symsrc's
To properly handle platforms with an opd section, both a runtime image
(which contains the opd section but possibly lacks symbols) and a symbol
image (which probably lacks an opd section but has symbols).
The next patch ("perf symbol: use both runtime and debug images")
adjusts the callsite in dso__load() to take advantage of being able to
pass both runtime & debug images.
Assumptions made here:
- The opd section, if it exists in the runtime image, has headers in
both the runtime image and the debug/syms image.
- The index of the opd section (again, only if it exists in the runtime
image) is the same in both the runtime and debug/symbols image.
Both of these are true on RHEL, but it is unclear how accurate they are
in general (on platforms with function descriptors in opd sections).
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-16-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 | 47 | ||||
-rw-r--r-- | tools/perf/util/symbol-minimal.c | 1 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 4 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 5 |
4 files changed, 30 insertions, 27 deletions
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 492ebecfbfb6..36e4a458e7a1 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c | |||
@@ -619,7 +619,8 @@ out_close: | |||
619 | return err; | 619 | return err; |
620 | } | 620 | } |
621 | 621 | ||
622 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | 622 | int dso__load_sym(struct dso *dso, struct map *map, |
623 | struct symsrc *syms_ss, struct symsrc *runtime_ss, | ||
623 | symbol_filter_t filter, int kmodule) | 624 | symbol_filter_t filter, int kmodule) |
624 | { | 625 | { |
625 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; | 626 | struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; |
@@ -630,31 +631,27 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | |||
630 | int err = -1; | 631 | int err = -1; |
631 | uint32_t idx; | 632 | uint32_t idx; |
632 | GElf_Ehdr ehdr; | 633 | GElf_Ehdr ehdr; |
633 | GElf_Shdr shdr, opdshdr; | 634 | GElf_Shdr shdr; |
634 | Elf_Data *syms, *opddata = NULL; | 635 | Elf_Data *syms, *opddata = NULL; |
635 | GElf_Sym sym; | 636 | GElf_Sym sym; |
636 | Elf_Scn *sec, *sec_strndx, *opdsec; | 637 | Elf_Scn *sec, *sec_strndx; |
637 | Elf *elf; | 638 | Elf *elf; |
638 | int nr = 0; | 639 | int nr = 0; |
639 | size_t opdidx = 0; | ||
640 | 640 | ||
641 | dso->symtab_type = ss->type; | 641 | dso->symtab_type = syms_ss->type; |
642 | 642 | ||
643 | if (!ss->symtab) { | 643 | if (!syms_ss->symtab) { |
644 | ss->symtab = ss->dynsym; | 644 | syms_ss->symtab = syms_ss->dynsym; |
645 | ss->symshdr = ss->dynshdr; | 645 | syms_ss->symshdr = syms_ss->dynshdr; |
646 | } | 646 | } |
647 | 647 | ||
648 | elf = ss->elf; | 648 | elf = syms_ss->elf; |
649 | ehdr = ss->ehdr; | 649 | ehdr = syms_ss->ehdr; |
650 | sec = ss->symtab; | 650 | sec = syms_ss->symtab; |
651 | shdr = ss->symshdr; | 651 | shdr = syms_ss->symshdr; |
652 | 652 | ||
653 | opdsec = ss->opdsec; | 653 | if (runtime_ss->opdsec) |
654 | opdshdr = ss->opdshdr; | 654 | opddata = elf_rawdata(runtime_ss->opdsec, NULL); |
655 | opdidx = ss->opdidx; | ||
656 | if (opdsec) | ||
657 | opddata = elf_rawdata(opdsec, NULL); | ||
658 | 655 | ||
659 | syms = elf_getdata(sec, NULL); | 656 | syms = elf_getdata(sec, NULL); |
660 | if (syms == NULL) | 657 | if (syms == NULL) |
@@ -679,13 +676,14 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | |||
679 | nr_syms = shdr.sh_size / shdr.sh_entsize; | 676 | nr_syms = shdr.sh_size / shdr.sh_entsize; |
680 | 677 | ||
681 | memset(&sym, 0, sizeof(sym)); | 678 | memset(&sym, 0, sizeof(sym)); |
682 | dso->adjust_symbols = ss->adjust_symbols; | 679 | dso->adjust_symbols = runtime_ss->adjust_symbols; |
683 | elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { | 680 | elf_symtab__for_each_symbol(syms, nr_syms, idx, sym) { |
684 | struct symbol *f; | 681 | struct symbol *f; |
685 | const char *elf_name = elf_sym__name(&sym, symstrs); | 682 | const char *elf_name = elf_sym__name(&sym, symstrs); |
686 | char *demangled = NULL; | 683 | char *demangled = NULL; |
687 | int is_label = elf_sym__is_label(&sym); | 684 | int is_label = elf_sym__is_label(&sym); |
688 | const char *section_name; | 685 | const char *section_name; |
686 | bool used_opd = false; | ||
689 | 687 | ||
690 | if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name && | 688 | if (kmap && kmap->ref_reloc_sym && kmap->ref_reloc_sym->name && |
691 | strcmp(elf_name, kmap->ref_reloc_sym->name) == 0) | 689 | strcmp(elf_name, kmap->ref_reloc_sym->name) == 0) |
@@ -704,14 +702,16 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | |||
704 | continue; | 702 | continue; |
705 | } | 703 | } |
706 | 704 | ||
707 | if (opdsec && sym.st_shndx == opdidx) { | 705 | if (runtime_ss->opdsec && sym.st_shndx == runtime_ss->opdidx) { |
708 | u32 offset = sym.st_value - opdshdr.sh_addr; | 706 | u32 offset = sym.st_value - syms_ss->opdshdr.sh_addr; |
709 | u64 *opd = opddata->d_buf + offset; | 707 | u64 *opd = opddata->d_buf + offset; |
710 | sym.st_value = DSO__SWAP(dso, u64, *opd); | 708 | sym.st_value = DSO__SWAP(dso, u64, *opd); |
711 | sym.st_shndx = elf_addr_to_index(elf, sym.st_value); | 709 | sym.st_shndx = elf_addr_to_index(runtime_ss->elf, |
710 | sym.st_value); | ||
711 | used_opd = true; | ||
712 | } | 712 | } |
713 | 713 | ||
714 | sec = elf_getscn(elf, sym.st_shndx); | 714 | sec = elf_getscn(runtime_ss->elf, sym.st_shndx); |
715 | if (!sec) | 715 | if (!sec) |
716 | goto out_elf_end; | 716 | goto out_elf_end; |
717 | 717 | ||
@@ -777,7 +777,8 @@ int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | |||
777 | goto new_symbol; | 777 | goto new_symbol; |
778 | } | 778 | } |
779 | 779 | ||
780 | if (curr_dso->adjust_symbols && sym.st_value) { | 780 | if ((used_opd && runtime_ss->adjust_symbols) |
781 | || (!used_opd && syms_ss->adjust_symbols)) { | ||
781 | pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " | 782 | pr_debug4("%s: adjusting symbol: st_value: %#" PRIx64 " " |
782 | "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, | 783 | "sh_addr: %#" PRIx64 " sh_offset: %#" PRIx64 "\n", __func__, |
783 | (u64)sym.st_value, (u64)shdr.sh_addr, | 784 | (u64)sym.st_value, (u64)shdr.sh_addr, |
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c index 11c2c606ce77..7747ea6d7e97 100644 --- a/tools/perf/util/symbol-minimal.c +++ b/tools/perf/util/symbol-minimal.c | |||
@@ -280,6 +280,7 @@ int dso__synthesize_plt_symbols(struct dso *dso __used, | |||
280 | } | 280 | } |
281 | 281 | ||
282 | int dso__load_sym(struct dso *dso, struct map *map __used, struct symsrc *ss, | 282 | int dso__load_sym(struct dso *dso, struct map *map __used, struct symsrc *ss, |
283 | struct symsrc *runtime_ss __used, | ||
283 | symbol_filter_t filter __used, int kmodule __used) | 284 | symbol_filter_t filter __used, int kmodule __used) |
284 | { | 285 | { |
285 | unsigned char *build_id[BUILD_ID_SIZE]; | 286 | unsigned char *build_id[BUILD_ID_SIZE]; |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 8e7d74ff6ba5..739e5a32366a 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -1094,7 +1094,7 @@ restart: | |||
1094 | continue; | 1094 | continue; |
1095 | } | 1095 | } |
1096 | 1096 | ||
1097 | ret = dso__load_sym(dso, map, &ss, filter, 0); | 1097 | ret = dso__load_sym(dso, map, &ss, &ss, filter, 0); |
1098 | 1098 | ||
1099 | /* | 1099 | /* |
1100 | * Some people seem to have debuginfo files _WITHOUT_ debug | 1100 | * Some people seem to have debuginfo files _WITHOUT_ debug |
@@ -1380,7 +1380,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, | |||
1380 | if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) | 1380 | if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) |
1381 | return -1; | 1381 | return -1; |
1382 | 1382 | ||
1383 | err = dso__load_sym(dso, map, &ss, filter, 0); | 1383 | err = dso__load_sym(dso, map, &ss, &ss, filter, 0); |
1384 | symsrc__destroy(&ss); | 1384 | symsrc__destroy(&ss); |
1385 | 1385 | ||
1386 | if (err > 0) { | 1386 | if (err > 0) { |
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index fa9f6b1cdc46..1f3eed21f35d 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -369,8 +369,9 @@ ssize_t dso__data_read_addr(struct dso *dso, struct map *map, | |||
369 | struct machine *machine, u64 addr, | 369 | struct machine *machine, u64 addr, |
370 | u8 *data, ssize_t size); | 370 | u8 *data, ssize_t size); |
371 | int dso__test_data(void); | 371 | int dso__test_data(void); |
372 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *ss, | 372 | int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, |
373 | symbol_filter_t filter, int kmodule); | 373 | struct symsrc *runtime_ss, symbol_filter_t filter, |
374 | int kmodule); | ||
374 | int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, | 375 | int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, |
375 | struct map *map, symbol_filter_t filter); | 376 | struct map *map, symbol_filter_t filter); |
376 | 377 | ||