diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2009-11-20 17:51:25 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-21 08:11:32 -0500 |
commit | fd7a346ea292074e9f6cdb5232a57c56bf98fdc9 (patch) | |
tree | 9f5154c912d274a4df4a913a8e9baaf3f652591e /tools/perf/util | |
parent | 6671cb1674e69e2aba3d610714bdd3e97a7b51ff (diff) |
perf symbols: Filename__read_build_id should look at .notes section too
In the kernel we have more than one notes section, so the linker
script combines all and puts them into a ".notes" combined
section. So we need to look at both sections and also traverse
them looking at multiple GElf_Nhdr entries till we find the one
we want, with the build_id.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1258757489-5978-2-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/symbol.c | 47 |
1 files changed, 38 insertions, 9 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3b23c18cd36b..d22030828c21 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -899,13 +899,19 @@ bool dsos__read_build_ids(void) | |||
899 | return have_build_id; | 899 | return have_build_id; |
900 | } | 900 | } |
901 | 901 | ||
902 | /* | ||
903 | * Align offset to 4 bytes as needed for note name and descriptor data. | ||
904 | */ | ||
905 | #define NOTE_ALIGN(n) (((n) + 3) & -4U) | ||
906 | |||
902 | int filename__read_build_id(const char *filename, void *bf, size_t size) | 907 | int filename__read_build_id(const char *filename, void *bf, size_t size) |
903 | { | 908 | { |
904 | int fd, err = -1; | 909 | int fd, err = -1; |
905 | GElf_Ehdr ehdr; | 910 | GElf_Ehdr ehdr; |
906 | GElf_Shdr shdr; | 911 | GElf_Shdr shdr; |
907 | Elf_Data *build_id_data; | 912 | Elf_Data *data; |
908 | Elf_Scn *sec; | 913 | Elf_Scn *sec; |
914 | void *ptr; | ||
909 | Elf *elf; | 915 | Elf *elf; |
910 | 916 | ||
911 | if (size < BUILD_ID_SIZE) | 917 | if (size < BUILD_ID_SIZE) |
@@ -928,14 +934,37 @@ int filename__read_build_id(const char *filename, void *bf, size_t size) | |||
928 | 934 | ||
929 | sec = elf_section_by_name(elf, &ehdr, &shdr, | 935 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
930 | ".note.gnu.build-id", NULL); | 936 | ".note.gnu.build-id", NULL); |
931 | if (sec == NULL) | 937 | if (sec == NULL) { |
932 | goto out_elf_end; | 938 | sec = elf_section_by_name(elf, &ehdr, &shdr, |
939 | ".notes", NULL); | ||
940 | if (sec == NULL) | ||
941 | goto out_elf_end; | ||
942 | } | ||
933 | 943 | ||
934 | build_id_data = elf_getdata(sec, NULL); | 944 | data = elf_getdata(sec, NULL); |
935 | if (build_id_data == NULL) | 945 | if (data == NULL) |
936 | goto out_elf_end; | 946 | goto out_elf_end; |
937 | memcpy(bf, build_id_data->d_buf + 16, BUILD_ID_SIZE); | 947 | |
938 | err = BUILD_ID_SIZE; | 948 | ptr = data->d_buf; |
949 | while (ptr < (data->d_buf + data->d_size)) { | ||
950 | GElf_Nhdr *nhdr = ptr; | ||
951 | int namesz = NOTE_ALIGN(nhdr->n_namesz), | ||
952 | descsz = NOTE_ALIGN(nhdr->n_descsz); | ||
953 | const char *name; | ||
954 | |||
955 | ptr += sizeof(*nhdr); | ||
956 | name = ptr; | ||
957 | ptr += namesz; | ||
958 | if (nhdr->n_type == NT_GNU_BUILD_ID && | ||
959 | nhdr->n_namesz == sizeof("GNU")) { | ||
960 | if (memcmp(name, "GNU", sizeof("GNU")) == 0) { | ||
961 | memcpy(bf, ptr, BUILD_ID_SIZE); | ||
962 | err = BUILD_ID_SIZE; | ||
963 | break; | ||
964 | } | ||
965 | } | ||
966 | ptr += descsz; | ||
967 | } | ||
939 | out_elf_end: | 968 | out_elf_end: |
940 | elf_end(elf); | 969 | elf_end(elf); |
941 | out_close: | 970 | out_close: |
@@ -963,8 +992,8 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size) | |||
963 | if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) | 992 | if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr)) |
964 | break; | 993 | break; |
965 | 994 | ||
966 | namesz = (nhdr.n_namesz + 3) & -4U; | 995 | namesz = NOTE_ALIGN(nhdr.n_namesz); |
967 | descsz = (nhdr.n_descsz + 3) & -4U; | 996 | descsz = NOTE_ALIGN(nhdr.n_descsz); |
968 | if (nhdr.n_type == NT_GNU_BUILD_ID && | 997 | if (nhdr.n_type == NT_GNU_BUILD_ID && |
969 | nhdr.n_namesz == sizeof("GNU")) { | 998 | nhdr.n_namesz == sizeof("GNU")) { |
970 | if (read(fd, bf, namesz) != namesz) | 999 | if (read(fd, bf, namesz) != namesz) |