41 #include <system_error>
45 using namespace sampleprof;
53 OS <<
"Function: " << FName <<
": " <<
Profiles[FName];
70 uint64_t &NumSamples, uint64_t &NumHeadSamples) {
73 size_t n2 = Input.
rfind(
':');
74 size_t n1 = Input.
rfind(
':', n2 - 1);
75 FName = Input.
substr(0, n1);
118 uint64_t &NumSamples,
uint32_t &LineOffset,
121 uint64_t &FunctionHash) {
132 size_t n1 = Input.
find(
':');
134 size_t n2 = Loc.
find(
'.');
147 if (isDigit(Rest[0])) {
149 size_t n3 = Rest.
find(
' ');
199 if (n4 == Rest.
size())
207 CalleeName = Rest.
substr(0, n3);
229 bool SeenMetadata =
false;
232 if ((*LineIt)[(*LineIt).find_first_not_of(
' ')] ==
'#')
246 if ((*LineIt)[0] !=
' ') {
247 uint64_t NumSamples, NumHeadSamples;
249 if (!
ParseHead(*LineIt, FName, NumSamples, NumHeadSamples)) {
251 "Expected 'mangled_name:NUM:NUM', found " + *LineIt);
254 SeenMetadata =
false;
265 InlineStack.push_back(&FProfile);
272 uint64_t FunctionHash;
274 Discriminator, FName, TargetCountMap, FunctionHash)) {
276 "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " +
283 "Found non-metadata after metadata: " + *LineIt);
286 while (InlineStack.size() >
Depth) {
287 InlineStack.pop_back();
292 LineLocation(LineOffset, Discriminator))[std::string(FName)];
295 InlineStack.push_back(&FSamples);
299 while (InlineStack.size() >
Depth) {
300 InlineStack.pop_back();
303 for (
const auto &name_count : TargetCountMap) {
305 LineOffset, Discriminator, name_count.first,
324 "Cannot have both context-sensitive and regular profile");
326 assert((ProbeProfileCount == 0 || ProbeProfileCount ==
Profiles.size()) &&
327 "Cannot have both probe-based profiles and regular profiles");
344 if ((*LineIt)[0] !=
' ') {
345 uint64_t NumSamples, NumHeadSamples;
355 unsigned NumBytesRead = 0;
361 else if (
Data + NumBytesRead >
End)
371 Data += NumBytesRead;
372 return static_cast<T>(Val);
388 template <
typename T>
399 T Val = endian::readNext<T, little, unaligned>(
Data);
403 template <
typename T>
406 auto Idx = readNumber<uint32_t>();
407 if (std::error_code EC = Idx.getError())
409 if (*Idx >= Table.size())
416 if (std::error_code EC = Idx.getError())
428 if (std::error_code EC = Idx.getError())
435 const uint8_t *SavedData =
Data;
436 Data = MD5NameMemStart + ((*Idx) *
sizeof(uint64_t));
437 auto FID = readUnencodedNumber<uint64_t>();
438 if (std::error_code EC = FID.getError())
444 SR = MD5StringBuf->
back();
452 if (std::error_code EC = Idx.getError())
460 auto NumSamples = readNumber<uint64_t>();
461 if (std::error_code EC = NumSamples.getError())
466 auto NumRecords = readNumber<uint32_t>();
467 if (std::error_code EC = NumRecords.getError())
471 auto LineOffset = readNumber<uint64_t>();
472 if (std::error_code EC = LineOffset.getError())
476 return std::error_code();
479 auto Discriminator = readNumber<uint64_t>();
480 if (std::error_code EC = Discriminator.getError())
483 auto NumSamples = readNumber<uint64_t>();
484 if (std::error_code EC = NumSamples.getError())
487 auto NumCalls = readNumber<uint32_t>();
488 if (std::error_code EC = NumCalls.getError())
491 for (
uint32_t J = 0; J < *NumCalls; ++J) {
493 if (std::error_code EC = CalledFunction.getError())
496 auto CalledFunctionSamples = readNumber<uint64_t>();
497 if (std::error_code EC = CalledFunctionSamples.getError())
501 *CalledFunction, *CalledFunctionSamples);
504 FProfile.
addBodySamples(*LineOffset, *Discriminator, *NumSamples);
508 auto NumCallsites = readNumber<uint32_t>();
509 if (std::error_code EC = NumCallsites.getError())
512 for (
uint32_t J = 0; J < *NumCallsites; ++J) {
513 auto LineOffset = readNumber<uint64_t>();
514 if (std::error_code EC = LineOffset.getError())
517 auto Discriminator = readNumber<uint64_t>();
518 if (std::error_code EC = Discriminator.getError())
522 if (std::error_code EC = FName.getError())
526 LineLocation(*LineOffset, *Discriminator))[std::string(*FName)];
528 if (std::error_code EC =
readProfile(CalleeProfile))
538 auto NumHeadSamples = readNumber<uint64_t>();
539 if (std::error_code EC = NumHeadSamples.getError())
543 if (std::error_code EC = FName.getError())
574 switch (Entry.Type) {
579 Summary->setPartialProfile(
true);
585 assert((!FixedLengthMD5 || UseMD5) &&
586 "If FixedLengthMD5 is true, UseMD5 has to be true");
587 if (std::error_code EC = readNameTableSec(UseMD5))
592 if (std::error_code EC = readFuncProfiles())
596 if (std::error_code EC = readFuncOffsetTable())
603 if (std::error_code EC = readFuncMetadata())
607 if (std::error_code EC = readProfileSymbolList())
611 if (std::error_code EC = readCustomSection(Entry))
629 FuncOffsetTable.clear();
631 auto Size = readNumber<uint64_t>();
632 if (std::error_code EC =
Size.getError())
635 FuncOffsetTable.reserve(*
Size);
638 if (std::error_code EC = FName.getError())
641 auto Offset = readNumber<uint64_t>();
642 if (std::error_code EC =
Offset.getError())
645 FuncOffsetTable[*FName] = *
Offset;
651 const uint8_t *Start =
Data;
660 for (
auto Name : FuncsToUse) {
666 for (
auto Name : FuncsToUse) {
668 auto iter = FuncOffsetTable.find(
StringRef(GUID));
669 if (iter == FuncOffsetTable.end())
671 const uint8_t *FuncProfileAddr = Start + iter->second;
672 assert(FuncProfileAddr <
End &&
"out of LBRProfile section");
677 for (
auto NameOffset : FuncOffsetTable) {
680 if (!FuncsToUse.count(FuncName) &&
683 const uint8_t *FuncProfileAddr = Start + NameOffset.second;
684 assert(FuncProfileAddr <
End &&
"out of LBRProfile section");
693 "Cannot have both context-sensitive and regular profile");
701 ProfSymList = std::make_unique<ProfileSymbolList>();
703 if (std::error_code EC = ProfSymList->read(
Data,
End -
Data))
710 std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
711 const uint8_t *SecStart,
const uint64_t SecSize,
712 const uint8_t *&DecompressBuf, uint64_t &DecompressBufSize) {
714 End = SecStart + SecSize;
715 auto DecompressSize = readNumber<uint64_t>();
716 if (std::error_code EC = DecompressSize.getError())
718 DecompressBufSize = *DecompressSize;
720 auto CompressSize = readNumber<uint64_t>();
721 if (std::error_code EC = CompressSize.getError())
727 StringRef CompressedStrings(
reinterpret_cast<const char *
>(
Data),
730 size_t UCSize = DecompressBufSize;
735 DecompressBuf =
reinterpret_cast<const uint8_t *
>(
Buffer);
740 const uint8_t *BufStart =
741 reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart());
743 for (
auto &Entry : SecHdrTable) {
752 const uint8_t *SecStart = BufStart + Entry.Offset;
753 uint64_t SecSize = Entry.Size;
761 const uint8_t *DecompressBuf;
762 uint64_t DecompressBufSize;
763 if (std::error_code EC = decompressSection(
764 SecStart, SecSize, DecompressBuf, DecompressBufSize))
766 SecStart = DecompressBuf;
767 SecSize = DecompressBufSize;
770 if (std::error_code EC = readOneSection(SecStart, SecSize, Entry))
772 if (
Data != SecStart + SecSize)
777 Data = BufStart + Entry.Offset;
778 End = BufStart +
Buffer->getBufferSize();
786 std::vector<uint64_t> OffsetsToUse;
788 for (
auto FuncEntry : FuncOffsetTable) {
789 OffsetsToUse.push_back(FuncEntry.second);
793 for (
auto Name : FuncsToUse) {
795 auto iter = FuncOffsetTable.find(
StringRef(GUID));
796 if (iter == FuncOffsetTable.end())
798 OffsetsToUse.push_back(iter->second);
802 for (
auto Offset : OffsetsToUse) {
803 const uint8_t *SavedData =
Data;
805 reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart()) +
813 std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t
Magic) {
819 std::error_code SampleProfileReaderExtBinary::verifySPMagic(uint64_t
Magic) {
826 SampleProfileReaderCompactBinary::verifySPMagic(uint64_t
Magic) {
833 auto Size = readNumber<uint32_t>();
834 if (std::error_code EC =
Size.getError())
839 if (std::error_code EC =
Name.getError())
848 auto Size = readNumber<uint64_t>();
849 if (std::error_code EC =
Size.getError())
851 MD5StringBuf = std::make_unique<std::vector<std::string>>();
852 MD5StringBuf->reserve(*
Size);
853 if (FixedLengthMD5) {
860 MD5NameMemStart =
Data;
861 Data =
Data + (*Size) *
sizeof(uint64_t);
866 auto FID = readNumber<uint64_t>();
867 if (std::error_code EC = FID.getError())
872 NameTable.push_back(MD5StringBuf->back());
879 return readMD5NameTable();
888 if (std::error_code EC = FName.getError())
891 auto Checksum = readNumber<uint64_t>();
892 if (std::error_code EC = Checksum.getError())
899 Profiles[FContext].setFunctionHash(*Checksum);
906 std::error_code SampleProfileReaderCompactBinary::readNameTable() {
907 auto Size = readNumber<uint64_t>();
908 if (std::error_code EC =
Size.getError())
912 auto FID = readNumber<uint64_t>();
913 if (std::error_code EC = FID.getError())
923 auto Type = readUnencodedNumber<uint64_t>();
924 if (std::error_code EC =
Type.getError())
926 Entry.Type =
static_cast<SecType>(*Type);
928 auto Flags = readUnencodedNumber<uint64_t>();
929 if (std::error_code EC = Flags.getError())
931 Entry.Flags = *Flags;
933 auto Offset = readUnencodedNumber<uint64_t>();
934 if (std::error_code EC =
Offset.getError())
938 auto Size = readUnencodedNumber<uint64_t>();
939 if (std::error_code EC =
Size.getError())
943 Entry.LayoutIndex = Idx;
949 auto EntryNum = readUnencodedNumber<uint64_t>();
950 if (std::error_code EC = EntryNum.getError())
954 if (std::error_code EC = readSecHdrTableEntry(
i))
961 const uint8_t *BufStart =
962 reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart());
964 End = BufStart +
Buffer->getBufferSize();
969 if (std::error_code EC = readSecHdrTable())
977 for (
auto &Entry : SecHdrTable) {
978 if (Entry.Type ==
Type)
990 uint64_t FileSize = 0;
991 for (
auto &Entry : SecHdrTable) {
992 FileSize =
std::max(Entry.Offset + Entry.Size, FileSize);
1000 Flags.append(
"{compressed,");
1005 Flags.append(
"flat,");
1007 switch (Entry.Type) {
1010 Flags.append(
"fixlenmd5,");
1012 Flags.append(
"md5,");
1016 Flags.append(
"partial,");
1021 char &last = Flags.back();
1030 uint64_t TotalSecsSize = 0;
1031 for (
auto &Entry : SecHdrTable) {
1032 OS <<
getSecName(Entry.Type) <<
" - Offset: " << Entry.Offset
1033 <<
", Size: " << Entry.Size <<
", Flags: " <<
getSecFlagsStr(Entry)
1036 TotalSecsSize += Entry.Size;
1038 uint64_t
HeaderSize = SecHdrTable.front().Offset;
1040 "Size of 'header + sections' doesn't match the total size of profile");
1043 OS <<
"Total Sections Size: " << TotalSecsSize <<
"\n";
1044 OS <<
"File Size: " << getFileSize() <<
"\n";
1050 auto Magic = readNumber<uint64_t>();
1051 if (std::error_code EC =
Magic.getError())
1053 else if (std::error_code EC = verifySPMagic(*
Magic))
1057 auto Version = readNumber<uint64_t>();
1058 if (std::error_code EC =
Version.getError())
1067 Data =
reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart());
1081 std::error_code SampleProfileReaderCompactBinary::readHeader() {
1083 if (std::error_code EC = readFuncOffsetTable())
1088 std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() {
1089 auto TableOffset = readUnencodedNumber<uint64_t>();
1090 if (std::error_code EC = TableOffset.getError())
1093 const uint8_t *SavedData =
Data;
1094 const uint8_t *TableStart =
1095 reinterpret_cast<const uint8_t *
>(
Buffer->getBufferStart()) +
1099 auto Size = readNumber<uint64_t>();
1100 if (std::error_code EC =
Size.getError())
1103 FuncOffsetTable.reserve(*
Size);
1106 if (std::error_code EC = FName.getError())
1109 auto Offset = readNumber<uint64_t>();
1110 if (std::error_code EC =
Offset.getError())
1113 FuncOffsetTable[*FName] = *
Offset;
1121 UseAllFuncs =
false;
1127 std::error_code SampleProfileReaderBinary::readSummaryEntry(
1128 std::vector<ProfileSummaryEntry> &Entries) {
1129 auto Cutoff = readNumber<uint64_t>();
1130 if (std::error_code EC = Cutoff.getError())
1133 auto MinBlockCount = readNumber<uint64_t>();
1134 if (std::error_code EC = MinBlockCount.getError())
1137 auto NumBlocks = readNumber<uint64_t>();
1138 if (std::error_code EC = NumBlocks.getError())
1141 Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
1146 auto TotalCount = readNumber<uint64_t>();
1147 if (std::error_code EC = TotalCount.getError())
1150 auto MaxBlockCount = readNumber<uint64_t>();
1151 if (std::error_code EC = MaxBlockCount.getError())
1154 auto MaxFunctionCount = readNumber<uint64_t>();
1155 if (std::error_code EC = MaxFunctionCount.getError())
1158 auto NumBlocks = readNumber<uint64_t>();
1159 if (std::error_code EC = NumBlocks.getError())
1162 auto NumFunctions = readNumber<uint64_t>();
1163 if (std::error_code EC = NumFunctions.getError())
1166 auto NumSummaryEntries = readNumber<uint64_t>();
1167 if (std::error_code EC = NumSummaryEntries.getError())
1170 std::vector<ProfileSummaryEntry> Entries;
1171 for (
unsigned i = 0;
i < *NumSummaryEntries;
i++) {
1172 std::error_code EC = readSummaryEntry(Entries);
1176 Summary = std::make_unique<ProfileSummary>(
1178 *MaxFunctionCount, *NumBlocks, *NumFunctions);
1184 const uint8_t *
Data =
1185 reinterpret_cast<const uint8_t *
>(
Buffer.getBufferStart());
1191 const uint8_t *
Data =
1192 reinterpret_cast<const uint8_t *
>(
Buffer.getBufferStart());
1198 const uint8_t *
Data =
1199 reinterpret_cast<const uint8_t *
>(
Buffer.getBufferStart());
1206 if (!GcovBuffer.readInt(dummy))
1215 return static_cast<T>(Val);
1216 }
else if (
sizeof(
T) <=
sizeof(uint64_t)) {
1219 return static_cast<T>(Val);
1229 if (!GcovBuffer.readString(Str))
1236 if (!GcovBuffer.readGCDAFormat())
1242 if (!GcovBuffer.readGCOVVersion(version))
1249 if (std::error_code EC = skipNextWord())
1257 if (!GcovBuffer.readInt(Tag))
1263 if (std::error_code EC = skipNextWord())
1270 if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
1274 if (!GcovBuffer.readInt(
Size))
1279 if (!GcovBuffer.readString(Str))
1281 Names.push_back(std::string(Str));
1288 if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
1292 if (!GcovBuffer.readInt(NumFunctions))
1297 if (std::error_code EC = readOneFunctionProfile(Stack,
true, 0))
1306 uint64_t HeadCount = 0;
1307 if (InlineStack.size() == 0)
1308 if (!GcovBuffer.readInt64(HeadCount))
1312 if (!GcovBuffer.readInt(NameIdx))
1318 if (!GcovBuffer.readInt(NumPosCounts))
1322 if (!GcovBuffer.readInt(NumCallsites))
1326 if (InlineStack.size() == 0) {
1351 if (!GcovBuffer.readInt(
Offset))
1355 if (!GcovBuffer.readInt(NumTargets))
1359 if (!GcovBuffer.readInt64(Count))
1369 NewStack.push_back(FProfile);
1374 for (
auto CallerProfile : NewStack)
1375 CallerProfile->addTotalSamples(Count);
1384 for (
uint32_t J = 0; J < NumTargets; J++) {
1386 if (!GcovBuffer.readInt(HistVal))
1393 if (!GcovBuffer.readInt64(TargetIdx))
1397 uint64_t TargetCount;
1398 if (!GcovBuffer.readInt64(TargetCount))
1403 TargetName, TargetCount);
1414 if (!GcovBuffer.readInt(
Offset))
1417 NewStack.push_back(FProfile);
1419 if (std::error_code EC = readOneFunctionProfile(NewStack, Update,
Offset))
1436 if (std::error_code EC = readFunctionProfiles())
1444 return Magic ==
"adcg*704";
1450 if (Reader.useMD5()) {
1452 Reader.getBuffer()->getBufferIdentifier(),
1453 "Profile data remapping cannot be applied to profile data "
1454 "in compact format (original mangled names are not available).",
1461 assert(Remappings &&
"should be initialized while creating remapper");
1462 for (
auto &Sample : Reader.getProfiles()) {
1464 Sample.second.findAllNames(NamesInSample);
1465 for (
auto &
Name : NamesInSample)
1466 if (
auto Key = Remappings->insert(
Name))
1470 RemappingApplied =
true;
1475 if (
auto Key = Remappings->lookup(Fname))
1476 return NameMap.lookup(
Key);
1486 if (std::error_code EC = BufferOrErr.getError())
1508 const std::string RemapFilename) {
1510 if (std::error_code EC = BufferOrError.getError())
1512 return create(BufferOrError.get(),
C, RemapFilename);
1530 if (std::error_code EC = BufferOrError.getError())
1532 return create(BufferOrError.get(), Reader,
C);
1549 auto Remappings = std::make_unique<SymbolRemappingReader>();
1550 if (
Error E = Remappings->read(*
B.get())) {
1560 return std::make_unique<SampleProfileReaderItaniumRemapper>(
1575 const std::string RemapFilename) {
1576 std::unique_ptr<SampleProfileReader> Reader;
1590 if (!RemapFilename.empty()) {
1593 if (std::error_code EC = ReaderOrErr.getError()) {
1594 std::string Msg =
"Could not create remapper: " + EC.message();
1598 Reader->Remapper =
std::move(ReaderOrErr.get());
1602 if (std::error_code EC = Reader->readHeader()) {