[profile] Add binary id into profiles

This patch adds binary id into profiles to easily associate binaries
with the corresponding profiles. There is an RFC that discusses
the motivation, design and implementation in more detail:
https://lists.llvm.org/pipermail/llvm-dev/2021-June/151154.html

Differential Revision: https://reviews.llvm.org/D102039
This commit is contained in:
Gulfem Savrun Yeniceri
2021-05-06 16:09:12 +00:00
parent 6ba493d81b
commit f984ac2715
21 changed files with 260 additions and 24 deletions

View File

@@ -137,6 +137,7 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
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 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
(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). */

View File

@@ -23,4 +23,23 @@ COMPILER_RT_VISIBILITY void lprofSetProfileDumped(unsigned Value) {
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

View File

@@ -193,4 +193,11 @@ COMPILER_RT_VISIBILITY extern ValueProfNode *CurrentVNode;
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

View File

@@ -9,9 +9,13 @@
#if defined(__linux__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \
(defined(__sun__) && defined(__svr4__)) || defined(__NetBSD__)
#include <elf.h>
#include <link.h>
#include <stdlib.h>
#include <string.h>
#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 *__llvm_profile_end_vnodes(void) {
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

View File

@@ -283,16 +283,24 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
#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. */

View File

@@ -43,9 +43,9 @@ int main(int argc, char** argv) {
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");

View File

@@ -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]+}}

View File

@@ -1103,6 +1103,7 @@ namespace RawInstrProf {
// 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 <class IntPtrT> inline uint64_t getMagic();

View File

@@ -137,6 +137,7 @@ INSTR_PROF_RAW_HEADER(uint64_t, NamesSize, NamesSize)
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 @@ serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
(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). */

View File

@@ -82,6 +82,9 @@ public:
/// 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 @@ private:
uint32_t ValueKindLast;
uint32_t CurValueDataSize;
uint64_t BinaryIdsSize;
const uint8_t *BinaryIdsStart;
public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
: DataBuffer(std::move(DataBuffer)) {}
@@ -231,6 +237,7 @@ public:
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;

View File

@@ -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 <algorithm>
#include <cctype>
#include <cstddef>
@@ -374,11 +374,13 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
NamesSize = swap(Header.NamesSize);
ValueKindLast = swap(Header.ValueKindLast);
BinaryIdsSize = swap(Header.BinaryIdsSize);
auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
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 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
Start + DataOffset);
DataEnd = Data + DataSize;
// Binary ids start just after the header.
BinaryIdsStart =
reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
NamesStart = Start + NamesOffset;
ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
@@ -506,6 +512,33 @@ Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record)
return success();
}
template <class IntPtrT>
Error RawInstrProfReader<IntPtrT>::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<const uint64_t *>(BI));
// Increment by binary id length data type size.
BI += sizeof(BinaryIdLen);
if (BI > (const uint8_t *)DataBuffer->getBufferEnd())
return make_error<InstrProfError>(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<InstrProfError>(instrprof_error::malformed);
}
return success();
}
namespace llvm {
template class RawInstrProfReader<uint32_t>;

View File

@@ -14,7 +14,7 @@ RUN: llvm-profdata show %p/Inputs/c-general.profraw -o - --function=switches | F
SWITCHES-LABEL: Counters:
SWITCHES-NEXT: switches:
SWITCHES-NEXT: Hash: 0xa50a07f391ae4be5
SWITCHES-NEXT: Hash: 0x0099a0c98383683e
SWITCHES-NEXT: Counters: 19
SWITCHES-NEXT: Function count: 1
SWITCHES-LABEL: Functions shown: 1

View File

@@ -8,9 +8,10 @@
// 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))
RUN: printf '\201rforpl\377' > %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 '\10\0\0\0\0\0\0\0' >> %t.profraw
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
//

View File

@@ -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\0\0\0\20' >> %t
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

View File

@@ -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 '\20\0\0\0\0\0\0\0' >> %t
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

View File

@@ -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\0\0\0\20' >> %t
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

View File

@@ -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 '\20\0\0\0\0\0\0\0' >> %t
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

View File

@@ -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 '\10\0\0\0\0\0\0\0' >> %t-foo.profraw
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 '\023\0\0\0\0\0\0\0' >> %t-foo.profraw
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 '\10\0\0\0\0\0\0\0' >> %t-bar.profraw
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

View File

@@ -2069,7 +2069,7 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
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<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
if (ShowDetailedSummary && Cutoffs.empty()) {
@@ -2251,6 +2251,11 @@ static int showInstrProfile(const std::string &Filename, bool ShowCounts,
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 @@ static int show_main(int argc, const char *argv[]) {
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<bool> 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 @@ static int show_main(int argc, const char *argv[]) {
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,