diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -137,6 +137,7 @@ INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) +INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL)) #undef INSTR_PROF_RAW_HEADER /* INSTR_PROF_RAW_HEADER end */ @@ -645,7 +646,7 @@ (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 /* Raw profile format version (start from 1). */ -#define INSTR_PROF_RAW_VERSION 5 +#define INSTR_PROF_RAW_VERSION 6 /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 7 /* Coverage mapping format version (start from 0). */ diff --git a/compiler-rt/lib/profile/InstrProfilingInternal.h b/compiler-rt/lib/profile/InstrProfilingInternal.h --- a/compiler-rt/lib/profile/InstrProfilingInternal.h +++ b/compiler-rt/lib/profile/InstrProfilingInternal.h @@ -193,4 +193,11 @@ COMPILER_RT_VISIBILITY extern ValueProfNode *EndVNode; extern void (*VPMergeHook)(struct ValueProfData *, __llvm_profile_data *); +/* + * Write binary ids into profiles if writer is given. + * Return -1 if an error occurs, otherwise, return total size of binary ids. + */ +COMPILER_RT_VISIBILITY COMPILER_RT_WEAK int +__llvm_write_binary_ids(ProfDataWriter *Writer); + #endif diff --git a/compiler-rt/lib/profile/InstrProfilingInternal.c b/compiler-rt/lib/profile/InstrProfilingInternal.c --- a/compiler-rt/lib/profile/InstrProfilingInternal.c +++ b/compiler-rt/lib/profile/InstrProfilingInternal.c @@ -23,4 +23,23 @@ ProfileDumped = Value; } +static unsigned RuntimeCounterRelocation = 0; + +COMPILER_RT_VISIBILITY unsigned lprofRuntimeCounterRelocation(void) { + return RuntimeCounterRelocation; +} + +COMPILER_RT_VISIBILITY void lprofSetRuntimeCounterRelocation(unsigned Value) { + RuntimeCounterRelocation = Value; +} + +/* + * The runtime provides the default definition of this function + * for the platforms that do not support binary id. + */ +COMPILER_RT_VISIBILITY COMPILER_RT_WEAK int +__llvm_write_binary_ids(ProfDataWriter *Writer) { + return 0; +} + #endif diff --git a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c --- a/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c +++ b/compiler-rt/lib/profile/InstrProfilingPlatformLinux.c @@ -9,9 +9,13 @@ #if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ (defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__) +#include +#include #include +#include #include "InstrProfiling.h" +#include "InstrProfilingInternal.h" #define PROF_DATA_START INSTR_PROF_SECT_START(INSTR_PROF_DATA_COMMON) #define PROF_DATA_STOP INSTR_PROF_SECT_STOP(INSTR_PROF_DATA_COMMON) @@ -72,4 +76,109 @@ COMPILER_RT_VISIBILITY ValueProfNode *CurrentVNode = &PROF_VNODES_START; COMPILER_RT_VISIBILITY ValueProfNode *EndVNode = &PROF_VNODES_STOP; +static size_t RoundUp(size_t size, size_t align) { + return (size + align - 1) & ~(align - 1); +} + +/* + * Write binary id length and then its data, because binary id does not + * have a fixed length. + */ +int WriteOneBinaryId(ProfDataWriter *Writer, uint64_t BinaryIdLen, + const uint8_t *BinaryIdData) { + ProfDataIOVec BinaryIdIOVec[] = { + {&BinaryIdLen, sizeof(uint64_t), 1, 0}, + {BinaryIdData, sizeof(uint8_t), BinaryIdLen, 0}}; + if (Writer->Write(Writer, BinaryIdIOVec, + sizeof(BinaryIdIOVec) / sizeof(*BinaryIdIOVec))) + return -1; + + /* Successfully wrote binary id, report success. */ + return 0; +} + +/* + * Look for the note that has the name "GNU\0" and type NT_GNU_BUILD_ID + * that contains build id. If build id exists, write binary id. + * + * Each note in notes section starts with a struct which includes + * n_namesz, n_descsz, and n_type members. It is followed by the name + * (whose length is defined in n_namesz) and then by the descriptor + * (whose length is defined in n_descsz). + * + * Note sections like .note.ABI-tag and .note.gnu.build-id are aligned + * to 4 bytes, so round n_namesz and n_descsz to the nearest 4 bytes. + */ +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)); + if (Writer != NULL && + WriteOneBinaryId(Writer, BinaryIdLen, BinaryIdData) == -1) + return -1; + + BinaryIdSize = sizeof(BinaryIdLen) + BinaryIdLen; + } + + return BinaryIdSize; +} + +/* + * Helper function that iterates through notes section and find build ids. + * If writer is given, write binary ids into profiles. + * If an error happens while writing, return -1. + */ +int WriteBinaryIds(ProfDataWriter *Writer, const ElfW(Nhdr) * Note, + const ElfW(Nhdr) * NotesEnd) { + int TotalBinaryIdsSize = 0; + while (Note < NotesEnd) { + int Result = WriteBinaryIdForNote(Writer, Note); + if (Result == -1) + return -1; + TotalBinaryIdsSize += Result; + + /* Calculate the offset of the next note in notes section. */ + size_t NoteOffset = sizeof(ElfW(Nhdr)) + RoundUp(Note->n_namesz, 4) + + RoundUp(Note->n_descsz, 4); + Note = (const ElfW(Nhdr) *)((const char *)(Note) + NoteOffset); + } + + return TotalBinaryIdsSize; +} + +/* + * Write binary ids into profiles if writer is given. + * Return the total size of binary ids. + * If an error happens while writing, return -1. + */ +COMPILER_RT_VISIBILITY COMPILER_RT_WEAK int +__llvm_write_binary_ids(ProfDataWriter *Writer) { + extern const ElfW(Ehdr) __ehdr_start __attribute__((visibility("hidden"))); + const ElfW(Ehdr) *ElfHeader = &__ehdr_start; + const ElfW(Phdr) *ProgramHeader = + (const ElfW(Phdr) *)((uintptr_t)ElfHeader + ElfHeader->e_phoff); + + 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. */ + 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); + } + + return 0; +} + #endif diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c --- a/compiler-rt/lib/profile/InstrProfilingWriter.c +++ b/compiler-rt/lib/profile/InstrProfilingWriter.c @@ -283,16 +283,24 @@ #define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init; #include "profile/InstrProfData.inc" - /* Write the data. */ - ProfDataIOVec IOVec[] = { - {&Header, sizeof(__llvm_profile_header), 1, 0}, + /* Write the profile header. */ + ProfDataIOVec IOVec[] = {{&Header, sizeof(__llvm_profile_header), 1, 0}}; + if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec))) + return -1; + + /* Write the binary id lengths and data. */ + if (__llvm_write_binary_ids(Writer) == -1) + return -1; + + /* Write the profile data. */ + ProfDataIOVec IOVecData[] = { {DataBegin, sizeof(__llvm_profile_data), DataSize, 0}, {NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1}, {CountersBegin, sizeof(uint64_t), CountersSize, 0}, {NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1}, {SkipNameDataWrite ? NULL : NamesBegin, sizeof(uint8_t), NamesSize, 0}, {NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}}; - if (Writer->Write(Writer, IOVec, sizeof(IOVec) / sizeof(*IOVec))) + if (Writer->Write(Writer, IOVecData, sizeof(IOVecData) / sizeof(*IOVecData))) return -1; /* Value profiling is not yet supported in continuous mode. */ diff --git a/compiler-rt/test/profile/Linux/corrupted-profile.c b/compiler-rt/test/profile/Linux/corrupted-profile.c --- a/compiler-rt/test/profile/Linux/corrupted-profile.c +++ b/compiler-rt/test/profile/Linux/corrupted-profile.c @@ -43,9 +43,9 @@ bail("mmap"); // We're trying to make the first CounterPtr invalid. - // 10 64-bit words as header. + // 11 64-bit words as header. // CounterPtr is the third 64-bit word field. - memset(&Buf[10 * 8 + 2 * 8], 0xAB, 8); + memset(&Buf[11 * 8 + 2 * 8], 0xAB, 8); if (munmap(Buf, FileSize)) bail("munmap"); diff --git a/compiler-rt/test/profile/binary-id.c b/compiler-rt/test/profile/binary-id.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/profile/binary-id.c @@ -0,0 +1,35 @@ +// RUN: %clang_profgen -Wl,--build-id=none -O2 -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show --binary-ids %t.profraw > %t.out +// RUN: FileCheck %s --check-prefix=NO-BINARY-ID < %t.out +// RUN: llvm-profdata merge -o %t.profdata %t.profraw + +// RUN: %clang_profgen -Wl,--build-id -O2 -o %t %s +// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t +// RUN: llvm-profdata show --binary-ids %t.profraw > %t.profraw.out +// RUN: FileCheck %s --check-prefix=BINARY-ID-RAW-PROF < %t.profraw.out + +void foo() { +} + +void bar() { +} + +int main() { + foo(); + bar(); + return 0; +} + +// NO-BINARY-ID: Instrumentation level: Front-end +// NO-BINARY-ID-NEXT: Total functions: 3 +// NO-BINARY-ID-NEXT: Maximum function count: 1 +// NO-BINARY-ID-NEXT: Maximum internal block count: 0 +// NO-BINARY-ID-NOT: Binary IDs: + +// BINARY-ID-RAW-PROF: Instrumentation level: Front-end +// BINARY-ID-RAW-PROF-NEXT: Total functions: 3 +// BINARY-ID-RAW-PROF-NEXT: Maximum function count: 1 +// BINARY-ID-RAW-PROF-NEXT: Maximum internal block count: 0 +// BINARY-ID-RAW-PROF-NEXT: Binary IDs: +// BINARY-ID-RAW-PROF-NEXT: {{[0-9a-f]+}} diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -1103,6 +1103,7 @@ // raw header. // Version 5: Bit 60 of FuncHash is reserved for the flag for the context // sensitive records. +// Version 6: Added binary id. const uint64_t Version = INSTR_PROF_RAW_VERSION; template inline uint64_t getMagic(); diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -137,6 +137,7 @@ INSTR_PROF_RAW_HEADER(uint64_t, CountersDelta, (uintptr_t)CountersBegin) INSTR_PROF_RAW_HEADER(uint64_t, NamesDelta, (uintptr_t)NamesBegin) INSTR_PROF_RAW_HEADER(uint64_t, ValueKindLast, IPVK_Last) +INSTR_PROF_RAW_HEADER(uint64_t, BinaryIdsSize, __llvm_write_binary_ids(NULL)) #undef INSTR_PROF_RAW_HEADER /* INSTR_PROF_RAW_HEADER end */ @@ -645,7 +646,7 @@ (uint64_t)'f' << 16 | (uint64_t)'R' << 8 | (uint64_t)129 /* Raw profile format version (start from 1). */ -#define INSTR_PROF_RAW_VERSION 5 +#define INSTR_PROF_RAW_VERSION 6 /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 7 /* Coverage mapping format version (start from 0). */ diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h --- a/llvm/include/llvm/ProfileData/InstrProfReader.h +++ b/llvm/include/llvm/ProfileData/InstrProfReader.h @@ -82,6 +82,9 @@ /// Read a single record. virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0; + /// Print binary ids on stream OS. + virtual Error printBinaryIds(raw_ostream &OS) { return success(); }; + /// Iterator over profile data. InstrProfIterator begin() { return InstrProfIterator(this); } InstrProfIterator end() { return InstrProfIterator(); } @@ -222,6 +225,9 @@ uint32_t ValueKindLast; uint32_t CurValueDataSize; + uint64_t BinaryIdsSize; + const uint8_t *BinaryIdsStart; + public: RawInstrProfReader(std::unique_ptr DataBuffer) : DataBuffer(std::move(DataBuffer)) {} @@ -231,6 +237,7 @@ static bool hasFormat(const MemoryBuffer &DataBuffer); Error readHeader() override; Error readNextRecord(NamedInstrProfRecord &Record) override; + Error printBinaryIds(raw_ostream &OS) override; bool isIRLevelProfile() const override { return (Version & VARIANT_MASK_IR_PROF) != 0; diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -24,8 +24,8 @@ #include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SymbolRemappingReader.h" #include "llvm/Support/SwapByteOrder.h" +#include "llvm/Support/SymbolRemappingReader.h" #include #include #include @@ -374,11 +374,13 @@ auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters); NamesSize = swap(Header.NamesSize); ValueKindLast = swap(Header.ValueKindLast); + BinaryIdsSize = swap(Header.BinaryIdsSize); auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData); auto PaddingSize = getNumPaddingBytes(NamesSize); - ptrdiff_t DataOffset = sizeof(RawInstrProf::Header); + // Profile data starts after profile header and binary ids if exist. + ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize; ptrdiff_t CountersOffset = DataOffset + DataSizeInBytes + PaddingBytesBeforeCounters; ptrdiff_t NamesOffset = CountersOffset + (sizeof(uint64_t) * CountersSize) + @@ -392,6 +394,10 @@ Data = reinterpret_cast *>( Start + DataOffset); DataEnd = Data + DataSize; + + // Binary ids start just after the header. + BinaryIdsStart = + reinterpret_cast(&Header) + sizeof(RawInstrProf::Header); CountersStart = reinterpret_cast(Start + CountersOffset); NamesStart = Start + NamesOffset; ValueDataStart = reinterpret_cast(Start + ValueDataOffset); @@ -506,6 +512,33 @@ return success(); } +template +Error RawInstrProfReader::printBinaryIds(raw_ostream &OS) { + if (BinaryIdsSize == 0) + return success(); + + OS << "Binary IDs: \n"; + const uint8_t *BI = BinaryIdsStart; + while (BI < BinaryIdsStart + BinaryIdsSize) { + uint64_t BinaryIdLen = swap(*reinterpret_cast(BI)); + // Increment by binary id length data type size. + BI += sizeof(BinaryIdLen); + if (BI > (const uint8_t *)DataBuffer->getBufferEnd()) + return make_error(instrprof_error::malformed); + + for (uint64_t I = 0; I < BinaryIdLen; I++) + OS << format("%02x", BI[I]); + OS << "\n"; + + // Increment by binary id data length. + BI += BinaryIdLen; + if (BI > (const uint8_t *)DataBuffer->getBufferEnd()) + return make_error(instrprof_error::malformed); + } + + return success(); +} + namespace llvm { template class RawInstrProfReader; diff --git a/llvm/test/tools/llvm-profdata/Inputs/c-general.profraw b/llvm/test/tools/llvm-profdata/Inputs/c-general.profraw index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ %t.profraw -RUN: printf '\5\0\0\0\0\0\0\0' >> %t.profraw +RUN: printf '\6\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw RUN: printf '\2\0\0\0\0\0\0\0' >> %t.profraw @@ -19,6 +20,7 @@ RUN: printf '\0\0\6\0\1\0\0\0' >> %t.profraw RUN: printf '\0\0\6\0\2\0\0\0' >> %t.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t.profraw // Data Section // diff --git a/llvm/test/tools/llvm-profdata/raw-32-bits-be.test b/llvm/test/tools/llvm-profdata/raw-32-bits-be.test --- a/llvm/test/tools/llvm-profdata/raw-32-bits-be.test +++ b/llvm/test/tools/llvm-profdata/raw-32-bits-be.test @@ -1,5 +1,5 @@ RUN: printf '\377lprofR\201' > %t -RUN: printf '\0\0\0\0\0\0\0\5' >> %t +RUN: printf '\0\0\0\0\0\0\0\6' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\3' >> %t @@ -8,6 +8,7 @@ RUN: printf '\0\0\0\0\1\0\0\0' >> %t RUN: printf '\0\0\0\0\2\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\134\370\302\114\333\030\275\254' >> %t RUN: printf '\0\0\0\0\0\0\0\1' >> %t diff --git a/llvm/test/tools/llvm-profdata/raw-32-bits-le.test b/llvm/test/tools/llvm-profdata/raw-32-bits-le.test --- a/llvm/test/tools/llvm-profdata/raw-32-bits-le.test +++ b/llvm/test/tools/llvm-profdata/raw-32-bits-le.test @@ -1,5 +1,5 @@ RUN: printf '\201Rforpl\377' > %t -RUN: printf '\5\0\0\0\0\0\0\0' >> %t +RUN: printf '\6\0\0\0\0\0\0\0' >> %t RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0\0\0\0\0' >> %t @@ -8,6 +8,7 @@ RUN: printf '\0\0\0\1\0\0\0\0' >> %t RUN: printf '\0\0\0\2\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\254\275\030\333\114\302\370\134' >> %t RUN: printf '\1\0\0\0\0\0\0\0' >> %t diff --git a/llvm/test/tools/llvm-profdata/raw-64-bits-be.test b/llvm/test/tools/llvm-profdata/raw-64-bits-be.test --- a/llvm/test/tools/llvm-profdata/raw-64-bits-be.test +++ b/llvm/test/tools/llvm-profdata/raw-64-bits-be.test @@ -1,5 +1,5 @@ RUN: printf '\377lprofr\201' > %t -RUN: printf '\0\0\0\0\0\0\0\5' >> %t +RUN: printf '\0\0\0\0\0\0\0\6' >> %t RUN: printf '\0\0\0\0\0\0\0\2' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\3' >> %t @@ -8,6 +8,7 @@ RUN: printf '\0\0\0\1\0\4\0\0' >> %t RUN: printf '\0\0\0\2\0\4\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\134\370\302\114\333\030\275\254' >> %t RUN: printf '\0\0\0\0\0\0\0\1' >> %t diff --git a/llvm/test/tools/llvm-profdata/raw-64-bits-le.test b/llvm/test/tools/llvm-profdata/raw-64-bits-le.test --- a/llvm/test/tools/llvm-profdata/raw-64-bits-le.test +++ b/llvm/test/tools/llvm-profdata/raw-64-bits-le.test @@ -1,5 +1,5 @@ RUN: printf '\201rforpl\377' > %t -RUN: printf '\5\0\0\0\0\0\0\0' >> %t +RUN: printf '\6\0\0\0\0\0\0\0' >> %t RUN: printf '\2\0\0\0\0\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\3\0\0\0\0\0\0\0' >> %t @@ -8,6 +8,7 @@ RUN: printf '\0\0\4\0\1\0\0\0' >> %t RUN: printf '\0\0\4\0\2\0\0\0' >> %t RUN: printf '\0\0\0\0\0\0\0\0' >> %t +RUN: printf '\0\0\0\0\0\0\0\0' >> %t RUN: printf '\254\275\030\333\114\302\370\134' >> %t RUN: printf '\1\0\0\0\0\0\0\0' >> %t diff --git a/llvm/test/tools/llvm-profdata/raw-two-profiles.test b/llvm/test/tools/llvm-profdata/raw-two-profiles.test --- a/llvm/test/tools/llvm-profdata/raw-two-profiles.test +++ b/llvm/test/tools/llvm-profdata/raw-two-profiles.test @@ -1,5 +1,5 @@ RUN: printf '\201rforpl\377' > %t-foo.profraw -RUN: printf '\5\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\6\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw @@ -8,6 +8,7 @@ RUN: printf '\0\0\4\0\1\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\4\0\2\0\0\0' >> %t-foo.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-foo.profraw RUN: printf '\254\275\030\333\114\302\370\134' >> %t-foo.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-foo.profraw @@ -20,7 +21,7 @@ RUN: printf '\3\0foo\0\0\0' >> %t-foo.profraw RUN: printf '\201rforpl\377' > %t-bar.profraw -RUN: printf '\5\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\6\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\1\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\2\0\0\0\0\0\0\0' >> %t-bar.profraw @@ -29,6 +30,7 @@ RUN: printf '\0\0\6\0\1\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\6\0\2\0\0\0' >> %t-bar.profraw RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw +RUN: printf '\0\0\0\0\0\0\0\0' >> %t-bar.profraw RUN: printf '\067\265\035\031\112\165\023\344' >> %t-bar.profraw RUN: printf '\02\0\0\0\0\0\0\0' >> %t-bar.profraw diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -2069,7 +2069,7 @@ bool ShowAllFunctions, bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow, const std::string &ShowFunction, bool TextFormat, - raw_fd_ostream &OS) { + bool ShowBinaryIds, raw_fd_ostream &OS) { auto ReaderOrErr = InstrProfReader::create(Filename); std::vector Cutoffs = std::move(DetailedSummaryCutoffs); if (ShowDetailedSummary && Cutoffs.empty()) { @@ -2251,6 +2251,11 @@ OS << "Total count: " << PS->getTotalCount() << "\n"; PS->printDetailedSummary(OS); } + + if (ShowBinaryIds) + if (Error E = Reader->printBinaryIds(OS)) + exitWithError(std::move(E), Filename); + return 0; } @@ -2501,6 +2506,8 @@ cl::desc("Show the information of each section in the sample profile. " "The flag is only usable when the sample profile is in " "extbinary format")); + cl::opt ShowBinaryIds("binary-ids", cl::init(false), + cl::desc("Show binary ids in the profile. ")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); @@ -2519,11 +2526,11 @@ WithColor::warning() << "-function argument ignored: showing all functions\n"; if (ProfileKind == instr) - return showInstrProfile(Filename, ShowCounts, TopNFunctions, - ShowIndirectCallTargets, ShowMemOPSizes, - ShowDetailedSummary, DetailedSummaryCutoffs, - ShowAllFunctions, ShowCS, ValueCutoff, - OnlyListBelow, ShowFunction, TextFormat, OS); + return showInstrProfile( + Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets, + ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs, + ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction, + TextFormat, ShowBinaryIds, OS); else return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, ShowDetailedSummary, ShowFunction,