diff options
| author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-08-05 18:02:49 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-08-06 14:24:37 -0400 |
| commit | 4d1e00a8af426500edfb8643fa6c375b89f1f804 (patch) | |
| tree | 89fc08dca5da0f6ac7ee28de865281ccad530455 | |
| parent | e0d82a0a4e9841b787e6431ccfbb515546c55dc2 (diff) | |
perf symbol: Fix symbol parsing in certain cases: use the build-id as a symlink
In some cases distros have binaries and debuginfo in weird places:
[root@doppio tuna]# ls -la /usr/lib64/{xulrunner-1.9.1/xulrunner-stub,firefox-3.5.2/firefox}
-rwxr-xr-x 1 root root 90024 2009-08-03 19:45 /usr/lib64/firefox-3.5.2/firefox
-rwxr-xr-x 1 root root 90024 2009-08-03 18:23 /usr/lib64/xulrunner-1.9.1/xulrunner-stub
[root@doppio tuna]# sha1sum /usr/lib64/{xulrunner-1.9.1/xulrunner-stub,firefox-3.5.2/firefox}
19a858077d263d5de22c9c5da250d3e4396ae739 /usr/lib64/xulrunner-1.9.1/xulrunner-stub
19a858077d263d5de22c9c5da250d3e4396ae739 /usr/lib64/firefox-3.5.2/firefox
[root@doppio tuna]# rpm -qf /usr/lib64/{xulrunner-1.9.1/xulrunner-stub,firefox-3.5.2/firefox}
xulrunner-1.9.1.2-1.fc11.x86_64
firefox-3.5.2-2.fc11.x86_64
[root@doppio tuna]# ls -la /usr/lib/debug/{usr/lib64/xulrunner-1.9.1/xulrunner-stub,usr/lib64/firefox-3.5.2/firefox}.debug
ls: cannot access /usr/lib/debug/usr/lib64/firefox-3.5.2/firefox.debug: No such file or directory
-rwxr-xr-x 1 root root 403608 2009-08-03 18:22 /usr/lib/debug/usr/lib64/xulrunner-1.9.1/xulrunner-stub.debug
Seemingly we don't have a .symtab when we actually can find it
if we use the .note.gnu.build-id ELF section put in place by
some distros. Use it and find the symbols we need.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Peter Zijlstra <peterz@infradead.org>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | tools/perf/util/symbol.c | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 0580b94785e7..16ddca202948 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
| @@ -661,10 +661,69 @@ out_close: | |||
| 661 | return err; | 661 | return err; |
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | #define BUILD_ID_SIZE 128 | ||
| 665 | |||
| 666 | static char *dso__read_build_id(struct dso *self, int verbose) | ||
| 667 | { | ||
| 668 | int i; | ||
| 669 | GElf_Ehdr ehdr; | ||
| 670 | GElf_Shdr shdr; | ||
| 671 | Elf_Data *build_id_data; | ||
| 672 | Elf_Scn *sec; | ||
| 673 | char *build_id = NULL, *bid; | ||
| 674 | unsigned char *raw; | ||
| 675 | Elf *elf; | ||
| 676 | int fd = open(self->name, O_RDONLY); | ||
| 677 | |||
| 678 | if (fd < 0) | ||
| 679 | goto out; | ||
| 680 | |||
| 681 | elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); | ||
| 682 | if (elf == NULL) { | ||
| 683 | if (verbose) | ||
| 684 | fprintf(stderr, "%s: cannot read %s ELF file.\n", | ||
| 685 | __func__, self->name); | ||
| 686 | goto out_close; | ||
| 687 | } | ||
| 688 | |||
| 689 | if (gelf_getehdr(elf, &ehdr) == NULL) { | ||
| 690 | if (verbose) | ||
| 691 | fprintf(stderr, "%s: cannot get elf header.\n", __func__); | ||
| 692 | goto out_elf_end; | ||
| 693 | } | ||
| 694 | |||
| 695 | sec = elf_section_by_name(elf, &ehdr, &shdr, ".note.gnu.build-id", NULL); | ||
| 696 | if (sec == NULL) | ||
| 697 | goto out_elf_end; | ||
| 698 | |||
| 699 | build_id_data = elf_getdata(sec, NULL); | ||
| 700 | if (build_id_data == NULL) | ||
| 701 | goto out_elf_end; | ||
| 702 | build_id = malloc(BUILD_ID_SIZE); | ||
| 703 | if (build_id == NULL) | ||
| 704 | goto out_elf_end; | ||
| 705 | raw = build_id_data->d_buf + 16; | ||
| 706 | bid = build_id; | ||
| 707 | |||
| 708 | for (i = 0; i < 20; ++i) { | ||
| 709 | sprintf(bid, "%02x", *raw); | ||
| 710 | ++raw; | ||
| 711 | bid += 2; | ||
| 712 | } | ||
| 713 | if (verbose) | ||
| 714 | printf("%s(%s): %s\n", __func__, self->name, build_id); | ||
| 715 | out_elf_end: | ||
| 716 | elf_end(elf); | ||
| 717 | out_close: | ||
| 718 | close(fd); | ||
| 719 | out: | ||
| 720 | return build_id; | ||
| 721 | } | ||
| 722 | |||
| 664 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) | 723 | int dso__load(struct dso *self, symbol_filter_t filter, int verbose) |
| 665 | { | 724 | { |
| 666 | int size = strlen(self->name) + sizeof("/usr/lib/debug%s.debug"); | 725 | int size = PATH_MAX; |
| 667 | char *name = malloc(size); | 726 | char *name = malloc(size), *build_id = NULL; |
| 668 | int variant = 0; | 727 | int variant = 0; |
| 669 | int ret = -1; | 728 | int ret = -1; |
| 670 | int fd; | 729 | int fd; |
| @@ -686,7 +745,18 @@ more: | |||
| 686 | case 1: /* Ubuntu */ | 745 | case 1: /* Ubuntu */ |
| 687 | snprintf(name, size, "/usr/lib/debug%s", self->name); | 746 | snprintf(name, size, "/usr/lib/debug%s", self->name); |
| 688 | break; | 747 | break; |
| 689 | case 2: /* Sane people */ | 748 | case 2: |
| 749 | build_id = dso__read_build_id(self, verbose); | ||
| 750 | if (build_id != NULL) { | ||
| 751 | snprintf(name, size, | ||
| 752 | "/usr/lib/debug/.build-id/%.2s/%s.debug", | ||
| 753 | build_id, build_id + 2); | ||
| 754 | free(build_id); | ||
| 755 | break; | ||
| 756 | } | ||
| 757 | variant++; | ||
| 758 | /* Fall thru */ | ||
| 759 | case 3: /* Sane people */ | ||
| 690 | snprintf(name, size, "%s", self->name); | 760 | snprintf(name, size, "%s", self->name); |
| 691 | break; | 761 | break; |
| 692 | 762 | ||
