diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c index e61f90b2cef96..ac2ab4a6a8f53 100644 --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -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 */ /*