aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-20 17:51:25 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-21 08:11:32 -0500
commitfd7a346ea292074e9f6cdb5232a57c56bf98fdc9 (patch)
tree9f5154c912d274a4df4a913a8e9baaf3f652591e /tools
parent6671cb1674e69e2aba3d610714bdd3e97a7b51ff (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')
-rw-r--r--tools/perf/util/symbol.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 3b23c18cd36..d22030828c2 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
902int filename__read_build_id(const char *filename, void *bf, size_t size) 907int 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 }
939out_elf_end: 968out_elf_end:
940 elf_end(elf); 969 elf_end(elf);
941out_close: 970out_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)