Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd7a346e authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar
Browse files

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: default avatarArnaldo 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: default avatarIngo Molnar <mingo@elte.hu>
parent 6671cb16
Loading
Loading
Loading
Loading
+38 −9
Original line number Original line Diff line number Diff line
@@ -899,13 +899,19 @@ bool dsos__read_build_ids(void)
	return have_build_id;
	return have_build_id;
}
}


/*
 * Align offset to 4 bytes as needed for note name and descriptor data.
 */
#define NOTE_ALIGN(n) (((n) + 3) & -4U)

int filename__read_build_id(const char *filename, void *bf, size_t size)
int filename__read_build_id(const char *filename, void *bf, size_t size)
{
{
	int fd, err = -1;
	int fd, err = -1;
	GElf_Ehdr ehdr;
	GElf_Ehdr ehdr;
	GElf_Shdr shdr;
	GElf_Shdr shdr;
	Elf_Data *build_id_data;
	Elf_Data *data;
	Elf_Scn *sec;
	Elf_Scn *sec;
	void *ptr;
	Elf *elf;
	Elf *elf;


	if (size < BUILD_ID_SIZE)
	if (size < BUILD_ID_SIZE)
@@ -928,14 +934,37 @@ int filename__read_build_id(const char *filename, void *bf, size_t size)


	sec = elf_section_by_name(elf, &ehdr, &shdr,
	sec = elf_section_by_name(elf, &ehdr, &shdr,
				  ".note.gnu.build-id", NULL);
				  ".note.gnu.build-id", NULL);
	if (sec == NULL) {
		sec = elf_section_by_name(elf, &ehdr, &shdr,
					  ".notes", NULL);
		if (sec == NULL)
		if (sec == NULL)
			goto out_elf_end;
			goto out_elf_end;
	}


	build_id_data = elf_getdata(sec, NULL);
	data = elf_getdata(sec, NULL);
	if (build_id_data == NULL)
	if (data == NULL)
		goto out_elf_end;
		goto out_elf_end;
	memcpy(bf, build_id_data->d_buf + 16, BUILD_ID_SIZE);

	ptr = data->d_buf;
	while (ptr < (data->d_buf + data->d_size)) {
		GElf_Nhdr *nhdr = ptr;
		int namesz = NOTE_ALIGN(nhdr->n_namesz),
		    descsz = NOTE_ALIGN(nhdr->n_descsz);
		const char *name;

		ptr += sizeof(*nhdr);
		name = ptr;
		ptr += namesz;
		if (nhdr->n_type == NT_GNU_BUILD_ID &&
		    nhdr->n_namesz == sizeof("GNU")) {
			if (memcmp(name, "GNU", sizeof("GNU")) == 0) {
				memcpy(bf, ptr, BUILD_ID_SIZE);
				err = BUILD_ID_SIZE;
				err = BUILD_ID_SIZE;
				break;
			}
		}
		ptr += descsz;
	}
out_elf_end:
out_elf_end:
	elf_end(elf);
	elf_end(elf);
out_close:
out_close:
@@ -963,8 +992,8 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
		if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
		if (read(fd, &nhdr, sizeof(nhdr)) != sizeof(nhdr))
			break;
			break;


		namesz = (nhdr.n_namesz + 3) & -4U;
		namesz = NOTE_ALIGN(nhdr.n_namesz);
		descsz = (nhdr.n_descsz + 3) & -4U;
		descsz = NOTE_ALIGN(nhdr.n_descsz);
		if (nhdr.n_type == NT_GNU_BUILD_ID &&
		if (nhdr.n_type == NT_GNU_BUILD_ID &&
		    nhdr.n_namesz == sizeof("GNU")) {
		    nhdr.n_namesz == sizeof("GNU")) {
			if (read(fd, bf, namesz) != namesz)
			if (read(fd, bf, namesz) != namesz)