1//=-- InstrProfReader.cpp - Instrumented profiling reader -------------------=//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains support for reading profiling data for clang's
11// instrumentation based PGO and coverage.
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/ProfileData/InstrProfReader.h"
16#include "llvm/ProfileData/InstrProf.h"
17
18#include "InstrProfIndexed.h"
19
20#include <cassert>
21
22using namespace llvm;
23
24static std::error_code
25setupMemoryBuffer(std::string Path, std::unique_ptr<MemoryBuffer> &Buffer) {
26  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
27      MemoryBuffer::getFileOrSTDIN(Path);
28  if (std::error_code EC = BufferOrErr.getError())
29    return EC;
30  Buffer = std::move(BufferOrErr.get());
31
32  // Sanity check the file.
33  if (Buffer->getBufferSize() > std::numeric_limits<unsigned>::max())
34    return instrprof_error::too_large;
35  return instrprof_error::success;
36}
37
38static std::error_code initializeReader(InstrProfReader &Reader) {
39  return Reader.readHeader();
40}
41
42std::error_code
43InstrProfReader::create(std::string Path,
44                        std::unique_ptr<InstrProfReader> &Result) {
45  // Set up the buffer to read.
46  std::unique_ptr<MemoryBuffer> Buffer;
47  if (std::error_code EC = setupMemoryBuffer(Path, Buffer))
48    return EC;
49
50  // Create the reader.
51  if (IndexedInstrProfReader::hasFormat(*Buffer))
52    Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
53  else if (RawInstrProfReader64::hasFormat(*Buffer))
54    Result.reset(new RawInstrProfReader64(std::move(Buffer)));
55  else if (RawInstrProfReader32::hasFormat(*Buffer))
56    Result.reset(new RawInstrProfReader32(std::move(Buffer)));
57  else
58    Result.reset(new TextInstrProfReader(std::move(Buffer)));
59
60  // Initialize the reader and return the result.
61  return initializeReader(*Result);
62}
63
64std::error_code IndexedInstrProfReader::create(
65    std::string Path, std::unique_ptr<IndexedInstrProfReader> &Result) {
66  // Set up the buffer to read.
67  std::unique_ptr<MemoryBuffer> Buffer;
68  if (std::error_code EC = setupMemoryBuffer(Path, Buffer))
69    return EC;
70
71  // Create the reader.
72  if (!IndexedInstrProfReader::hasFormat(*Buffer))
73    return instrprof_error::bad_magic;
74  Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
75
76  // Initialize the reader and return the result.
77  return initializeReader(*Result);
78}
79
80void InstrProfIterator::Increment() {
81  if (Reader->readNextRecord(Record))
82    *this = InstrProfIterator();
83}
84
85std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) {
86  // Skip empty lines.
87  while (!Line.is_at_end() && Line->empty())
88    ++Line;
89  // If we hit EOF while looking for a name, we're done.
90  if (Line.is_at_end())
91    return error(instrprof_error::eof);
92
93  // Read the function name.
94  Record.Name = *Line++;
95
96  // Read the function hash.
97  if (Line.is_at_end())
98    return error(instrprof_error::truncated);
99  if ((Line++)->getAsInteger(10, Record.Hash))
100    return error(instrprof_error::malformed);
101
102  // Read the number of counters.
103  uint64_t NumCounters;
104  if (Line.is_at_end())
105    return error(instrprof_error::truncated);
106  if ((Line++)->getAsInteger(10, NumCounters))
107    return error(instrprof_error::malformed);
108  if (NumCounters == 0)
109    return error(instrprof_error::malformed);
110
111  // Read each counter and fill our internal storage with the values.
112  Counts.clear();
113  Counts.reserve(NumCounters);
114  for (uint64_t I = 0; I < NumCounters; ++I) {
115    if (Line.is_at_end())
116      return error(instrprof_error::truncated);
117    uint64_t Count;
118    if ((Line++)->getAsInteger(10, Count))
119      return error(instrprof_error::malformed);
120    Counts.push_back(Count);
121  }
122  // Give the record a reference to our internal counter storage.
123  Record.Counts = Counts;
124
125  return success();
126}
127
128template <class IntPtrT>
129static uint64_t getRawMagic();
130
131template <>
132uint64_t getRawMagic<uint64_t>() {
133  return
134    uint64_t(255) << 56 |
135    uint64_t('l') << 48 |
136    uint64_t('p') << 40 |
137    uint64_t('r') << 32 |
138    uint64_t('o') << 24 |
139    uint64_t('f') << 16 |
140    uint64_t('r') <<  8 |
141    uint64_t(129);
142}
143
144template <>
145uint64_t getRawMagic<uint32_t>() {
146  return
147    uint64_t(255) << 56 |
148    uint64_t('l') << 48 |
149    uint64_t('p') << 40 |
150    uint64_t('r') << 32 |
151    uint64_t('o') << 24 |
152    uint64_t('f') << 16 |
153    uint64_t('R') <<  8 |
154    uint64_t(129);
155}
156
157template <class IntPtrT>
158bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
159  if (DataBuffer.getBufferSize() < sizeof(uint64_t))
160    return false;
161  uint64_t Magic =
162    *reinterpret_cast<const uint64_t *>(DataBuffer.getBufferStart());
163  return getRawMagic<IntPtrT>() == Magic ||
164    sys::getSwappedBytes(getRawMagic<IntPtrT>()) == Magic;
165}
166
167template <class IntPtrT>
168std::error_code RawInstrProfReader<IntPtrT>::readHeader() {
169  if (!hasFormat(*DataBuffer))
170    return error(instrprof_error::bad_magic);
171  if (DataBuffer->getBufferSize() < sizeof(RawHeader))
172    return error(instrprof_error::bad_header);
173  auto *Header =
174    reinterpret_cast<const RawHeader *>(DataBuffer->getBufferStart());
175  ShouldSwapBytes = Header->Magic != getRawMagic<IntPtrT>();
176  return readHeader(*Header);
177}
178
179template <class IntPtrT>
180std::error_code
181RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
182  const char *End = DataBuffer->getBufferEnd();
183  // Skip zero padding between profiles.
184  while (CurrentPos != End && *CurrentPos == 0)
185    ++CurrentPos;
186  // If there's nothing left, we're done.
187  if (CurrentPos == End)
188    return instrprof_error::eof;
189  // If there isn't enough space for another header, this is probably just
190  // garbage at the end of the file.
191  if (CurrentPos + sizeof(RawHeader) > End)
192    return instrprof_error::malformed;
193  // The magic should have the same byte order as in the previous header.
194  uint64_t Magic = *reinterpret_cast<const uint64_t *>(CurrentPos);
195  if (Magic != swap(getRawMagic<IntPtrT>()))
196    return instrprof_error::bad_magic;
197
198  // There's another profile to read, so we need to process the header.
199  auto *Header = reinterpret_cast<const RawHeader *>(CurrentPos);
200  return readHeader(*Header);
201}
202
203static uint64_t getRawVersion() {
204  return 1;
205}
206
207template <class IntPtrT>
208std::error_code
209RawInstrProfReader<IntPtrT>::readHeader(const RawHeader &Header) {
210  if (swap(Header.Version) != getRawVersion())
211    return error(instrprof_error::unsupported_version);
212
213  CountersDelta = swap(Header.CountersDelta);
214  NamesDelta = swap(Header.NamesDelta);
215  auto DataSize = swap(Header.DataSize);
216  auto CountersSize = swap(Header.CountersSize);
217  auto NamesSize = swap(Header.NamesSize);
218
219  ptrdiff_t DataOffset = sizeof(RawHeader);
220  ptrdiff_t CountersOffset = DataOffset + sizeof(ProfileData) * DataSize;
221  ptrdiff_t NamesOffset = CountersOffset + sizeof(uint64_t) * CountersSize;
222  size_t ProfileSize = NamesOffset + sizeof(char) * NamesSize;
223
224  auto *Start = reinterpret_cast<const char *>(&Header);
225  if (Start + ProfileSize > DataBuffer->getBufferEnd())
226    return error(instrprof_error::bad_header);
227
228  Data = reinterpret_cast<const ProfileData *>(Start + DataOffset);
229  DataEnd = Data + DataSize;
230  CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
231  NamesStart = Start + NamesOffset;
232  ProfileEnd = Start + ProfileSize;
233
234  return success();
235}
236
237template <class IntPtrT>
238std::error_code
239RawInstrProfReader<IntPtrT>::readNextRecord(InstrProfRecord &Record) {
240  if (Data == DataEnd)
241    if (std::error_code EC = readNextHeader(ProfileEnd))
242      return EC;
243
244  // Get the raw data.
245  StringRef RawName(getName(Data->NamePtr), swap(Data->NameSize));
246  uint32_t NumCounters = swap(Data->NumCounters);
247  if (NumCounters == 0)
248    return error(instrprof_error::malformed);
249  auto RawCounts = makeArrayRef(getCounter(Data->CounterPtr), NumCounters);
250
251  // Check bounds.
252  auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
253  if (RawName.data() < NamesStart ||
254      RawName.data() + RawName.size() > DataBuffer->getBufferEnd() ||
255      RawCounts.data() < CountersStart ||
256      RawCounts.data() + RawCounts.size() > NamesStartAsCounter)
257    return error(instrprof_error::malformed);
258
259  // Store the data in Record, byte-swapping as necessary.
260  Record.Hash = swap(Data->FuncHash);
261  Record.Name = RawName;
262  if (ShouldSwapBytes) {
263    Counts.clear();
264    Counts.reserve(RawCounts.size());
265    for (uint64_t Count : RawCounts)
266      Counts.push_back(swap(Count));
267    Record.Counts = Counts;
268  } else
269    Record.Counts = RawCounts;
270
271  // Iterate.
272  ++Data;
273  return success();
274}
275
276namespace llvm {
277template class RawInstrProfReader<uint32_t>;
278template class RawInstrProfReader<uint64_t>;
279}
280
281InstrProfLookupTrait::hash_value_type
282InstrProfLookupTrait::ComputeHash(StringRef K) {
283  return IndexedInstrProf::ComputeHash(HashType, K);
284}
285
286bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
287  if (DataBuffer.getBufferSize() < 8)
288    return false;
289  using namespace support;
290  uint64_t Magic =
291      endian::read<uint64_t, little, aligned>(DataBuffer.getBufferStart());
292  return Magic == IndexedInstrProf::Magic;
293}
294
295std::error_code IndexedInstrProfReader::readHeader() {
296  const unsigned char *Start =
297      (const unsigned char *)DataBuffer->getBufferStart();
298  const unsigned char *Cur = Start;
299  if ((const unsigned char *)DataBuffer->getBufferEnd() - Cur < 24)
300    return error(instrprof_error::truncated);
301
302  using namespace support;
303
304  // Check the magic number.
305  uint64_t Magic = endian::readNext<uint64_t, little, unaligned>(Cur);
306  if (Magic != IndexedInstrProf::Magic)
307    return error(instrprof_error::bad_magic);
308
309  // Read the version.
310  uint64_t Version = endian::readNext<uint64_t, little, unaligned>(Cur);
311  if (Version != IndexedInstrProf::Version)
312    return error(instrprof_error::unsupported_version);
313
314  // Read the maximal function count.
315  MaxFunctionCount = endian::readNext<uint64_t, little, unaligned>(Cur);
316
317  // Read the hash type and start offset.
318  IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
319      endian::readNext<uint64_t, little, unaligned>(Cur));
320  if (HashType > IndexedInstrProf::HashT::Last)
321    return error(instrprof_error::unsupported_hash_type);
322  uint64_t HashOffset = endian::readNext<uint64_t, little, unaligned>(Cur);
323
324  // The rest of the file is an on disk hash table.
325  Index.reset(InstrProfReaderIndex::Create(Start + HashOffset, Cur, Start,
326                                           InstrProfLookupTrait(HashType)));
327  // Set up our iterator for readNextRecord.
328  RecordIterator = Index->data_begin();
329
330  return success();
331}
332
333std::error_code IndexedInstrProfReader::getFunctionCounts(
334    StringRef FuncName, uint64_t &FuncHash, std::vector<uint64_t> &Counts) {
335  const auto &Iter = Index->find(FuncName);
336  if (Iter == Index->end())
337    return error(instrprof_error::unknown_function);
338
339  // Found it. Make sure it's valid before giving back a result.
340  const InstrProfRecord &Record = *Iter;
341  if (Record.Name.empty())
342    return error(instrprof_error::malformed);
343  FuncHash = Record.Hash;
344  Counts = Record.Counts;
345  return success();
346}
347
348std::error_code
349IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) {
350  // Are we out of records?
351  if (RecordIterator == Index->data_end())
352    return error(instrprof_error::eof);
353
354  // Read the next one.
355  Record = *RecordIterator;
356  ++RecordIterator;
357  if (Record.Name.empty())
358    return error(instrprof_error::malformed);
359  return success();
360}
361