[profile] Fix writing binary id into profiles

This patch adds support to read all the PT_NOTE segments in the
executable to find the binary ids. Previously, it was only reading
the first PT_NOTE segment, and this was missing the cases where
binary id is in the following segments. As a result, binary-id.c
and binary-id-padding.c test were failing in the following cases:
1) sanitizer-x86_64-linux bot
   https://lab.llvm.org/staging/#/builders/97
2) OpenSuse Tumbleweed
   https://github.com/llvm/llvm-project/issues/52695

Differential Revision: https://reviews.llvm.org/D115830
This commit is contained in:
Gulfem Savrun Yeniceri 2021-12-15 21:51:33 +00:00
parent 773ab3c665
commit f261e258ec
1 changed files with 37 additions and 14 deletions

View File

@ -125,11 +125,9 @@ static int WriteOneBinaryId(ProfDataWriter *Writer, uint64_t BinaryIdLen,
static int WriteBinaryIdForNote(ProfDataWriter *Writer,
const ElfW(Nhdr) * Note) {
int BinaryIdSize = 0;
const char *NoteName = (const char *)Note + sizeof(ElfW(Nhdr));
if (Note->n_type == NT_GNU_BUILD_ID && Note->n_namesz == 4 &&
memcmp(NoteName, "GNU\0", 4) == 0) {
uint64_t BinaryIdLen = Note->n_descsz;
const uint8_t *BinaryIdData =
(const uint8_t *)(NoteName + RoundUp(Note->n_namesz, 4));
@ -151,12 +149,12 @@ static int WriteBinaryIdForNote(ProfDataWriter *Writer,
*/
static int WriteBinaryIds(ProfDataWriter *Writer, const ElfW(Nhdr) * Note,
const ElfW(Nhdr) * NotesEnd) {
int TotalBinaryIdsSize = 0;
int BinaryIdsSize = 0;
while (Note < NotesEnd) {
int Result = WriteBinaryIdForNote(Writer, Note);
if (Result == -1)
int OneBinaryIdSize = WriteBinaryIdForNote(Writer, Note);
if (OneBinaryIdSize == -1)
return -1;
TotalBinaryIdsSize += Result;
BinaryIdsSize += OneBinaryIdSize;
/* Calculate the offset of the next note in notes section. */
size_t NoteOffset = sizeof(ElfW(Nhdr)) + RoundUp(Note->n_namesz, 4) +
@ -164,7 +162,7 @@ static int WriteBinaryIds(ProfDataWriter *Writer, const ElfW(Nhdr) * Note,
Note = (const ElfW(Nhdr) *)((const char *)(Note) + NoteOffset);
}
return TotalBinaryIdsSize;
return BinaryIdsSize;
}
/*
@ -178,21 +176,46 @@ COMPILER_RT_VISIBILITY int __llvm_write_binary_ids(ProfDataWriter *Writer) {
const ElfW(Phdr) *ProgramHeader =
(const ElfW(Phdr) *)((uintptr_t)ElfHeader + ElfHeader->e_phoff);
int TotalBinaryIdsSize = 0;
uint32_t I;
/* Iterate through entries in the program header. */
for (I = 0; I < ElfHeader->e_phnum; I++) {
/* Look for the notes section in program header entries. */
/* Look for the notes segment in program header entries. */
if (ProgramHeader[I].p_type != PT_NOTE)
continue;
const ElfW(Nhdr) *Note =
(const ElfW(Nhdr) *)((uintptr_t)ElfHeader + ProgramHeader[I].p_offset);
const ElfW(Nhdr) *NotesEnd =
(const ElfW(Nhdr) *)((const char *)(Note) + ProgramHeader[I].p_filesz);
return WriteBinaryIds(Writer, Note, NotesEnd);
/* There can be multiple notes segment, and examine each of them. */
const ElfW(Nhdr) * Note;
const ElfW(Nhdr) * NotesEnd;
/*
* When examining notes in file, use p_offset, which is the offset within
* the elf file, to find the start of notes.
*/
if (ProgramHeader[I].p_memsz == 0 ||
ProgramHeader[I].p_memsz == ProgramHeader[I].p_filesz) {
Note = (const ElfW(Nhdr) *)((uintptr_t)ElfHeader +
ProgramHeader[I].p_offset);
NotesEnd = (const ElfW(Nhdr) *)((const char *)(Note) +
ProgramHeader[I].p_filesz);
} else {
/*
* When examining notes in memory, use p_vaddr, which is the address of
* section after loaded to memory, to find the start of notes.
*/
Note =
(const ElfW(Nhdr) *)((uintptr_t)ElfHeader + ProgramHeader[I].p_vaddr);
NotesEnd =
(const ElfW(Nhdr) *)((const char *)(Note) + ProgramHeader[I].p_memsz);
}
int BinaryIdsSize = WriteBinaryIds(Writer, Note, NotesEnd);
if (TotalBinaryIdsSize == -1)
return -1;
TotalBinaryIdsSize += BinaryIdsSize;
}
return 0;
return TotalBinaryIdsSize;
}
#else /* !NT_GNU_BUILD_ID */
/*