xref: /freebsd/contrib/llvm-project/llvm/lib/ProfileData/InstrProfReader.cpp (revision 5f4c09dd85bff675e0ca63c55ea3c517e0fddfcc)
1 //===- InstrProfReader.cpp - Instrumented profiling reader ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for reading profiling data for clang's
10 // instrumentation based PGO and coverage.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ProfileData/InstrProfReader.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/IR/ProfileSummary.h"
20 #include "llvm/ProfileData/InstrProf.h"
21 #include "llvm/ProfileData/MemProf.h"
22 #include "llvm/ProfileData/ProfileCommon.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include "llvm/Support/ErrorOr.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/SwapByteOrder.h"
28 #include "llvm/Support/SymbolRemappingReader.h"
29 #include <algorithm>
30 #include <cstddef>
31 #include <cstdint>
32 #include <limits>
33 #include <memory>
34 #include <system_error>
35 #include <utility>
36 #include <vector>
37 
38 using namespace llvm;
39 
40 // Extracts the variant information from the top 8 bits in the version and
41 // returns an enum specifying the variants present.
42 static InstrProfKind getProfileKindFromVersion(uint64_t Version) {
43   InstrProfKind ProfileKind = InstrProfKind::Unknown;
44   if (Version & VARIANT_MASK_IR_PROF) {
45     ProfileKind |= InstrProfKind::IRInstrumentation;
46   }
47   if (Version & VARIANT_MASK_CSIR_PROF) {
48     ProfileKind |= InstrProfKind::ContextSensitive;
49   }
50   if (Version & VARIANT_MASK_INSTR_ENTRY) {
51     ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
52   }
53   if (Version & VARIANT_MASK_BYTE_COVERAGE) {
54     ProfileKind |= InstrProfKind::SingleByteCoverage;
55   }
56   if (Version & VARIANT_MASK_FUNCTION_ENTRY_ONLY) {
57     ProfileKind |= InstrProfKind::FunctionEntryOnly;
58   }
59   if (Version & VARIANT_MASK_MEMPROF) {
60     ProfileKind |= InstrProfKind::MemProf;
61   }
62   return ProfileKind;
63 }
64 
65 static Expected<std::unique_ptr<MemoryBuffer>>
66 setupMemoryBuffer(const Twine &Path) {
67   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
68       MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/true);
69   if (std::error_code EC = BufferOrErr.getError())
70     return errorCodeToError(EC);
71   return std::move(BufferOrErr.get());
72 }
73 
74 static Error initializeReader(InstrProfReader &Reader) {
75   return Reader.readHeader();
76 }
77 
78 /// Read a list of binary ids from a profile that consist of
79 /// a. uint64_t binary id length
80 /// b. uint8_t  binary id data
81 /// c. uint8_t  padding (if necessary)
82 /// This function is shared between raw and indexed profiles.
83 /// Raw profiles are in host-endian format, and indexed profiles are in
84 /// little-endian format. So, this function takes an argument indicating the
85 /// associated endian format to read the binary ids correctly.
86 static Error
87 readBinaryIdsInternal(const MemoryBuffer &DataBuffer,
88                       const uint64_t BinaryIdsSize,
89                       const uint8_t *BinaryIdsStart,
90                       std::vector<llvm::object::BuildID> &BinaryIds,
91                       const llvm::support::endianness Endian) {
92   using namespace support;
93 
94   if (BinaryIdsSize == 0)
95     return Error::success();
96 
97   const uint8_t *BI = BinaryIdsStart;
98   const uint8_t *BIEnd = BinaryIdsStart + BinaryIdsSize;
99   const uint8_t *End =
100       reinterpret_cast<const uint8_t *>(DataBuffer.getBufferEnd());
101 
102   while (BI < BIEnd) {
103     size_t Remaining = BIEnd - BI;
104     // There should be enough left to read the binary id length.
105     if (Remaining < sizeof(uint64_t))
106       return make_error<InstrProfError>(
107           instrprof_error::malformed,
108           "not enough data to read binary id length");
109 
110     uint64_t BILen = 0;
111     if (Endian == little)
112       BILen = endian::readNext<uint64_t, little, unaligned>(BI);
113     else
114       BILen = endian::readNext<uint64_t, big, unaligned>(BI);
115 
116     if (BILen == 0)
117       return make_error<InstrProfError>(instrprof_error::malformed,
118                                         "binary id length is 0");
119 
120     Remaining = BIEnd - BI;
121     // There should be enough left to read the binary id data.
122     if (Remaining < alignToPowerOf2(BILen, sizeof(uint64_t)))
123       return make_error<InstrProfError>(
124           instrprof_error::malformed, "not enough data to read binary id data");
125 
126     // Add binary id to the binary ids list.
127     BinaryIds.push_back(object::BuildID(BI, BI + BILen));
128 
129     // Increment by binary id data length, which aligned to the size of uint64.
130     BI += alignToPowerOf2(BILen, sizeof(uint64_t));
131     if (BI > End)
132       return make_error<InstrProfError>(
133           instrprof_error::malformed,
134           "binary id section is greater than buffer size");
135   }
136 
137   return Error::success();
138 }
139 
140 static Error printBinaryIdsInternal(raw_ostream &OS,
141                                     const MemoryBuffer &DataBuffer,
142                                     uint64_t BinaryIdsSize,
143                                     const uint8_t *BinaryIdsStart,
144                                     llvm::support::endianness Endian) {
145   if (BinaryIdsSize == 0)
146     return Error::success();
147 
148   std::vector<llvm::object::BuildID> BinaryIds;
149   if (Error E = readBinaryIdsInternal(DataBuffer, BinaryIdsSize, BinaryIdsStart,
150                                       BinaryIds, Endian))
151     return E;
152 
153   OS << "Binary IDs: \n";
154   for (auto BI : BinaryIds) {
155     for (uint64_t I = 0; I < BI.size(); I++)
156       OS << format("%02x", BI[I]);
157     OS << "\n";
158   }
159 
160   return Error::success();
161 }
162 
163 Expected<std::unique_ptr<InstrProfReader>>
164 InstrProfReader::create(const Twine &Path,
165                         const InstrProfCorrelator *Correlator) {
166   // Set up the buffer to read.
167   auto BufferOrError = setupMemoryBuffer(Path);
168   if (Error E = BufferOrError.takeError())
169     return std::move(E);
170   return InstrProfReader::create(std::move(BufferOrError.get()), Correlator);
171 }
172 
173 Expected<std::unique_ptr<InstrProfReader>>
174 InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
175                         const InstrProfCorrelator *Correlator) {
176   // Sanity check the buffer.
177   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
178     return make_error<InstrProfError>(instrprof_error::too_large);
179 
180   if (Buffer->getBufferSize() == 0)
181     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
182 
183   std::unique_ptr<InstrProfReader> Result;
184   // Create the reader.
185   if (IndexedInstrProfReader::hasFormat(*Buffer))
186     Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
187   else if (RawInstrProfReader64::hasFormat(*Buffer))
188     Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator));
189   else if (RawInstrProfReader32::hasFormat(*Buffer))
190     Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator));
191   else if (TextInstrProfReader::hasFormat(*Buffer))
192     Result.reset(new TextInstrProfReader(std::move(Buffer)));
193   else
194     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
195 
196   // Initialize the reader and return the result.
197   if (Error E = initializeReader(*Result))
198     return std::move(E);
199 
200   return std::move(Result);
201 }
202 
203 Expected<std::unique_ptr<IndexedInstrProfReader>>
204 IndexedInstrProfReader::create(const Twine &Path, const Twine &RemappingPath) {
205   // Set up the buffer to read.
206   auto BufferOrError = setupMemoryBuffer(Path);
207   if (Error E = BufferOrError.takeError())
208     return std::move(E);
209 
210   // Set up the remapping buffer if requested.
211   std::unique_ptr<MemoryBuffer> RemappingBuffer;
212   std::string RemappingPathStr = RemappingPath.str();
213   if (!RemappingPathStr.empty()) {
214     auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr);
215     if (Error E = RemappingBufferOrError.takeError())
216       return std::move(E);
217     RemappingBuffer = std::move(RemappingBufferOrError.get());
218   }
219 
220   return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
221                                         std::move(RemappingBuffer));
222 }
223 
224 Expected<std::unique_ptr<IndexedInstrProfReader>>
225 IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
226                                std::unique_ptr<MemoryBuffer> RemappingBuffer) {
227   if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
228     return make_error<InstrProfError>(instrprof_error::too_large);
229 
230   // Create the reader.
231   if (!IndexedInstrProfReader::hasFormat(*Buffer))
232     return make_error<InstrProfError>(instrprof_error::bad_magic);
233   auto Result = std::make_unique<IndexedInstrProfReader>(
234       std::move(Buffer), std::move(RemappingBuffer));
235 
236   // Initialize the reader and return the result.
237   if (Error E = initializeReader(*Result))
238     return std::move(E);
239 
240   return std::move(Result);
241 }
242 
243 bool TextInstrProfReader::hasFormat(const MemoryBuffer &Buffer) {
244   // Verify that this really looks like plain ASCII text by checking a
245   // 'reasonable' number of characters (up to profile magic size).
246   size_t count = std::min(Buffer.getBufferSize(), sizeof(uint64_t));
247   StringRef buffer = Buffer.getBufferStart();
248   return count == 0 ||
249          std::all_of(buffer.begin(), buffer.begin() + count,
250                      [](char c) { return isPrint(c) || isSpace(c); });
251 }
252 
253 // Read the profile variant flag from the header: ":FE" means this is a FE
254 // generated profile. ":IR" means this is an IR level profile. Other strings
255 // with a leading ':' will be reported an error format.
256 Error TextInstrProfReader::readHeader() {
257   Symtab.reset(new InstrProfSymtab());
258 
259   while (Line->startswith(":")) {
260     StringRef Str = Line->substr(1);
261     if (Str.equals_insensitive("ir"))
262       ProfileKind |= InstrProfKind::IRInstrumentation;
263     else if (Str.equals_insensitive("fe"))
264       ProfileKind |= InstrProfKind::FrontendInstrumentation;
265     else if (Str.equals_insensitive("csir")) {
266       ProfileKind |= InstrProfKind::IRInstrumentation;
267       ProfileKind |= InstrProfKind::ContextSensitive;
268     } else if (Str.equals_insensitive("entry_first"))
269       ProfileKind |= InstrProfKind::FunctionEntryInstrumentation;
270     else if (Str.equals_insensitive("not_entry_first"))
271       ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation;
272     else
273       return error(instrprof_error::bad_header);
274     ++Line;
275   }
276   return success();
277 }
278 
279 Error
280 TextInstrProfReader::readValueProfileData(InstrProfRecord &Record) {
281 
282 #define CHECK_LINE_END(Line)                                                   \
283   if (Line.is_at_end())                                                        \
284     return error(instrprof_error::truncated);
285 #define READ_NUM(Str, Dst)                                                     \
286   if ((Str).getAsInteger(10, (Dst)))                                           \
287     return error(instrprof_error::malformed);
288 #define VP_READ_ADVANCE(Val)                                                   \
289   CHECK_LINE_END(Line);                                                        \
290   uint32_t Val;                                                                \
291   READ_NUM((*Line), (Val));                                                    \
292   Line++;
293 
294   if (Line.is_at_end())
295     return success();
296 
297   uint32_t NumValueKinds;
298   if (Line->getAsInteger(10, NumValueKinds)) {
299     // No value profile data
300     return success();
301   }
302   if (NumValueKinds == 0 || NumValueKinds > IPVK_Last + 1)
303     return error(instrprof_error::malformed,
304                  "number of value kinds is invalid");
305   Line++;
306 
307   for (uint32_t VK = 0; VK < NumValueKinds; VK++) {
308     VP_READ_ADVANCE(ValueKind);
309     if (ValueKind > IPVK_Last)
310       return error(instrprof_error::malformed, "value kind is invalid");
311     ;
312     VP_READ_ADVANCE(NumValueSites);
313     if (!NumValueSites)
314       continue;
315 
316     Record.reserveSites(VK, NumValueSites);
317     for (uint32_t S = 0; S < NumValueSites; S++) {
318       VP_READ_ADVANCE(NumValueData);
319 
320       std::vector<InstrProfValueData> CurrentValues;
321       for (uint32_t V = 0; V < NumValueData; V++) {
322         CHECK_LINE_END(Line);
323         std::pair<StringRef, StringRef> VD = Line->rsplit(':');
324         uint64_t TakenCount, Value;
325         if (ValueKind == IPVK_IndirectCallTarget) {
326           if (InstrProfSymtab::isExternalSymbol(VD.first)) {
327             Value = 0;
328           } else {
329             if (Error E = Symtab->addFuncName(VD.first))
330               return E;
331             Value = IndexedInstrProf::ComputeHash(VD.first);
332           }
333         } else {
334           READ_NUM(VD.first, Value);
335         }
336         READ_NUM(VD.second, TakenCount);
337         CurrentValues.push_back({Value, TakenCount});
338         Line++;
339       }
340       Record.addValueData(ValueKind, S, CurrentValues.data(), NumValueData,
341                           nullptr);
342     }
343   }
344   return success();
345 
346 #undef CHECK_LINE_END
347 #undef READ_NUM
348 #undef VP_READ_ADVANCE
349 }
350 
351 Error TextInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
352   // Skip empty lines and comments.
353   while (!Line.is_at_end() && (Line->empty() || Line->startswith("#")))
354     ++Line;
355   // If we hit EOF while looking for a name, we're done.
356   if (Line.is_at_end()) {
357     return error(instrprof_error::eof);
358   }
359 
360   // Read the function name.
361   Record.Name = *Line++;
362   if (Error E = Symtab->addFuncName(Record.Name))
363     return error(std::move(E));
364 
365   // Read the function hash.
366   if (Line.is_at_end())
367     return error(instrprof_error::truncated);
368   if ((Line++)->getAsInteger(0, Record.Hash))
369     return error(instrprof_error::malformed,
370                  "function hash is not a valid integer");
371 
372   // Read the number of counters.
373   uint64_t NumCounters;
374   if (Line.is_at_end())
375     return error(instrprof_error::truncated);
376   if ((Line++)->getAsInteger(10, NumCounters))
377     return error(instrprof_error::malformed,
378                  "number of counters is not a valid integer");
379   if (NumCounters == 0)
380     return error(instrprof_error::malformed, "number of counters is zero");
381 
382   // Read each counter and fill our internal storage with the values.
383   Record.Clear();
384   Record.Counts.reserve(NumCounters);
385   for (uint64_t I = 0; I < NumCounters; ++I) {
386     if (Line.is_at_end())
387       return error(instrprof_error::truncated);
388     uint64_t Count;
389     if ((Line++)->getAsInteger(10, Count))
390       return error(instrprof_error::malformed, "count is invalid");
391     Record.Counts.push_back(Count);
392   }
393 
394   // Check if value profile data exists and read it if so.
395   if (Error E = readValueProfileData(Record))
396     return error(std::move(E));
397 
398   return success();
399 }
400 
401 template <class IntPtrT>
402 InstrProfKind RawInstrProfReader<IntPtrT>::getProfileKind() const {
403   return getProfileKindFromVersion(Version);
404 }
405 
406 template <class IntPtrT>
407 bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
408   if (DataBuffer.getBufferSize() < sizeof(uint64_t))
409     return false;
410   uint64_t Magic =
411     *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
412   return RawInstrProf::getMagic<IntPtrT>() == Magic ||
413          sys::getSwappedBytes(RawInstrProf::getMagic<IntPtrT>()) == Magic;
414 }
415 
416 template <class IntPtrT>
417 Error RawInstrProfReader<IntPtrT>::readHeader() {
418   if (!hasFormat(*DataBuffer))
419     return error(instrprof_error::bad_magic);
420   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
421     return error(instrprof_error::bad_header);
422   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(
423       DataBuffer->getBufferStart());
424   ShouldSwapBytes = Header->Magic != RawInstrProf::getMagic<IntPtrT>();
425   return readHeader(*Header);
426 }
427 
428 template <class IntPtrT>
429 Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
430   const char *End = DataBuffer->getBufferEnd();
431   // Skip zero padding between profiles.
432   while (CurrentPos != End && *CurrentPos == 0)
433     ++CurrentPos;
434   // If there's nothing left, we're done.
435   if (CurrentPos == End)
436     return make_error<InstrProfError>(instrprof_error::eof);
437   // If there isn't enough space for another header, this is probably just
438   // garbage at the end of the file.
439   if (CurrentPos + sizeof(RawInstrProf::Header) > End)
440     return make_error<InstrProfError>(instrprof_error::malformed,
441                                       "not enough space for another header");
442   // The writer ensures each profile is padded to start at an aligned address.
443   if (reinterpret_cast<size_t>(CurrentPos) % alignof(uint64_t))
444     return make_error<InstrProfError>(instrprof_error::malformed,
445                                       "insufficient padding");
446   // The magic should have the same byte order as in the previous header.
447   uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
448   if (Magic != swap(RawInstrProf::getMagic<IntPtrT>()))
449     return make_error<InstrProfError>(instrprof_error::bad_magic);
450 
451   // There's another profile to read, so we need to process the header.
452   auto *Header = reinterpret_cast<const RawInstrProf::Header *>(CurrentPos);
453   return readHeader(*Header);
454 }
455 
456 template <class IntPtrT>
457 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
458   if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart)))
459     return error(std::move(E));
460   for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
461     const IntPtrT FPtr = swap(I->FunctionPointer);
462     if (!FPtr)
463       continue;
464     Symtab.mapAddress(FPtr, I->NameRef);
465   }
466   return success();
467 }
468 
469 template <class IntPtrT>
470 Error RawInstrProfReader<IntPtrT>::readHeader(
471     const RawInstrProf::Header &Header) {
472   Version = swap(Header.Version);
473   if (GET_VERSION(Version) != RawInstrProf::Version)
474     return error(instrprof_error::unsupported_version);
475   if (useDebugInfoCorrelate() && !Correlator)
476     return error(instrprof_error::missing_debug_info_for_correlation);
477   if (!useDebugInfoCorrelate() && Correlator)
478     return error(instrprof_error::unexpected_debug_info_for_correlation);
479 
480   BinaryIdsSize = swap(Header.BinaryIdsSize);
481   if (BinaryIdsSize % sizeof(uint64_t))
482     return error(instrprof_error::bad_header);
483 
484   CountersDelta = swap(Header.CountersDelta);
485   NamesDelta = swap(Header.NamesDelta);
486   auto NumData = swap(Header.DataSize);
487   auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
488   auto CountersSize = swap(Header.CountersSize) * getCounterTypeSize();
489   auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
490   auto NamesSize = swap(Header.NamesSize);
491   ValueKindLast = swap(Header.ValueKindLast);
492 
493   auto DataSize = NumData * sizeof(RawInstrProf::ProfileData<IntPtrT>);
494   auto PaddingSize = getNumPaddingBytes(NamesSize);
495 
496   // Profile data starts after profile header and binary ids if exist.
497   ptrdiff_t DataOffset = sizeof(RawInstrProf::Header) + BinaryIdsSize;
498   ptrdiff_t CountersOffset = DataOffset + DataSize + PaddingBytesBeforeCounters;
499   ptrdiff_t NamesOffset =
500       CountersOffset + CountersSize + PaddingBytesAfterCounters;
501   ptrdiff_t ValueDataOffset = NamesOffset + NamesSize + PaddingSize;
502 
503   auto *Start = reinterpret_cast<const char *>(&Header);
504   if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
505     return error(instrprof_error::bad_header);
506 
507   if (Correlator) {
508     // These sizes in the raw file are zero because we constructed them in the
509     // Correlator.
510     assert(DataSize == 0 && NamesSize == 0);
511     assert(CountersDelta == 0 && NamesDelta == 0);
512     Data = Correlator->getDataPointer();
513     DataEnd = Data + Correlator->getDataSize();
514     NamesStart = Correlator->getNamesPointer();
515     NamesEnd = NamesStart + Correlator->getNamesSize();
516   } else {
517     Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
518         Start + DataOffset);
519     DataEnd = Data + NumData;
520     NamesStart = Start + NamesOffset;
521     NamesEnd = NamesStart + NamesSize;
522   }
523 
524   // Binary ids start just after the header.
525   BinaryIdsStart =
526       reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
527   CountersStart = Start + CountersOffset;
528   CountersEnd = CountersStart + CountersSize;
529   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
530 
531   const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
532   if (BinaryIdsStart + BinaryIdsSize > BufferEnd)
533     return error(instrprof_error::bad_header);
534 
535   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
536   if (Error E = createSymtab(*NewSymtab))
537     return E;
538 
539   Symtab = std::move(NewSymtab);
540   return success();
541 }
542 
543 template <class IntPtrT>
544 Error RawInstrProfReader<IntPtrT>::readName(NamedInstrProfRecord &Record) {
545   Record.Name = getName(Data->NameRef);
546   return success();
547 }
548 
549 template <class IntPtrT>
550 Error RawInstrProfReader<IntPtrT>::readFuncHash(NamedInstrProfRecord &Record) {
551   Record.Hash = swap(Data->FuncHash);
552   return success();
553 }
554 
555 template <class IntPtrT>
556 Error RawInstrProfReader<IntPtrT>::readRawCounts(
557     InstrProfRecord &Record) {
558   uint32_t NumCounters = swap(Data->NumCounters);
559   if (NumCounters == 0)
560     return error(instrprof_error::malformed, "number of counters is zero");
561 
562   ptrdiff_t CounterBaseOffset = swap(Data->CounterPtr) - CountersDelta;
563   if (CounterBaseOffset < 0)
564     return error(
565         instrprof_error::malformed,
566         ("counter offset " + Twine(CounterBaseOffset) + " is negative").str());
567 
568   if (CounterBaseOffset >= CountersEnd - CountersStart)
569     return error(instrprof_error::malformed,
570                  ("counter offset " + Twine(CounterBaseOffset) +
571                   " is greater than the maximum counter offset " +
572                   Twine(CountersEnd - CountersStart - 1))
573                      .str());
574 
575   uint64_t MaxNumCounters =
576       (CountersEnd - (CountersStart + CounterBaseOffset)) /
577       getCounterTypeSize();
578   if (NumCounters > MaxNumCounters)
579     return error(instrprof_error::malformed,
580                  ("number of counters " + Twine(NumCounters) +
581                   " is greater than the maximum number of counters " +
582                   Twine(MaxNumCounters))
583                      .str());
584 
585   Record.Counts.clear();
586   Record.Counts.reserve(NumCounters);
587   for (uint32_t I = 0; I < NumCounters; I++) {
588     const char *Ptr =
589         CountersStart + CounterBaseOffset + I * getCounterTypeSize();
590     if (hasSingleByteCoverage()) {
591       // A value of zero signifies the block is covered.
592       Record.Counts.push_back(*Ptr == 0 ? 1 : 0);
593     } else {
594       const auto *CounterValue = reinterpret_cast<const uint64_t *>(Ptr);
595       Record.Counts.push_back(swap(*CounterValue));
596     }
597   }
598 
599   return success();
600 }
601 
602 template <class IntPtrT>
603 Error RawInstrProfReader<IntPtrT>::readValueProfilingData(
604     InstrProfRecord &Record) {
605   Record.clearValueData();
606   CurValueDataSize = 0;
607   // Need to match the logic in value profile dumper code in compiler-rt:
608   uint32_t NumValueKinds = 0;
609   for (uint32_t I = 0; I < IPVK_Last + 1; I++)
610     NumValueKinds += (Data->NumValueSites[I] != 0);
611 
612   if (!NumValueKinds)
613     return success();
614 
615   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
616       ValueProfData::getValueProfData(
617           ValueDataStart, (const unsigned char *)DataBuffer->getBufferEnd(),
618           getDataEndianness());
619 
620   if (Error E = VDataPtrOrErr.takeError())
621     return E;
622 
623   // Note that besides deserialization, this also performs the conversion for
624   // indirect call targets.  The function pointers from the raw profile are
625   // remapped into function name hashes.
626   VDataPtrOrErr.get()->deserializeTo(Record, Symtab.get());
627   CurValueDataSize = VDataPtrOrErr.get()->getSize();
628   return success();
629 }
630 
631 template <class IntPtrT>
632 Error RawInstrProfReader<IntPtrT>::readNextRecord(NamedInstrProfRecord &Record) {
633   // Keep reading profiles that consist of only headers and no profile data and
634   // counters.
635   while (atEnd())
636     // At this point, ValueDataStart field points to the next header.
637     if (Error E = readNextHeader(getNextHeaderPos()))
638       return error(std::move(E));
639 
640   // Read name ad set it in Record.
641   if (Error E = readName(Record))
642     return error(std::move(E));
643 
644   // Read FuncHash and set it in Record.
645   if (Error E = readFuncHash(Record))
646     return error(std::move(E));
647 
648   // Read raw counts and set Record.
649   if (Error E = readRawCounts(Record))
650     return error(std::move(E));
651 
652   // Read value data and set Record.
653   if (Error E = readValueProfilingData(Record))
654     return error(std::move(E));
655 
656   // Iterate.
657   advanceData();
658   return success();
659 }
660 
661 template <class IntPtrT>
662 Error RawInstrProfReader<IntPtrT>::readBinaryIds(
663     std::vector<llvm::object::BuildID> &BinaryIds) {
664   return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
665                                BinaryIds, getDataEndianness());
666 }
667 
668 template <class IntPtrT>
669 Error RawInstrProfReader<IntPtrT>::printBinaryIds(raw_ostream &OS) {
670   return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
671                                 getDataEndianness());
672 }
673 
674 namespace llvm {
675 
676 template class RawInstrProfReader<uint32_t>;
677 template class RawInstrProfReader<uint64_t>;
678 
679 } // end namespace llvm
680 
681 InstrProfLookupTrait::hash_value_type
682 InstrProfLookupTrait::ComputeHash(StringRef K) {
683   return IndexedInstrProf::ComputeHash(HashType, K);
684 }
685 
686 using data_type = InstrProfLookupTrait::data_type;
687 using offset_type = InstrProfLookupTrait::offset_type;
688 
689 bool InstrProfLookupTrait::readValueProfilingData(
690     const unsigned char *&D, const unsigned char *const End) {
691   Expected<std::unique_ptr<ValueProfData>> VDataPtrOrErr =
692       ValueProfData::getValueProfData(D, End, ValueProfDataEndianness);
693 
694   if (VDataPtrOrErr.takeError())
695     return false;
696 
697   VDataPtrOrErr.get()->deserializeTo(DataBuffer.back(), nullptr);
698   D += VDataPtrOrErr.get()->TotalSize;
699 
700   return true;
701 }
702 
703 data_type InstrProfLookupTrait::ReadData(StringRef K, const unsigned char *D,
704                                          offset_type N) {
705   using namespace support;
706 
707   // Check if the data is corrupt. If so, don't try to read it.
708   if (N % sizeof(uint64_t))
709     return data_type();
710 
711   DataBuffer.clear();
712   std::vector<uint64_t> CounterBuffer;
713 
714   const unsigned char *End = D + N;
715   while (D < End) {
716     // Read hash.
717     if (D + sizeof(uint64_t) >= End)
718       return data_type();
719     uint64_t Hash = endian::readNext<uint64_t, little, unaligned>(D);
720 
721     // Initialize number of counters for GET_VERSION(FormatVersion) == 1.
722     uint64_t CountsSize = N / sizeof(uint64_t) - 1;
723     // If format version is different then read the number of counters.
724     if (GET_VERSION(FormatVersion) != IndexedInstrProf::ProfVersion::Version1) {
725       if (D + sizeof(uint64_t) > End)
726         return data_type();
727       CountsSize = endian::readNext<uint64_t, little, unaligned>(D);
728     }
729     // Read counter values.
730     if (D + CountsSize * sizeof(uint64_t) > End)
731       return data_type();
732 
733     CounterBuffer.clear();
734     CounterBuffer.reserve(CountsSize);
735     for (uint64_t J = 0; J < CountsSize; ++J)
736       CounterBuffer.push_back(endian::readNext<uint64_t, little, unaligned>(D));
737 
738     DataBuffer.emplace_back(K, Hash, std::move(CounterBuffer));
739 
740     // Read value profiling data.
741     if (GET_VERSION(FormatVersion) > IndexedInstrProf::ProfVersion::Version2 &&
742         !readValueProfilingData(D, End)) {
743       DataBuffer.clear();
744       return data_type();
745     }
746   }
747   return DataBuffer;
748 }
749 
750 template <typename HashTableImpl>
751 Error InstrProfReaderIndex<HashTableImpl>::getRecords(
752     StringRef FuncName, ArrayRef<NamedInstrProfRecord> &Data) {
753   auto Iter = HashTable->find(FuncName);
754   if (Iter == HashTable->end())
755     return make_error<InstrProfError>(instrprof_error::unknown_function);
756 
757   Data = (*Iter);
758   if (Data.empty())
759     return make_error<InstrProfError>(instrprof_error::malformed,
760                                       "profile data is empty");
761 
762   return Error::success();
763 }
764 
765 template <typename HashTableImpl>
766 Error InstrProfReaderIndex<HashTableImpl>::getRecords(
767     ArrayRef<NamedInstrProfRecord> &Data) {
768   if (atEnd())
769     return make_error<InstrProfError>(instrprof_error::eof);
770 
771   Data = *RecordIterator;
772 
773   if (Data.empty())
774     return make_error<InstrProfError>(instrprof_error::malformed,
775                                       "profile data is empty");
776 
777   return Error::success();
778 }
779 
780 template <typename HashTableImpl>
781 InstrProfReaderIndex<HashTableImpl>::InstrProfReaderIndex(
782     const unsigned char *Buckets, const unsigned char *const Payload,
783     const unsigned char *const Base, IndexedInstrProf::HashT HashType,
784     uint64_t Version) {
785   FormatVersion = Version;
786   HashTable.reset(HashTableImpl::Create(
787       Buckets, Payload, Base,
788       typename HashTableImpl::InfoType(HashType, Version)));
789   RecordIterator = HashTable->data_begin();
790 }
791 
792 template <typename HashTableImpl>
793 InstrProfKind InstrProfReaderIndex<HashTableImpl>::getProfileKind() const {
794   return getProfileKindFromVersion(FormatVersion);
795 }
796 
797 namespace {
798 /// A remapper that does not apply any remappings.
799 class InstrProfReaderNullRemapper : public InstrProfReaderRemapper {
800   InstrProfReaderIndexBase &Underlying;
801 
802 public:
803   InstrProfReaderNullRemapper(InstrProfReaderIndexBase &Underlying)
804       : Underlying(Underlying) {}
805 
806   Error getRecords(StringRef FuncName,
807                    ArrayRef<NamedInstrProfRecord> &Data) override {
808     return Underlying.getRecords(FuncName, Data);
809   }
810 };
811 } // namespace
812 
813 /// A remapper that applies remappings based on a symbol remapping file.
814 template <typename HashTableImpl>
815 class llvm::InstrProfReaderItaniumRemapper
816     : public InstrProfReaderRemapper {
817 public:
818   InstrProfReaderItaniumRemapper(
819       std::unique_ptr<MemoryBuffer> RemapBuffer,
820       InstrProfReaderIndex<HashTableImpl> &Underlying)
821       : RemapBuffer(std::move(RemapBuffer)), Underlying(Underlying) {
822   }
823 
824   /// Extract the original function name from a PGO function name.
825   static StringRef extractName(StringRef Name) {
826     // We can have multiple :-separated pieces; there can be pieces both
827     // before and after the mangled name. Find the first part that starts
828     // with '_Z'; we'll assume that's the mangled name we want.
829     std::pair<StringRef, StringRef> Parts = {StringRef(), Name};
830     while (true) {
831       Parts = Parts.second.split(':');
832       if (Parts.first.startswith("_Z"))
833         return Parts.first;
834       if (Parts.second.empty())
835         return Name;
836     }
837   }
838 
839   /// Given a mangled name extracted from a PGO function name, and a new
840   /// form for that mangled name, reconstitute the name.
841   static void reconstituteName(StringRef OrigName, StringRef ExtractedName,
842                                StringRef Replacement,
843                                SmallVectorImpl<char> &Out) {
844     Out.reserve(OrigName.size() + Replacement.size() - ExtractedName.size());
845     Out.insert(Out.end(), OrigName.begin(), ExtractedName.begin());
846     Out.insert(Out.end(), Replacement.begin(), Replacement.end());
847     Out.insert(Out.end(), ExtractedName.end(), OrigName.end());
848   }
849 
850   Error populateRemappings() override {
851     if (Error E = Remappings.read(*RemapBuffer))
852       return E;
853     for (StringRef Name : Underlying.HashTable->keys()) {
854       StringRef RealName = extractName(Name);
855       if (auto Key = Remappings.insert(RealName)) {
856         // FIXME: We could theoretically map the same equivalence class to
857         // multiple names in the profile data. If that happens, we should
858         // return NamedInstrProfRecords from all of them.
859         MappedNames.insert({Key, RealName});
860       }
861     }
862     return Error::success();
863   }
864 
865   Error getRecords(StringRef FuncName,
866                    ArrayRef<NamedInstrProfRecord> &Data) override {
867     StringRef RealName = extractName(FuncName);
868     if (auto Key = Remappings.lookup(RealName)) {
869       StringRef Remapped = MappedNames.lookup(Key);
870       if (!Remapped.empty()) {
871         if (RealName.begin() == FuncName.begin() &&
872             RealName.end() == FuncName.end())
873           FuncName = Remapped;
874         else {
875           // Try rebuilding the name from the given remapping.
876           SmallString<256> Reconstituted;
877           reconstituteName(FuncName, RealName, Remapped, Reconstituted);
878           Error E = Underlying.getRecords(Reconstituted, Data);
879           if (!E)
880             return E;
881 
882           // If we failed because the name doesn't exist, fall back to asking
883           // about the original name.
884           if (Error Unhandled = handleErrors(
885                   std::move(E), [](std::unique_ptr<InstrProfError> Err) {
886                     return Err->get() == instrprof_error::unknown_function
887                                ? Error::success()
888                                : Error(std::move(Err));
889                   }))
890             return Unhandled;
891         }
892       }
893     }
894     return Underlying.getRecords(FuncName, Data);
895   }
896 
897 private:
898   /// The memory buffer containing the remapping configuration. Remappings
899   /// holds pointers into this buffer.
900   std::unique_ptr<MemoryBuffer> RemapBuffer;
901 
902   /// The mangling remapper.
903   SymbolRemappingReader Remappings;
904 
905   /// Mapping from mangled name keys to the name used for the key in the
906   /// profile data.
907   /// FIXME: Can we store a location within the on-disk hash table instead of
908   /// redoing lookup?
909   DenseMap<SymbolRemappingReader::Key, StringRef> MappedNames;
910 
911   /// The real profile data reader.
912   InstrProfReaderIndex<HashTableImpl> &Underlying;
913 };
914 
915 bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
916   using namespace support;
917 
918   if (DataBuffer.getBufferSize() < 8)
919     return false;
920   uint64_t Magic =
921       endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
922   // Verify that it's magical.
923   return Magic == IndexedInstrProf::Magic;
924 }
925 
926 const unsigned char *
927 IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
928                                     const unsigned char *Cur, bool UseCS) {
929   using namespace IndexedInstrProf;
930   using namespace support;
931 
932   if (Version >= IndexedInstrProf::Version4) {
933     const IndexedInstrProf::Summary *SummaryInLE =
934         reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
935     uint64_t NFields =
936         endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
937     uint64_t NEntries =
938         endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
939     uint32_t SummarySize =
940         IndexedInstrProf::Summary::getSize(NFields, NEntries);
941     std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
942         IndexedInstrProf::allocSummary(SummarySize);
943 
944     const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
945     uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
946     for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
947       Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
948 
949     SummaryEntryVector DetailedSummary;
950     for (unsigned I = 0; I < SummaryData->NumCutoffEntries; I++) {
951       const IndexedInstrProf::Summary::Entry &Ent = SummaryData->getEntry(I);
952       DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
953                                    Ent.NumBlocks);
954     }
955     std::unique_ptr<llvm::ProfileSummary> &Summary =
956         UseCS ? this->CS_Summary : this->Summary;
957 
958     // initialize InstrProfSummary using the SummaryData from disk.
959     Summary = std::make_unique<ProfileSummary>(
960         UseCS ? ProfileSummary::PSK_CSInstr : ProfileSummary::PSK_Instr,
961         DetailedSummary, SummaryData->get(Summary::TotalBlockCount),
962         SummaryData->get(Summary::MaxBlockCount),
963         SummaryData->get(Summary::MaxInternalBlockCount),
964         SummaryData->get(Summary::MaxFunctionCount),
965         SummaryData->get(Summary::TotalNumBlocks),
966         SummaryData->get(Summary::TotalNumFunctions));
967     return Cur + SummarySize;
968   } else {
969     // The older versions do not support a profile summary. This just computes
970     // an empty summary, which will not result in accurate hot/cold detection.
971     // We would need to call addRecord for all NamedInstrProfRecords to get the
972     // correct summary. However, this version is old (prior to early 2016) and
973     // has not been supporting an accurate summary for several years.
974     InstrProfSummaryBuilder Builder(ProfileSummaryBuilder::DefaultCutoffs);
975     Summary = Builder.getSummary();
976     return Cur;
977   }
978 }
979 
980 Error IndexedInstrProfReader::readHeader() {
981   using namespace support;
982 
983   const unsigned char *Start =
984       (const unsigned char *)DataBuffer->getBufferStart();
985   const unsigned char *Cur = Start;
986   if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
987     return error(instrprof_error::truncated);
988 
989   auto HeaderOr = IndexedInstrProf::Header::readFromBuffer(Start);
990   if (!HeaderOr)
991     return HeaderOr.takeError();
992 
993   const IndexedInstrProf::Header *Header = &HeaderOr.get();
994   Cur += Header->size();
995 
996   Cur = readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
997                     /* UseCS */ false);
998   if (Header->formatVersion() & VARIANT_MASK_CSIR_PROF)
999     Cur =
1000         readSummary((IndexedInstrProf::ProfVersion)Header->formatVersion(), Cur,
1001                     /* UseCS */ true);
1002   // Read the hash type and start offset.
1003   IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
1004       endian::byte_swap<uint64_t, little>(Header->HashType));
1005   if (HashType > IndexedInstrProf::HashT::Last)
1006     return error(instrprof_error::unsupported_hash_type);
1007 
1008   uint64_t HashOffset = endian::byte_swap<uint64_t, little>(Header->HashOffset);
1009 
1010   // The hash table with profile counts comes next.
1011   auto IndexPtr = std::make_unique<InstrProfReaderIndex<OnDiskHashTableImplV3>>(
1012       Start + HashOffset, Cur, Start, HashType, Header->formatVersion());
1013 
1014   // The MemProfOffset field in the header is only valid when the format
1015   // version is higher than 8 (when it was introduced).
1016   if (GET_VERSION(Header->formatVersion()) >= 8 &&
1017       Header->formatVersion() & VARIANT_MASK_MEMPROF) {
1018     uint64_t MemProfOffset =
1019         endian::byte_swap<uint64_t, little>(Header->MemProfOffset);
1020 
1021     const unsigned char *Ptr = Start + MemProfOffset;
1022     // The value returned from RecordTableGenerator.Emit.
1023     const uint64_t RecordTableOffset =
1024         support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1025     // The offset in the stream right before invoking
1026     // FrameTableGenerator.Emit.
1027     const uint64_t FramePayloadOffset =
1028         support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1029     // The value returned from FrameTableGenerator.Emit.
1030     const uint64_t FrameTableOffset =
1031         support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1032 
1033     // Read the schema.
1034     auto SchemaOr = memprof::readMemProfSchema(Ptr);
1035     if (!SchemaOr)
1036       return SchemaOr.takeError();
1037     Schema = SchemaOr.get();
1038 
1039     // Now initialize the table reader with a pointer into data buffer.
1040     MemProfRecordTable.reset(MemProfRecordHashTable::Create(
1041         /*Buckets=*/Start + RecordTableOffset,
1042         /*Payload=*/Ptr,
1043         /*Base=*/Start, memprof::RecordLookupTrait(Schema)));
1044 
1045     // Initialize the frame table reader with the payload and bucket offsets.
1046     MemProfFrameTable.reset(MemProfFrameHashTable::Create(
1047         /*Buckets=*/Start + FrameTableOffset,
1048         /*Payload=*/Start + FramePayloadOffset,
1049         /*Base=*/Start, memprof::FrameLookupTrait()));
1050   }
1051 
1052   // BinaryIdOffset field in the header is only valid when the format version
1053   // is higher than 9 (when it was introduced).
1054   if (GET_VERSION(Header->formatVersion()) >= 9) {
1055     uint64_t BinaryIdOffset =
1056         endian::byte_swap<uint64_t, little>(Header->BinaryIdOffset);
1057     const unsigned char *Ptr = Start + BinaryIdOffset;
1058     // Read binary ids size.
1059     BinaryIdsSize = support::endian::readNext<uint64_t, little, unaligned>(Ptr);
1060     if (BinaryIdsSize % sizeof(uint64_t))
1061       return error(instrprof_error::bad_header);
1062     // Set the binary ids start.
1063     BinaryIdsStart = Ptr;
1064     if (BinaryIdsStart > (const unsigned char *)DataBuffer->getBufferEnd())
1065       return make_error<InstrProfError>(instrprof_error::malformed,
1066                                         "corrupted binary ids");
1067   }
1068 
1069   // Load the remapping table now if requested.
1070   if (RemappingBuffer) {
1071     Remapper =
1072         std::make_unique<InstrProfReaderItaniumRemapper<OnDiskHashTableImplV3>>(
1073             std::move(RemappingBuffer), *IndexPtr);
1074     if (Error E = Remapper->populateRemappings())
1075       return E;
1076   } else {
1077     Remapper = std::make_unique<InstrProfReaderNullRemapper>(*IndexPtr);
1078   }
1079   Index = std::move(IndexPtr);
1080 
1081   return success();
1082 }
1083 
1084 InstrProfSymtab &IndexedInstrProfReader::getSymtab() {
1085   if (Symtab)
1086     return *Symtab;
1087 
1088   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
1089   if (Error E = Index->populateSymtab(*NewSymtab)) {
1090     consumeError(error(InstrProfError::take(std::move(E))));
1091   }
1092 
1093   Symtab = std::move(NewSymtab);
1094   return *Symtab;
1095 }
1096 
1097 Expected<InstrProfRecord> IndexedInstrProfReader::getInstrProfRecord(
1098     StringRef FuncName, uint64_t FuncHash, uint64_t *MismatchedFuncSum) {
1099   ArrayRef<NamedInstrProfRecord> Data;
1100   uint64_t FuncSum = 0;
1101   Error Err = Remapper->getRecords(FuncName, Data);
1102   if (Err)
1103     return std::move(Err);
1104   // Found it. Look for counters with the right hash.
1105 
1106   // A flag to indicate if the records are from the same type
1107   // of profile (i.e cs vs nocs).
1108   bool CSBitMatch = false;
1109   auto getFuncSum = [](const std::vector<uint64_t> &Counts) {
1110     uint64_t ValueSum = 0;
1111     for (uint64_t CountValue : Counts) {
1112       if (CountValue == (uint64_t)-1)
1113         continue;
1114       // Handle overflow -- if that happens, return max.
1115       if (std::numeric_limits<uint64_t>::max() - CountValue <= ValueSum)
1116         return std::numeric_limits<uint64_t>::max();
1117       ValueSum += CountValue;
1118     }
1119     return ValueSum;
1120   };
1121 
1122   for (const NamedInstrProfRecord &I : Data) {
1123     // Check for a match and fill the vector if there is one.
1124     if (I.Hash == FuncHash)
1125       return std::move(I);
1126     if (NamedInstrProfRecord::hasCSFlagInHash(I.Hash) ==
1127         NamedInstrProfRecord::hasCSFlagInHash(FuncHash)) {
1128       CSBitMatch = true;
1129       if (MismatchedFuncSum == nullptr)
1130         continue;
1131       FuncSum = std::max(FuncSum, getFuncSum(I.Counts));
1132     }
1133   }
1134   if (CSBitMatch) {
1135     if (MismatchedFuncSum != nullptr)
1136       *MismatchedFuncSum = FuncSum;
1137     return error(instrprof_error::hash_mismatch);
1138   }
1139   return error(instrprof_error::unknown_function);
1140 }
1141 
1142 Expected<memprof::MemProfRecord>
1143 IndexedInstrProfReader::getMemProfRecord(const uint64_t FuncNameHash) {
1144   // TODO: Add memprof specific errors.
1145   if (MemProfRecordTable == nullptr)
1146     return make_error<InstrProfError>(instrprof_error::invalid_prof,
1147                                       "no memprof data available in profile");
1148   auto Iter = MemProfRecordTable->find(FuncNameHash);
1149   if (Iter == MemProfRecordTable->end())
1150     return make_error<InstrProfError>(
1151         instrprof_error::unknown_function,
1152         "memprof record not found for function hash " + Twine(FuncNameHash));
1153 
1154   // Setup a callback to convert from frame ids to frame using the on-disk
1155   // FrameData hash table.
1156   memprof::FrameId LastUnmappedFrameId = 0;
1157   bool HasFrameMappingError = false;
1158   auto IdToFrameCallback = [&](const memprof::FrameId Id) {
1159     auto FrIter = MemProfFrameTable->find(Id);
1160     if (FrIter == MemProfFrameTable->end()) {
1161       LastUnmappedFrameId = Id;
1162       HasFrameMappingError = true;
1163       return memprof::Frame(0, 0, 0, false);
1164     }
1165     return *FrIter;
1166   };
1167 
1168   memprof::MemProfRecord Record(*Iter, IdToFrameCallback);
1169 
1170   // Check that all frame ids were successfully converted to frames.
1171   if (HasFrameMappingError) {
1172     return make_error<InstrProfError>(instrprof_error::hash_mismatch,
1173                                       "memprof frame not found for frame id " +
1174                                           Twine(LastUnmappedFrameId));
1175   }
1176   return Record;
1177 }
1178 
1179 Error IndexedInstrProfReader::getFunctionCounts(StringRef FuncName,
1180                                                 uint64_t FuncHash,
1181                                                 std::vector<uint64_t> &Counts) {
1182   Expected<InstrProfRecord> Record = getInstrProfRecord(FuncName, FuncHash);
1183   if (Error E = Record.takeError())
1184     return error(std::move(E));
1185 
1186   Counts = Record.get().Counts;
1187   return success();
1188 }
1189 
1190 Error IndexedInstrProfReader::readNextRecord(NamedInstrProfRecord &Record) {
1191   ArrayRef<NamedInstrProfRecord> Data;
1192 
1193   Error E = Index->getRecords(Data);
1194   if (E)
1195     return error(std::move(E));
1196 
1197   Record = Data[RecordIndex++];
1198   if (RecordIndex >= Data.size()) {
1199     Index->advanceToNextKey();
1200     RecordIndex = 0;
1201   }
1202   return success();
1203 }
1204 
1205 Error IndexedInstrProfReader::readBinaryIds(
1206     std::vector<llvm::object::BuildID> &BinaryIds) {
1207   return readBinaryIdsInternal(*DataBuffer, BinaryIdsSize, BinaryIdsStart,
1208                                BinaryIds, llvm::support::little);
1209 }
1210 
1211 Error IndexedInstrProfReader::printBinaryIds(raw_ostream &OS) {
1212   return printBinaryIdsInternal(OS, *DataBuffer, BinaryIdsSize, BinaryIdsStart,
1213                                 llvm::support::little);
1214 }
1215 
1216 void InstrProfReader::accumulateCounts(CountSumOrPercent &Sum, bool IsCS) {
1217   uint64_t NumFuncs = 0;
1218   for (const auto &Func : *this) {
1219     if (isIRLevelProfile()) {
1220       bool FuncIsCS = NamedInstrProfRecord::hasCSFlagInHash(Func.Hash);
1221       if (FuncIsCS != IsCS)
1222         continue;
1223     }
1224     Func.accumulateCounts(Sum);
1225     ++NumFuncs;
1226   }
1227   Sum.NumEntries = NumFuncs;
1228 }
1229