172208a82SEugene Zelenko //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
2dc707122SEaswaran Raman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dc707122SEaswaran Raman //
7dc707122SEaswaran Raman //===----------------------------------------------------------------------===//
8dc707122SEaswaran Raman //
9dc707122SEaswaran Raman // This file contains support for reading coverage mapping data for
10dc707122SEaswaran Raman // instrumentation based coverage.
11dc707122SEaswaran Raman //
12dc707122SEaswaran Raman //===----------------------------------------------------------------------===//
13dc707122SEaswaran Raman 
144a5ddf80SXinliang David Li #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
15e78d131aSEugene Zelenko #include "llvm/ADT/ArrayRef.h"
16ac40e819SIgor Kudrin #include "llvm/ADT/DenseMap.h"
17e78d131aSEugene Zelenko #include "llvm/ADT/STLExtras.h"
184a5ddf80SXinliang David Li #include "llvm/ADT/SmallVector.h"
19dd1ea9deSVedant Kumar #include "llvm/ADT/Statistic.h"
20e78d131aSEugene Zelenko #include "llvm/ADT/StringRef.h"
21e78d131aSEugene Zelenko #include "llvm/ADT/Triple.h"
22e78d131aSEugene Zelenko #include "llvm/Object/Binary.h"
23e78d131aSEugene Zelenko #include "llvm/Object/Error.h"
24dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h"
25dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.h"
268b6af001SReid Kleckner #include "llvm/Object/COFF.h"
27e78d131aSEugene Zelenko #include "llvm/ProfileData/InstrProf.h"
28e78d131aSEugene Zelenko #include "llvm/Support/Casting.h"
29dd1ea9deSVedant Kumar #include "llvm/Support/Compression.h"
30dc707122SEaswaran Raman #include "llvm/Support/Debug.h"
314a5ddf80SXinliang David Li #include "llvm/Support/Endian.h"
32e78d131aSEugene Zelenko #include "llvm/Support/Error.h"
33e78d131aSEugene Zelenko #include "llvm/Support/ErrorHandling.h"
34dc707122SEaswaran Raman #include "llvm/Support/LEB128.h"
35dc707122SEaswaran Raman #include "llvm/Support/MathExtras.h"
36dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h"
37e78d131aSEugene Zelenko #include <vector>
38dc707122SEaswaran Raman 
39dc707122SEaswaran Raman using namespace llvm;
40dc707122SEaswaran Raman using namespace coverage;
41dc707122SEaswaran Raman using namespace object;
42dc707122SEaswaran Raman 
43dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping"
44dc707122SEaswaran Raman 
45dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records");
46dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");
47dd1ea9deSVedant Kumar 
48dc707122SEaswaran Raman void CoverageMappingIterator::increment() {
49bae83970SVedant Kumar   if (ReadErr != coveragemap_error::success)
50bae83970SVedant Kumar     return;
51bae83970SVedant Kumar 
52dc707122SEaswaran Raman   // Check if all the records were read or if an error occurred while reading
53dc707122SEaswaran Raman   // the next record.
54bae83970SVedant Kumar   if (auto E = Reader->readNextRecord(Record))
559152fd17SVedant Kumar     handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
569152fd17SVedant Kumar       if (CME.get() == coveragemap_error::eof)
57dc707122SEaswaran Raman         *this = CoverageMappingIterator();
589152fd17SVedant Kumar       else
59bae83970SVedant Kumar         ReadErr = CME.get();
609152fd17SVedant Kumar     });
619152fd17SVedant Kumar }
62dc707122SEaswaran Raman 
639152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) {
6472208a82SEugene Zelenko   if (Data.empty())
659152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
66dc707122SEaswaran Raman   unsigned N = 0;
676a0746a9SFangrui Song   Result = decodeULEB128(Data.bytes_begin(), &N);
68dc707122SEaswaran Raman   if (N > Data.size())
699152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
70dc707122SEaswaran Raman   Data = Data.substr(N);
719152fd17SVedant Kumar   return Error::success();
72dc707122SEaswaran Raman }
73dc707122SEaswaran Raman 
749152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
75dc707122SEaswaran Raman   if (auto Err = readULEB128(Result))
76dc707122SEaswaran Raman     return Err;
77dc707122SEaswaran Raman   if (Result >= MaxPlus1)
789152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
799152fd17SVedant Kumar   return Error::success();
80dc707122SEaswaran Raman }
81dc707122SEaswaran Raman 
829152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) {
83dc707122SEaswaran Raman   if (auto Err = readULEB128(Result))
84dc707122SEaswaran Raman     return Err;
85dc707122SEaswaran Raman   // Sanity check the number.
86dc707122SEaswaran Raman   if (Result > Data.size())
879152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
889152fd17SVedant Kumar   return Error::success();
89dc707122SEaswaran Raman }
90dc707122SEaswaran Raman 
919152fd17SVedant Kumar Error RawCoverageReader::readString(StringRef &Result) {
92dc707122SEaswaran Raman   uint64_t Length;
93dc707122SEaswaran Raman   if (auto Err = readSize(Length))
94dc707122SEaswaran Raman     return Err;
95dc707122SEaswaran Raman   Result = Data.substr(0, Length);
96dc707122SEaswaran Raman   Data = Data.substr(Length);
979152fd17SVedant Kumar   return Error::success();
98dc707122SEaswaran Raman }
99dc707122SEaswaran Raman 
100dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::read(
101dd1ea9deSVedant Kumar     CovMapVersion Version,
102dd1ea9deSVedant Kumar     BinaryCoverageReader::DecompressedData &Decompressed) {
103dc707122SEaswaran Raman   uint64_t NumFilenames;
104dc707122SEaswaran Raman   if (auto Err = readSize(NumFilenames))
105dc707122SEaswaran Raman     return Err;
106dd1ea9deSVedant Kumar   if (!NumFilenames)
107dd1ea9deSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
108dd1ea9deSVedant Kumar 
109dd1ea9deSVedant Kumar   if (Version < CovMapVersion::Version4)
110dd1ea9deSVedant Kumar     return readUncompressed(NumFilenames);
111dd1ea9deSVedant Kumar 
112dd1ea9deSVedant Kumar   // The uncompressed length may exceed the size of the encoded filenames.
113dd1ea9deSVedant Kumar   // Skip size validation.
114dd1ea9deSVedant Kumar   uint64_t UncompressedLen;
115dd1ea9deSVedant Kumar   if (auto Err = readULEB128(UncompressedLen))
116dd1ea9deSVedant Kumar     return Err;
117dd1ea9deSVedant Kumar 
118dd1ea9deSVedant Kumar   uint64_t CompressedLen;
119dd1ea9deSVedant Kumar   if (auto Err = readSize(CompressedLen))
120dd1ea9deSVedant Kumar     return Err;
121dd1ea9deSVedant Kumar 
122dd1ea9deSVedant Kumar   if (CompressedLen > 0) {
123dd1ea9deSVedant Kumar     if (!zlib::isAvailable())
124dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(
125dd1ea9deSVedant Kumar           coveragemap_error::decompression_failed);
126dd1ea9deSVedant Kumar 
127dd1ea9deSVedant Kumar     // Allocate memory for the decompressed filenames. Transfer ownership of
128dd1ea9deSVedant Kumar     // the memory to BinaryCoverageReader.
129dd1ea9deSVedant Kumar     auto DecompressedStorage = std::make_unique<SmallVector<char, 0>>();
130dd1ea9deSVedant Kumar     SmallVectorImpl<char> &StorageBuf = *DecompressedStorage.get();
131dd1ea9deSVedant Kumar     Decompressed.push_back(std::move(DecompressedStorage));
132dd1ea9deSVedant Kumar 
133dd1ea9deSVedant Kumar     // Read compressed filenames.
134dd1ea9deSVedant Kumar     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
135dd1ea9deSVedant Kumar     Data = Data.substr(CompressedLen);
136dd1ea9deSVedant Kumar     auto Err =
137dd1ea9deSVedant Kumar         zlib::uncompress(CompressedFilenames, StorageBuf, UncompressedLen);
138dd1ea9deSVedant Kumar     if (Err) {
139dd1ea9deSVedant Kumar       consumeError(std::move(Err));
140dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(
141dd1ea9deSVedant Kumar           coveragemap_error::decompression_failed);
142dd1ea9deSVedant Kumar     }
143dd1ea9deSVedant Kumar 
144dd1ea9deSVedant Kumar     StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
145dd1ea9deSVedant Kumar     RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames);
146dd1ea9deSVedant Kumar     return Delegate.readUncompressed(NumFilenames);
147dd1ea9deSVedant Kumar   }
148dd1ea9deSVedant Kumar 
149dd1ea9deSVedant Kumar   return readUncompressed(NumFilenames);
150dd1ea9deSVedant Kumar }
151dd1ea9deSVedant Kumar 
152dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) {
153dd1ea9deSVedant Kumar   // Read uncompressed filenames.
154dc707122SEaswaran Raman   for (size_t I = 0; I < NumFilenames; ++I) {
155dc707122SEaswaran Raman     StringRef Filename;
156dc707122SEaswaran Raman     if (auto Err = readString(Filename))
157dc707122SEaswaran Raman       return Err;
158dc707122SEaswaran Raman     Filenames.push_back(Filename);
159dc707122SEaswaran Raman   }
1609152fd17SVedant Kumar   return Error::success();
161dc707122SEaswaran Raman }
162dc707122SEaswaran Raman 
1639152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
164dc707122SEaswaran Raman   auto Tag = Value & Counter::EncodingTagMask;
165dc707122SEaswaran Raman   switch (Tag) {
166dc707122SEaswaran Raman   case Counter::Zero:
167dc707122SEaswaran Raman     C = Counter::getZero();
1689152fd17SVedant Kumar     return Error::success();
169dc707122SEaswaran Raman   case Counter::CounterValueReference:
170dc707122SEaswaran Raman     C = Counter::getCounter(Value >> Counter::EncodingTagBits);
1719152fd17SVedant Kumar     return Error::success();
172dc707122SEaswaran Raman   default:
173dc707122SEaswaran Raman     break;
174dc707122SEaswaran Raman   }
175dc707122SEaswaran Raman   Tag -= Counter::Expression;
176dc707122SEaswaran Raman   switch (Tag) {
177dc707122SEaswaran Raman   case CounterExpression::Subtract:
178dc707122SEaswaran Raman   case CounterExpression::Add: {
179dc707122SEaswaran Raman     auto ID = Value >> Counter::EncodingTagBits;
180dc707122SEaswaran Raman     if (ID >= Expressions.size())
1819152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
182dc707122SEaswaran Raman     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
183dc707122SEaswaran Raman     C = Counter::getExpression(ID);
184dc707122SEaswaran Raman     break;
185dc707122SEaswaran Raman   }
186dc707122SEaswaran Raman   default:
1879152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
188dc707122SEaswaran Raman   }
1899152fd17SVedant Kumar   return Error::success();
190dc707122SEaswaran Raman }
191dc707122SEaswaran Raman 
1929152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) {
193dc707122SEaswaran Raman   uint64_t EncodedCounter;
194dc707122SEaswaran Raman   if (auto Err =
195dc707122SEaswaran Raman           readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
196dc707122SEaswaran Raman     return Err;
197dc707122SEaswaran Raman   if (auto Err = decodeCounter(EncodedCounter, C))
198dc707122SEaswaran Raman     return Err;
1999152fd17SVedant Kumar   return Error::success();
200dc707122SEaswaran Raman }
201dc707122SEaswaran Raman 
202dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1
203dc707122SEaswaran Raman                                                    << Counter::EncodingTagBits;
204dc707122SEaswaran Raman 
2055f8f34e4SAdrian Prantl /// Read the sub-array of regions for the given inferred file id.
206dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this
207dc707122SEaswaran Raman /// function.
2089152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray(
209dc707122SEaswaran Raman     std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
210dc707122SEaswaran Raman     size_t NumFileIDs) {
211dc707122SEaswaran Raman   uint64_t NumRegions;
212dc707122SEaswaran Raman   if (auto Err = readSize(NumRegions))
213dc707122SEaswaran Raman     return Err;
214dc707122SEaswaran Raman   unsigned LineStart = 0;
215dc707122SEaswaran Raman   for (size_t I = 0; I < NumRegions; ++I) {
216dc707122SEaswaran Raman     Counter C;
217dc707122SEaswaran Raman     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
218dc707122SEaswaran Raman 
219dc707122SEaswaran Raman     // Read the combined counter + region kind.
220dc707122SEaswaran Raman     uint64_t EncodedCounterAndRegion;
221dc707122SEaswaran Raman     if (auto Err = readIntMax(EncodedCounterAndRegion,
222dc707122SEaswaran Raman                               std::numeric_limits<unsigned>::max()))
223dc707122SEaswaran Raman       return Err;
224dc707122SEaswaran Raman     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
225dc707122SEaswaran Raman     uint64_t ExpandedFileID = 0;
226dc707122SEaswaran Raman     if (Tag != Counter::Zero) {
227dc707122SEaswaran Raman       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
228dc707122SEaswaran Raman         return Err;
229dc707122SEaswaran Raman     } else {
230dc707122SEaswaran Raman       // Is it an expansion region?
231dc707122SEaswaran Raman       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
232dc707122SEaswaran Raman         Kind = CounterMappingRegion::ExpansionRegion;
233dc707122SEaswaran Raman         ExpandedFileID = EncodedCounterAndRegion >>
234dc707122SEaswaran Raman                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
235dc707122SEaswaran Raman         if (ExpandedFileID >= NumFileIDs)
2369152fd17SVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
237dc707122SEaswaran Raman       } else {
238dc707122SEaswaran Raman         switch (EncodedCounterAndRegion >>
239dc707122SEaswaran Raman                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
240dc707122SEaswaran Raman         case CounterMappingRegion::CodeRegion:
241dc707122SEaswaran Raman           // Don't do anything when we have a code region with a zero counter.
242dc707122SEaswaran Raman           break;
243dc707122SEaswaran Raman         case CounterMappingRegion::SkippedRegion:
244dc707122SEaswaran Raman           Kind = CounterMappingRegion::SkippedRegion;
245dc707122SEaswaran Raman           break;
246dc707122SEaswaran Raman         default:
2479152fd17SVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
248dc707122SEaswaran Raman         }
249dc707122SEaswaran Raman       }
250dc707122SEaswaran Raman     }
251dc707122SEaswaran Raman 
252dc707122SEaswaran Raman     // Read the source range.
253dc707122SEaswaran Raman     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
254dc707122SEaswaran Raman     if (auto Err =
255dc707122SEaswaran Raman             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
256dc707122SEaswaran Raman       return Err;
257dc707122SEaswaran Raman     if (auto Err = readULEB128(ColumnStart))
258dc707122SEaswaran Raman       return Err;
259dc707122SEaswaran Raman     if (ColumnStart > std::numeric_limits<unsigned>::max())
2609152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
261dc707122SEaswaran Raman     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
262dc707122SEaswaran Raman       return Err;
263dc707122SEaswaran Raman     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
264dc707122SEaswaran Raman       return Err;
265dc707122SEaswaran Raman     LineStart += LineStartDelta;
266ad8f637bSVedant Kumar 
267ad8f637bSVedant Kumar     // If the high bit of ColumnEnd is set, this is a gap region.
268ad8f637bSVedant Kumar     if (ColumnEnd & (1U << 31)) {
269ad8f637bSVedant Kumar       Kind = CounterMappingRegion::GapRegion;
270ad8f637bSVedant Kumar       ColumnEnd &= ~(1U << 31);
271ad8f637bSVedant Kumar     }
272ad8f637bSVedant Kumar 
273dc707122SEaswaran Raman     // Adjust the column locations for the empty regions that are supposed to
274dc707122SEaswaran Raman     // cover whole lines. Those regions should be encoded with the
275dc707122SEaswaran Raman     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
276dc707122SEaswaran Raman     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
277dc707122SEaswaran Raman     // we set the column range to (0 -> 0) to ensure that the column start and
278dc707122SEaswaran Raman     // column end take up one byte each.
279dc707122SEaswaran Raman     // The std::numeric_limits<unsigned>::max() is used to represent a column
280dc707122SEaswaran Raman     // position at the end of the line without knowing the length of that line.
281dc707122SEaswaran Raman     if (ColumnStart == 0 && ColumnEnd == 0) {
282dc707122SEaswaran Raman       ColumnStart = 1;
283dc707122SEaswaran Raman       ColumnEnd = std::numeric_limits<unsigned>::max();
284dc707122SEaswaran Raman     }
285dc707122SEaswaran Raman 
286d34e60caSNicola Zaghen     LLVM_DEBUG({
287dc707122SEaswaran Raman       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
288dc707122SEaswaran Raman              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
289dc707122SEaswaran Raman              << ColumnEnd << ", ";
290dc707122SEaswaran Raman       if (Kind == CounterMappingRegion::ExpansionRegion)
291dc707122SEaswaran Raman         dbgs() << "Expands to file " << ExpandedFileID;
292dc707122SEaswaran Raman       else
293dc707122SEaswaran Raman         CounterMappingContext(Expressions).dump(C, dbgs());
294dc707122SEaswaran Raman       dbgs() << "\n";
295dc707122SEaswaran Raman     });
296dc707122SEaswaran Raman 
297bae83970SVedant Kumar     auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID,
298bae83970SVedant Kumar                                     LineStart, ColumnStart,
299bae83970SVedant Kumar                                     LineStart + NumLines, ColumnEnd, Kind);
300bae83970SVedant Kumar     if (CMR.startLoc() > CMR.endLoc())
301bae83970SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
302bae83970SVedant Kumar     MappingRegions.push_back(CMR);
303dc707122SEaswaran Raman   }
3049152fd17SVedant Kumar   return Error::success();
305dc707122SEaswaran Raman }
306dc707122SEaswaran Raman 
3079152fd17SVedant Kumar Error RawCoverageMappingReader::read() {
308dc707122SEaswaran Raman   // Read the virtual file mapping.
309e78d131aSEugene Zelenko   SmallVector<unsigned, 8> VirtualFileMapping;
310dc707122SEaswaran Raman   uint64_t NumFileMappings;
311dc707122SEaswaran Raman   if (auto Err = readSize(NumFileMappings))
312dc707122SEaswaran Raman     return Err;
313dc707122SEaswaran Raman   for (size_t I = 0; I < NumFileMappings; ++I) {
314dc707122SEaswaran Raman     uint64_t FilenameIndex;
315dc707122SEaswaran Raman     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
316dc707122SEaswaran Raman       return Err;
317dc707122SEaswaran Raman     VirtualFileMapping.push_back(FilenameIndex);
318dc707122SEaswaran Raman   }
319dc707122SEaswaran Raman 
320dc707122SEaswaran Raman   // Construct the files using unique filenames and virtual file mapping.
321dc707122SEaswaran Raman   for (auto I : VirtualFileMapping) {
322dc707122SEaswaran Raman     Filenames.push_back(TranslationUnitFilenames[I]);
323dc707122SEaswaran Raman   }
324dc707122SEaswaran Raman 
325dc707122SEaswaran Raman   // Read the expressions.
326dc707122SEaswaran Raman   uint64_t NumExpressions;
327dc707122SEaswaran Raman   if (auto Err = readSize(NumExpressions))
328dc707122SEaswaran Raman     return Err;
329dc707122SEaswaran Raman   // Create an array of dummy expressions that get the proper counters
330dc707122SEaswaran Raman   // when the expressions are read, and the proper kinds when the counters
331dc707122SEaswaran Raman   // are decoded.
332dc707122SEaswaran Raman   Expressions.resize(
333dc707122SEaswaran Raman       NumExpressions,
334dc707122SEaswaran Raman       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
335dc707122SEaswaran Raman   for (size_t I = 0; I < NumExpressions; ++I) {
336dc707122SEaswaran Raman     if (auto Err = readCounter(Expressions[I].LHS))
337dc707122SEaswaran Raman       return Err;
338dc707122SEaswaran Raman     if (auto Err = readCounter(Expressions[I].RHS))
339dc707122SEaswaran Raman       return Err;
340dc707122SEaswaran Raman   }
341dc707122SEaswaran Raman 
342dc707122SEaswaran Raman   // Read the mapping regions sub-arrays.
343dc707122SEaswaran Raman   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
344dc707122SEaswaran Raman        InferredFileID < S; ++InferredFileID) {
345dc707122SEaswaran Raman     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
346dc707122SEaswaran Raman                                               VirtualFileMapping.size()))
347dc707122SEaswaran Raman       return Err;
348dc707122SEaswaran Raman   }
349dc707122SEaswaran Raman 
350dc707122SEaswaran Raman   // Set the counters for the expansion regions.
351dc707122SEaswaran Raman   // i.e. Counter of expansion region = counter of the first region
352dc707122SEaswaran Raman   // from the expanded file.
353dc707122SEaswaran Raman   // Perform multiple passes to correctly propagate the counters through
354dc707122SEaswaran Raman   // all the nested expansion regions.
355dc707122SEaswaran Raman   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
356dc707122SEaswaran Raman   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
357dc707122SEaswaran Raman   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
358dc707122SEaswaran Raman     for (auto &R : MappingRegions) {
359dc707122SEaswaran Raman       if (R.Kind != CounterMappingRegion::ExpansionRegion)
360dc707122SEaswaran Raman         continue;
361dc707122SEaswaran Raman       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
362dc707122SEaswaran Raman       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
363dc707122SEaswaran Raman     }
364dc707122SEaswaran Raman     for (auto &R : MappingRegions) {
365dc707122SEaswaran Raman       if (FileIDExpansionRegionMapping[R.FileID]) {
366dc707122SEaswaran Raman         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
367dc707122SEaswaran Raman         FileIDExpansionRegionMapping[R.FileID] = nullptr;
368dc707122SEaswaran Raman       }
369dc707122SEaswaran Raman     }
370dc707122SEaswaran Raman   }
371dc707122SEaswaran Raman 
3729152fd17SVedant Kumar   return Error::success();
373dc707122SEaswaran Raman }
374dc707122SEaswaran Raman 
375ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
376ac40e819SIgor Kudrin   // A dummy coverage mapping data consists of just one region with zero count.
377ac40e819SIgor Kudrin   uint64_t NumFileMappings;
378ac40e819SIgor Kudrin   if (Error Err = readSize(NumFileMappings))
379c55cf4afSBill Wendling     return std::move(Err);
380ac40e819SIgor Kudrin   if (NumFileMappings != 1)
381ac40e819SIgor Kudrin     return false;
382ac40e819SIgor Kudrin   // We don't expect any specific value for the filename index, just skip it.
383ac40e819SIgor Kudrin   uint64_t FilenameIndex;
384ac40e819SIgor Kudrin   if (Error Err =
385ac40e819SIgor Kudrin           readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
386c55cf4afSBill Wendling     return std::move(Err);
387ac40e819SIgor Kudrin   uint64_t NumExpressions;
388ac40e819SIgor Kudrin   if (Error Err = readSize(NumExpressions))
389c55cf4afSBill Wendling     return std::move(Err);
390ac40e819SIgor Kudrin   if (NumExpressions != 0)
391ac40e819SIgor Kudrin     return false;
392ac40e819SIgor Kudrin   uint64_t NumRegions;
393ac40e819SIgor Kudrin   if (Error Err = readSize(NumRegions))
394c55cf4afSBill Wendling     return std::move(Err);
395ac40e819SIgor Kudrin   if (NumRegions != 1)
396ac40e819SIgor Kudrin     return false;
397ac40e819SIgor Kudrin   uint64_t EncodedCounterAndRegion;
398ac40e819SIgor Kudrin   if (Error Err = readIntMax(EncodedCounterAndRegion,
399ac40e819SIgor Kudrin                              std::numeric_limits<unsigned>::max()))
400c55cf4afSBill Wendling     return std::move(Err);
401ac40e819SIgor Kudrin   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
402ac40e819SIgor Kudrin   return Tag == Counter::Zero;
403ac40e819SIgor Kudrin }
404ac40e819SIgor Kudrin 
4059152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) {
406e183340cSFangrui Song   Expected<StringRef> DataOrErr = Section.getContents();
407e183340cSFangrui Song   if (!DataOrErr)
408e183340cSFangrui Song     return DataOrErr.takeError();
409e183340cSFangrui Song   Data = *DataOrErr;
410dc707122SEaswaran Raman   Address = Section.getAddress();
4118b6af001SReid Kleckner 
4128b6af001SReid Kleckner   // If this is a linked PE/COFF file, then we have to skip over the null byte
4138b6af001SReid Kleckner   // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
4148b6af001SReid Kleckner   const ObjectFile *Obj = Section.getObject();
4158b6af001SReid Kleckner   if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
4168b6af001SReid Kleckner     Data = Data.drop_front(1);
4178b6af001SReid Kleckner 
4189152fd17SVedant Kumar   return Error::success();
419dc707122SEaswaran Raman }
420dc707122SEaswaran Raman 
421dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
422dc707122SEaswaran Raman   if (Pointer < Address)
423dc707122SEaswaran Raman     return StringRef();
424dc707122SEaswaran Raman   auto Offset = Pointer - Address;
425dc707122SEaswaran Raman   if (Offset + Size > Data.size())
426dc707122SEaswaran Raman     return StringRef();
427dc707122SEaswaran Raman   return Data.substr(Pointer - Address, Size);
428dc707122SEaswaran Raman }
429dc707122SEaswaran Raman 
430ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
431ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
432ac40e819SIgor Kudrin   // The hash value of dummy mapping records is always zero.
433ac40e819SIgor Kudrin   if (Hash)
434ac40e819SIgor Kudrin     return false;
435ac40e819SIgor Kudrin   return RawCoverageMappingDummyChecker(Mapping).isDummy();
436ac40e819SIgor Kudrin }
437ac40e819SIgor Kudrin 
438dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of
439dd1ea9deSVedant Kumar /// filenames in a vector-like container.
440dd1ea9deSVedant Kumar struct FilenameRange {
441dd1ea9deSVedant Kumar   unsigned StartingIndex;
442dd1ea9deSVedant Kumar   unsigned Length;
443dd1ea9deSVedant Kumar 
444dd1ea9deSVedant Kumar   FilenameRange(unsigned StartingIndex, unsigned Length)
445dd1ea9deSVedant Kumar       : StartingIndex(StartingIndex), Length(Length) {}
446dd1ea9deSVedant Kumar 
447dd1ea9deSVedant Kumar   void markInvalid() { Length = 0; }
448dd1ea9deSVedant Kumar   bool isInvalid() const { return Length == 0; }
449dd1ea9deSVedant Kumar };
450dd1ea9deSVedant Kumar 
451dc707122SEaswaran Raman namespace {
452e78d131aSEugene Zelenko 
453dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module.
454dc707122SEaswaran Raman struct CovMapFuncRecordReader {
455e78d131aSEugene Zelenko   virtual ~CovMapFuncRecordReader() = default;
456e78d131aSEugene Zelenko 
457dd1ea9deSVedant Kumar   // Read a coverage header.
4583739b95dSVedant Kumar   //
459dd1ea9deSVedant Kumar   // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
4603739b95dSVedant Kumar   // mapping data associated with the module.
4613739b95dSVedant Kumar   //
462dd1ea9deSVedant Kumar   // Returns a pointer to the next \c CovHeader if it exists, or to an address
463dd1ea9deSVedant Kumar   // greater than \p CovEnd if not.
464dd1ea9deSVedant Kumar   virtual Expected<const char *>
465dd1ea9deSVedant Kumar   readCoverageHeader(const char *CovBuf, const char *CovBufEnd,
466dd1ea9deSVedant Kumar                      BinaryCoverageReader::DecompressedData &Decompressed) = 0;
467dd1ea9deSVedant Kumar 
468dd1ea9deSVedant Kumar   // Read function records.
469dd1ea9deSVedant Kumar   //
470dd1ea9deSVedant Kumar   // \p FuncRecBuf points to the buffer containing a batch of function records.
471dd1ea9deSVedant Kumar   // \p FuncRecBufEnd points past the end of the batch of records.
472dd1ea9deSVedant Kumar   //
473dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
474dd1ea9deSVedant Kumar   // associated with the function records. It is unused in Version4.
475dd1ea9deSVedant Kumar   //
476dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
477dd1ea9deSVedant Kumar   // mappings associated with the function records. It is unused in Version4.
478dd1ea9deSVedant Kumar   virtual Error readFunctionRecords(const char *FuncRecBuf,
479dd1ea9deSVedant Kumar                                     const char *FuncRecBufEnd,
480dd1ea9deSVedant Kumar                                     Optional<FilenameRange> OutOfLineFileRange,
481dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBuf,
482dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBufEnd) = 0;
483e78d131aSEugene Zelenko 
484dc707122SEaswaran Raman   template <class IntPtrT, support::endianness Endian>
4859152fd17SVedant Kumar   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
486e78d131aSEugene Zelenko   get(CovMapVersion Version, InstrProfSymtab &P,
487dc707122SEaswaran Raman       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
488dc707122SEaswaran Raman       std::vector<StringRef> &F);
489dc707122SEaswaran Raman };
490dc707122SEaswaran Raman 
491dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module.
492e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
493dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
49472208a82SEugene Zelenko   using FuncRecordType =
49572208a82SEugene Zelenko       typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
49672208a82SEugene Zelenko   using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
497dc707122SEaswaran Raman 
498ac40e819SIgor Kudrin   // Maps function's name references to the indexes of their records
499ac40e819SIgor Kudrin   // in \c Records.
500e78d131aSEugene Zelenko   DenseMap<NameRefType, size_t> FunctionRecords;
501dc707122SEaswaran Raman   InstrProfSymtab &ProfileNames;
502dc707122SEaswaran Raman   std::vector<StringRef> &Filenames;
503dc707122SEaswaran Raman   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
504dc707122SEaswaran Raman 
505dd1ea9deSVedant Kumar   // Maps a hash of the filenames in a TU to a \c FileRange. The range
506dd1ea9deSVedant Kumar   // specifies the location of the hashed filenames in \c Filenames.
507dd1ea9deSVedant Kumar   DenseMap<uint64_t, FilenameRange> FileRangeMap;
508dd1ea9deSVedant Kumar 
509ac40e819SIgor Kudrin   // Add the record to the collection if we don't already have a record that
510ac40e819SIgor Kudrin   // points to the same function name. This is useful to ignore the redundant
511ac40e819SIgor Kudrin   // records for the functions with ODR linkage.
512ac40e819SIgor Kudrin   // In addition, prefer records with real coverage mapping data to dummy
513ac40e819SIgor Kudrin   // records, which were emitted for inline functions which were seen but
514ac40e819SIgor Kudrin   // not used in the corresponding translation unit.
515ac40e819SIgor Kudrin   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
516dd1ea9deSVedant Kumar                                      StringRef Mapping,
517dd1ea9deSVedant Kumar                                      FilenameRange FileRange) {
518dd1ea9deSVedant Kumar     ++CovMapNumRecords;
519ac40e819SIgor Kudrin     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
520ac40e819SIgor Kudrin     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
521ac40e819SIgor Kudrin     auto InsertResult =
522ac40e819SIgor Kudrin         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
523ac40e819SIgor Kudrin     if (InsertResult.second) {
524ac40e819SIgor Kudrin       StringRef FuncName;
525ac40e819SIgor Kudrin       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
526ac40e819SIgor Kudrin         return Err;
527b5794ca9SVedant Kumar       if (FuncName.empty())
528b5794ca9SVedant Kumar         return make_error<InstrProfError>(instrprof_error::malformed);
529dd1ea9deSVedant Kumar       ++CovMapNumUsedRecords;
530dd1ea9deSVedant Kumar       Records.emplace_back(Version, FuncName, FuncHash, Mapping,
531dd1ea9deSVedant Kumar                            FileRange.StartingIndex, FileRange.Length);
532ac40e819SIgor Kudrin       return Error::success();
533ac40e819SIgor Kudrin     }
534ac40e819SIgor Kudrin     // Update the existing record if it's a dummy and the new record is real.
535ac40e819SIgor Kudrin     size_t OldRecordIndex = InsertResult.first->second;
536ac40e819SIgor Kudrin     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
537ac40e819SIgor Kudrin         Records[OldRecordIndex];
538ac40e819SIgor Kudrin     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
539ac40e819SIgor Kudrin         OldRecord.FunctionHash, OldRecord.CoverageMapping);
540ac40e819SIgor Kudrin     if (Error Err = OldIsDummyExpected.takeError())
541ac40e819SIgor Kudrin       return Err;
542ac40e819SIgor Kudrin     if (!*OldIsDummyExpected)
543ac40e819SIgor Kudrin       return Error::success();
544ac40e819SIgor Kudrin     Expected<bool> NewIsDummyExpected =
545ac40e819SIgor Kudrin         isCoverageMappingDummy(FuncHash, Mapping);
546ac40e819SIgor Kudrin     if (Error Err = NewIsDummyExpected.takeError())
547ac40e819SIgor Kudrin       return Err;
548ac40e819SIgor Kudrin     if (*NewIsDummyExpected)
549ac40e819SIgor Kudrin       return Error::success();
550dd1ea9deSVedant Kumar     ++CovMapNumUsedRecords;
551ac40e819SIgor Kudrin     OldRecord.FunctionHash = FuncHash;
552ac40e819SIgor Kudrin     OldRecord.CoverageMapping = Mapping;
553dd1ea9deSVedant Kumar     OldRecord.FilenamesBegin = FileRange.StartingIndex;
554dd1ea9deSVedant Kumar     OldRecord.FilenamesSize = FileRange.Length;
555ac40e819SIgor Kudrin     return Error::success();
556ac40e819SIgor Kudrin   }
557ac40e819SIgor Kudrin 
558dc707122SEaswaran Raman public:
559dc707122SEaswaran Raman   VersionedCovMapFuncRecordReader(
560dc707122SEaswaran Raman       InstrProfSymtab &P,
561dc707122SEaswaran Raman       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
562dc707122SEaswaran Raman       std::vector<StringRef> &F)
563dc707122SEaswaran Raman       : ProfileNames(P), Filenames(F), Records(R) {}
564e78d131aSEugene Zelenko 
565e78d131aSEugene Zelenko   ~VersionedCovMapFuncRecordReader() override = default;
566dc707122SEaswaran Raman 
567dd1ea9deSVedant Kumar   Expected<const char *> readCoverageHeader(
568dd1ea9deSVedant Kumar       const char *CovBuf, const char *CovBufEnd,
569dd1ea9deSVedant Kumar       BinaryCoverageReader::DecompressedData &Decompressed) override {
570dc707122SEaswaran Raman     using namespace support;
571e78d131aSEugene Zelenko 
572dd1ea9deSVedant Kumar     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
5739152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
574dd1ea9deSVedant Kumar     auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
575dc707122SEaswaran Raman     uint32_t NRecords = CovHeader->getNRecords<Endian>();
576dc707122SEaswaran Raman     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
577dc707122SEaswaran Raman     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
578dc707122SEaswaran Raman     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
579dd1ea9deSVedant Kumar     CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
580dc707122SEaswaran Raman 
581dc707122SEaswaran Raman     // Skip past the function records, saving the start and end for later.
582dd1ea9deSVedant Kumar     // This is a no-op in Version4 (function records are read after all headers
583dd1ea9deSVedant Kumar     // are read).
584dd1ea9deSVedant Kumar     const char *FuncRecBuf = nullptr;
585dd1ea9deSVedant Kumar     const char *FuncRecBufEnd = nullptr;
586dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
587dd1ea9deSVedant Kumar       FuncRecBuf = CovBuf;
588dd1ea9deSVedant Kumar     CovBuf += NRecords * sizeof(FuncRecordType);
589dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
590dd1ea9deSVedant Kumar       FuncRecBufEnd = CovBuf;
591dc707122SEaswaran Raman 
592dc707122SEaswaran Raman     // Get the filenames.
593dd1ea9deSVedant Kumar     if (CovBuf + FilenamesSize > CovBufEnd)
5949152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
595dc707122SEaswaran Raman     size_t FilenamesBegin = Filenames.size();
596dd1ea9deSVedant Kumar     StringRef FilenameRegion(CovBuf, FilenamesSize);
597dd1ea9deSVedant Kumar     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
598dd1ea9deSVedant Kumar     if (auto Err = Reader.read(Version, Decompressed))
599c55cf4afSBill Wendling       return std::move(Err);
600dd1ea9deSVedant Kumar     CovBuf += FilenamesSize;
601dd1ea9deSVedant Kumar     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
602dd1ea9deSVedant Kumar 
603dd1ea9deSVedant Kumar     if (Version == CovMapVersion::Version4) {
604dd1ea9deSVedant Kumar       // Map a hash of the filenames region to the filename range associated
605dd1ea9deSVedant Kumar       // with this coverage header.
606dd1ea9deSVedant Kumar       int64_t FilenamesRef =
607dd1ea9deSVedant Kumar           llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
608dd1ea9deSVedant Kumar       auto Insert =
609dd1ea9deSVedant Kumar           FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
610dd1ea9deSVedant Kumar       if (!Insert.second) {
611dd1ea9deSVedant Kumar         // The same filenames ref was encountered twice. It's possible that
612dd1ea9deSVedant Kumar         // the associated filenames are the same.
613dd1ea9deSVedant Kumar         auto It = Filenames.begin();
614dd1ea9deSVedant Kumar         FilenameRange &OrigRange = Insert.first->getSecond();
615dd1ea9deSVedant Kumar         if (std::equal(It + OrigRange.StartingIndex,
616dd1ea9deSVedant Kumar                        It + OrigRange.StartingIndex + OrigRange.Length,
617dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex,
618dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex + FileRange.Length))
619dd1ea9deSVedant Kumar           // Map the new range to the original one.
620dd1ea9deSVedant Kumar           FileRange = OrigRange;
621dd1ea9deSVedant Kumar         else
622dd1ea9deSVedant Kumar           // This is a hash collision. Mark the filenames ref invalid.
623dd1ea9deSVedant Kumar           OrigRange.markInvalid();
624dd1ea9deSVedant Kumar       }
625dd1ea9deSVedant Kumar     }
626dc707122SEaswaran Raman 
627dc707122SEaswaran Raman     // We'll read the coverage mapping records in the loop below.
628dd1ea9deSVedant Kumar     // This is a no-op in Version4 (coverage mappings are not affixed to the
629dd1ea9deSVedant Kumar     // coverage header).
630dd1ea9deSVedant Kumar     const char *MappingBuf = CovBuf;
631dd1ea9deSVedant Kumar     if (Version == CovMapVersion::Version4 && CoverageSize != 0)
6329152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
633dd1ea9deSVedant Kumar     CovBuf += CoverageSize;
634dd1ea9deSVedant Kumar     const char *MappingEnd = CovBuf;
635dd1ea9deSVedant Kumar 
636dd1ea9deSVedant Kumar     if (CovBuf > CovBufEnd)
637dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
638dd1ea9deSVedant Kumar 
639dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4) {
640dd1ea9deSVedant Kumar       // Read each function record.
641dd1ea9deSVedant Kumar       if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
642dd1ea9deSVedant Kumar                                         MappingBuf, MappingEnd))
643dd1ea9deSVedant Kumar         return std::move(E);
644dd1ea9deSVedant Kumar     }
645dd1ea9deSVedant Kumar 
646dc707122SEaswaran Raman     // Each coverage map has an alignment of 8, so we need to adjust alignment
647dc707122SEaswaran Raman     // before reading the next map.
648dd1ea9deSVedant Kumar     CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
649dc707122SEaswaran Raman 
650dd1ea9deSVedant Kumar     return CovBuf;
65199317124SVedant Kumar   }
652dd1ea9deSVedant Kumar 
653dd1ea9deSVedant Kumar   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
654dd1ea9deSVedant Kumar                             Optional<FilenameRange> OutOfLineFileRange,
655dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBuf,
656dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBufEnd) override {
657dd1ea9deSVedant Kumar     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
658dd1ea9deSVedant Kumar     while ((const char *)CFR < FuncRecBufEnd) {
659dd1ea9deSVedant Kumar       // Validate the length of the coverage mapping for this function.
660dd1ea9deSVedant Kumar       const char *NextMappingBuf;
661dd1ea9deSVedant Kumar       const FuncRecordType *NextCFR;
662dd1ea9deSVedant Kumar       std::tie(NextMappingBuf, NextCFR) =
663dd1ea9deSVedant Kumar           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
664dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4)
665dd1ea9deSVedant Kumar         if (NextMappingBuf > OutOfLineMappingBufEnd)
666dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
667dd1ea9deSVedant Kumar 
668dd1ea9deSVedant Kumar       // Look up the set of filenames associated with this function record.
669dd1ea9deSVedant Kumar       Optional<FilenameRange> FileRange;
670dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4) {
671dd1ea9deSVedant Kumar         FileRange = OutOfLineFileRange;
672dd1ea9deSVedant Kumar       } else {
673dd1ea9deSVedant Kumar         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
674dd1ea9deSVedant Kumar         auto It = FileRangeMap.find(FilenamesRef);
675dd1ea9deSVedant Kumar         if (It == FileRangeMap.end())
676dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
677dd1ea9deSVedant Kumar         else
678dd1ea9deSVedant Kumar           FileRange = It->getSecond();
679dd1ea9deSVedant Kumar       }
680dd1ea9deSVedant Kumar 
681dd1ea9deSVedant Kumar       // Now, read the coverage data.
682dd1ea9deSVedant Kumar       if (FileRange && !FileRange->isInvalid()) {
683dd1ea9deSVedant Kumar         StringRef Mapping =
684dd1ea9deSVedant Kumar             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
685dd1ea9deSVedant Kumar         if (Version == CovMapVersion::Version4 &&
686dd1ea9deSVedant Kumar             Mapping.data() + Mapping.size() > FuncRecBufEnd)
687dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
688dd1ea9deSVedant Kumar         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
689dd1ea9deSVedant Kumar           return Err;
690dd1ea9deSVedant Kumar       }
691dd1ea9deSVedant Kumar 
692dd1ea9deSVedant Kumar       std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
693dd1ea9deSVedant Kumar     }
694dd1ea9deSVedant Kumar     return Error::success();
695dc707122SEaswaran Raman   }
696dc707122SEaswaran Raman };
697e78d131aSEugene Zelenko 
698dc707122SEaswaran Raman } // end anonymous namespace
699dc707122SEaswaran Raman 
700dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian>
7019152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
702e78d131aSEugene Zelenko     CovMapVersion Version, InstrProfSymtab &P,
703dc707122SEaswaran Raman     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
704dc707122SEaswaran Raman     std::vector<StringRef> &F) {
705dc707122SEaswaran Raman   using namespace coverage;
706e78d131aSEugene Zelenko 
707dc707122SEaswaran Raman   switch (Version) {
708dc707122SEaswaran Raman   case CovMapVersion::Version1:
7090eaee545SJonas Devlieghere     return std::make_unique<VersionedCovMapFuncRecordReader<
710dc707122SEaswaran Raman         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
711dc707122SEaswaran Raman   case CovMapVersion::Version2:
712ad8f637bSVedant Kumar   case CovMapVersion::Version3:
713dd1ea9deSVedant Kumar   case CovMapVersion::Version4:
714dc707122SEaswaran Raman     // Decompress the name data.
7159152fd17SVedant Kumar     if (Error E = P.create(P.getNameData()))
716c55cf4afSBill Wendling       return std::move(E);
717ad8f637bSVedant Kumar     if (Version == CovMapVersion::Version2)
7180eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
719dc707122SEaswaran Raman           CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
720dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version3)
7210eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
722ad8f637bSVedant Kumar           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F);
723dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version4)
724dd1ea9deSVedant Kumar       return std::make_unique<VersionedCovMapFuncRecordReader<
725dd1ea9deSVedant Kumar           CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F);
726dc707122SEaswaran Raman   }
727dc707122SEaswaran Raman   llvm_unreachable("Unsupported version");
728dc707122SEaswaran Raman }
729dc707122SEaswaran Raman 
730dc707122SEaswaran Raman template <typename T, support::endianness Endian>
7319152fd17SVedant Kumar static Error readCoverageMappingData(
732dd1ea9deSVedant Kumar     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
733dc707122SEaswaran Raman     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
734dd1ea9deSVedant Kumar     std::vector<StringRef> &Filenames,
735dd1ea9deSVedant Kumar     BinaryCoverageReader::DecompressedData &Decompressed) {
736dc707122SEaswaran Raman   using namespace coverage;
737e78d131aSEugene Zelenko 
738dc707122SEaswaran Raman   // Read the records in the coverage data section.
739dc707122SEaswaran Raman   auto CovHeader =
740dd1ea9deSVedant Kumar       reinterpret_cast<const CovMapHeader *>(CovMap.data());
741dc707122SEaswaran Raman   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
742e78d131aSEugene Zelenko   if (Version > CovMapVersion::CurrentVersion)
7439152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
7449152fd17SVedant Kumar   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
745dc707122SEaswaran Raman       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
746dc707122SEaswaran Raman                                              Filenames);
7479152fd17SVedant Kumar   if (Error E = ReaderExpected.takeError())
7489152fd17SVedant Kumar     return E;
7499152fd17SVedant Kumar   auto Reader = std::move(ReaderExpected.get());
750dd1ea9deSVedant Kumar   const char *CovBuf = CovMap.data();
751dd1ea9deSVedant Kumar   const char *CovBufEnd = CovBuf + CovMap.size();
752dd1ea9deSVedant Kumar   const char *FuncRecBuf = FuncRecords.data();
753dd1ea9deSVedant Kumar   const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
754dd1ea9deSVedant Kumar   while (CovBuf < CovBufEnd) {
755dd1ea9deSVedant Kumar     // Read the current coverage header & filename data.
756dd1ea9deSVedant Kumar     //
757dd1ea9deSVedant Kumar     // Prior to Version4, this also reads all function records affixed to the
758dd1ea9deSVedant Kumar     // header.
759dd1ea9deSVedant Kumar     //
760dd1ea9deSVedant Kumar     // Return a pointer to the next coverage header.
761dd1ea9deSVedant Kumar     auto NextOrErr =
762dd1ea9deSVedant Kumar         Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed);
763dd1ea9deSVedant Kumar     if (auto E = NextOrErr.takeError())
7649152fd17SVedant Kumar       return E;
765dd1ea9deSVedant Kumar     CovBuf = NextOrErr.get();
766dc707122SEaswaran Raman   }
767dd1ea9deSVedant Kumar   // In Version4, function records are not affixed to coverage headers. Read
768dd1ea9deSVedant Kumar   // the records from their dedicated section.
769dd1ea9deSVedant Kumar   if (Version == CovMapVersion::Version4)
770dd1ea9deSVedant Kumar     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr,
771dd1ea9deSVedant Kumar                                        nullptr);
7729152fd17SVedant Kumar   return Error::success();
773dc707122SEaswaran Raman }
774e78d131aSEugene Zelenko 
775dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata";
776dc707122SEaswaran Raman 
777901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>>
778901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer(
77980cd518bSVedant Kumar     StringRef Coverage, std::string &&FuncRecords, InstrProfSymtab &&ProfileNames,
780dd1ea9deSVedant Kumar     uint8_t BytesInAddress, support::endianness Endian) {
78180cd518bSVedant Kumar   std::unique_ptr<BinaryCoverageReader> Reader(
78280cd518bSVedant Kumar       new BinaryCoverageReader(std::move(FuncRecords)));
783901d04fcSVedant Kumar   Reader->ProfileNames = std::move(ProfileNames);
78480cd518bSVedant Kumar   StringRef FuncRecordsRef = Reader->FuncRecords;
785901d04fcSVedant Kumar   if (BytesInAddress == 4 && Endian == support::endianness::little) {
786901d04fcSVedant Kumar     if (Error E =
787901d04fcSVedant Kumar             readCoverageMappingData<uint32_t, support::endianness::little>(
78880cd518bSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecordsRef,
789dd1ea9deSVedant Kumar                 Reader->MappingRecords, Reader->Filenames,
790dd1ea9deSVedant Kumar                 Reader->Decompressed))
791c55cf4afSBill Wendling       return std::move(E);
792901d04fcSVedant Kumar   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
793901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
79480cd518bSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecordsRef,
79580cd518bSVedant Kumar             Reader->MappingRecords, Reader->Filenames, Reader->Decompressed))
796c55cf4afSBill Wendling       return std::move(E);
797901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
798901d04fcSVedant Kumar     if (Error E =
799901d04fcSVedant Kumar             readCoverageMappingData<uint64_t, support::endianness::little>(
80080cd518bSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecordsRef,
801dd1ea9deSVedant Kumar                 Reader->MappingRecords, Reader->Filenames,
802dd1ea9deSVedant Kumar                 Reader->Decompressed))
803c55cf4afSBill Wendling       return std::move(E);
804901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
805901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
80680cd518bSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecordsRef,
80780cd518bSVedant Kumar             Reader->MappingRecords, Reader->Filenames, Reader->Decompressed))
808c55cf4afSBill Wendling       return std::move(E);
809901d04fcSVedant Kumar   } else
810901d04fcSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
811c55cf4afSBill Wendling   return std::move(Reader);
812901d04fcSVedant Kumar }
813901d04fcSVedant Kumar 
814901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
815901d04fcSVedant Kumar loadTestingFormat(StringRef Data) {
816901d04fcSVedant Kumar   uint8_t BytesInAddress = 8;
817901d04fcSVedant Kumar   support::endianness Endian = support::endianness::little;
818dc707122SEaswaran Raman 
819dc707122SEaswaran Raman   Data = Data.substr(StringRef(TestingFormatMagic).size());
82072208a82SEugene Zelenko   if (Data.empty())
8219152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
822dc707122SEaswaran Raman   unsigned N = 0;
8236a0746a9SFangrui Song   uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
824dc707122SEaswaran Raman   if (N > Data.size())
8259152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
826dc707122SEaswaran Raman   Data = Data.substr(N);
82772208a82SEugene Zelenko   if (Data.empty())
8289152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
829dc707122SEaswaran Raman   N = 0;
8306a0746a9SFangrui Song   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
831dc707122SEaswaran Raman   if (N > Data.size())
8329152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
833dc707122SEaswaran Raman   Data = Data.substr(N);
834dc707122SEaswaran Raman   if (Data.size() < ProfileNamesSize)
8359152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
836901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
8379152fd17SVedant Kumar   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
838c55cf4afSBill Wendling     return std::move(E);
839901d04fcSVedant Kumar   StringRef CoverageMapping = Data.substr(ProfileNamesSize);
840eb103073SIgor Kudrin   // Skip the padding bytes because coverage map data has an alignment of 8.
84172208a82SEugene Zelenko   if (CoverageMapping.empty())
8429152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
843ce56e1a1SGuillaume Chatelet   size_t Pad = offsetToAlignedAddr(CoverageMapping.data(), Align(8));
844eb103073SIgor Kudrin   if (CoverageMapping.size() < Pad)
8459152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
846eb103073SIgor Kudrin   CoverageMapping = CoverageMapping.substr(Pad);
847901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
848dd1ea9deSVedant Kumar       CoverageMapping, "", std::move(ProfileNames), BytesInAddress, Endian);
849dc707122SEaswaran Raman }
850dc707122SEaswaran Raman 
85180cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats
85280cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF.
85380cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
85480cd518bSVedant Kumar                                                         StringRef Name) {
8558b6af001SReid Kleckner   // On COFF, the object file section name may end in "$M". This tells the
8568b6af001SReid Kleckner   // linker to sort these sections between "$A" and "$Z". The linker removes the
8578b6af001SReid Kleckner   // dollar and everything after it in the final binary. Do the same to match.
8588b6af001SReid Kleckner   bool IsCOFF = isa<COFFObjectFile>(OF);
8598b6af001SReid Kleckner   auto stripSuffix = [IsCOFF](StringRef N) {
8608b6af001SReid Kleckner     return IsCOFF ? N.split('$').first : N;
8618b6af001SReid Kleckner   };
8628b6af001SReid Kleckner   Name = stripSuffix(Name);
8638b6af001SReid Kleckner 
86480cd518bSVedant Kumar   std::vector<SectionRef> Sections;
865dc707122SEaswaran Raman   for (const auto &Section : OF.sections()) {
866bcc00e1aSGeorge Rimar     Expected<StringRef> NameOrErr = Section.getName();
867bcc00e1aSGeorge Rimar     if (!NameOrErr)
868bcc00e1aSGeorge Rimar       return NameOrErr.takeError();
869bcc00e1aSGeorge Rimar     if (stripSuffix(*NameOrErr) == Name)
87080cd518bSVedant Kumar       Sections.push_back(Section);
871dc707122SEaswaran Raman   }
87280cd518bSVedant Kumar   if (Sections.empty())
8739152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
87480cd518bSVedant Kumar   return Sections;
875dc707122SEaswaran Raman }
876dc707122SEaswaran Raman 
877901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
878901d04fcSVedant Kumar loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
879dc707122SEaswaran Raman   std::unique_ptr<ObjectFile> OF;
880e78d131aSEugene Zelenko   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
881dc707122SEaswaran Raman     // If we have a universal binary, try to look up the object for the
882dc707122SEaswaran Raman     // appropriate architecture.
8834fd11c1eSAlexander Shaposhnikov     auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
8849acb1099SKevin Enderby     if (!ObjectFileOrErr)
8859acb1099SKevin Enderby       return ObjectFileOrErr.takeError();
886dc707122SEaswaran Raman     OF = std::move(ObjectFileOrErr.get());
887e78d131aSEugene Zelenko   } else if (isa<ObjectFile>(Bin.get())) {
888dc707122SEaswaran Raman     // For any other object file, upcast and take ownership.
889e78d131aSEugene Zelenko     OF.reset(cast<ObjectFile>(Bin.release()));
890dc707122SEaswaran Raman     // If we've asked for a particular arch, make sure they match.
891dc707122SEaswaran Raman     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
8929152fd17SVedant Kumar       return errorCodeToError(object_error::arch_not_found);
893dc707122SEaswaran Raman   } else
894dc707122SEaswaran Raman     // We can only handle object files.
8959152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
896dc707122SEaswaran Raman 
897dc707122SEaswaran Raman   // The coverage uses native pointer sizes for the object it's written in.
898901d04fcSVedant Kumar   uint8_t BytesInAddress = OF->getBytesInAddress();
899901d04fcSVedant Kumar   support::endianness Endian = OF->isLittleEndian()
900901d04fcSVedant Kumar                                    ? support::endianness::little
901dc707122SEaswaran Raman                                    : support::endianness::big;
902dc707122SEaswaran Raman 
903dc707122SEaswaran Raman   // Look for the sections that we are interested in.
9041a6a2b64SVedant Kumar   auto ObjFormat = OF->getTripleObjectFormat();
9054a5ddf80SXinliang David Li   auto NamesSection =
90680cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
9071a6a2b64SVedant Kumar                                                  /*AddSegmentInfo=*/false));
9089152fd17SVedant Kumar   if (auto E = NamesSection.takeError())
909c55cf4afSBill Wendling     return std::move(E);
9104a5ddf80SXinliang David Li   auto CoverageSection =
91180cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
9121a6a2b64SVedant Kumar                                                   /*AddSegmentInfo=*/false));
9139152fd17SVedant Kumar   if (auto E = CoverageSection.takeError())
914c55cf4afSBill Wendling     return std::move(E);
91580cd518bSVedant Kumar   std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
91680cd518bSVedant Kumar   if (CoverageSectionRefs.size() != 1)
91780cd518bSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
91880cd518bSVedant Kumar   auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
919901d04fcSVedant Kumar   if (!CoverageMappingOrErr)
920901d04fcSVedant Kumar     return CoverageMappingOrErr.takeError();
921dd1ea9deSVedant Kumar   StringRef CoverageMapping = CoverageMappingOrErr.get();
922e183340cSFangrui Song 
923901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
92480cd518bSVedant Kumar   std::vector<SectionRef> NamesSectionRefs = *NamesSection;
92580cd518bSVedant Kumar   if (NamesSectionRefs.size() != 1)
92680cd518bSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
92780cd518bSVedant Kumar   if (Error E = ProfileNames.create(NamesSectionRefs.back()))
928c55cf4afSBill Wendling     return std::move(E);
929dc707122SEaswaran Raman 
930dd1ea9deSVedant Kumar   // Look for the coverage records section (Version4 only).
93180cd518bSVedant Kumar   std::string FuncRecords;
93280cd518bSVedant Kumar   auto CoverageRecordsSections =
93380cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
934dd1ea9deSVedant Kumar                                                   /*AddSegmentInfo=*/false));
93580cd518bSVedant Kumar   if (auto E = CoverageRecordsSections.takeError())
936dd1ea9deSVedant Kumar     consumeError(std::move(E));
937dd1ea9deSVedant Kumar   else {
93880cd518bSVedant Kumar     for (SectionRef Section : *CoverageRecordsSections) {
93980cd518bSVedant Kumar       auto CoverageRecordsOrErr = Section.getContents();
940dd1ea9deSVedant Kumar       if (!CoverageRecordsOrErr)
941dd1ea9deSVedant Kumar         return CoverageRecordsOrErr.takeError();
94280cd518bSVedant Kumar       FuncRecords += CoverageRecordsOrErr.get();
94380cd518bSVedant Kumar       while (FuncRecords.size() % 8 != 0)
94480cd518bSVedant Kumar         FuncRecords += '\0';
94580cd518bSVedant Kumar     }
946dd1ea9deSVedant Kumar   }
947dd1ea9deSVedant Kumar 
948901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
94980cd518bSVedant Kumar       CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
95080cd518bSVedant Kumar       BytesInAddress, Endian);
951dc707122SEaswaran Raman }
952dc707122SEaswaran Raman 
953*7fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin.
954*7fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
955*7fafaa07SVedant Kumar   // If we have a universal binary and Arch doesn't identify any of its slices,
956*7fafaa07SVedant Kumar   // it's user error.
957*7fafaa07SVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
958*7fafaa07SVedant Kumar     for (auto &ObjForArch : Universal->objects())
959*7fafaa07SVedant Kumar       if (Arch == ObjForArch.getArchFlagName())
960*7fafaa07SVedant Kumar         return false;
961*7fafaa07SVedant Kumar     return true;
962*7fafaa07SVedant Kumar   }
963*7fafaa07SVedant Kumar   return false;
964*7fafaa07SVedant Kumar }
965*7fafaa07SVedant Kumar 
966901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
967901d04fcSVedant Kumar BinaryCoverageReader::create(
968901d04fcSVedant Kumar     MemoryBufferRef ObjectBuffer, StringRef Arch,
969901d04fcSVedant Kumar     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) {
970901d04fcSVedant Kumar   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
971dc707122SEaswaran Raman 
972901d04fcSVedant Kumar   if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
973dc707122SEaswaran Raman     // This is a special format used for testing.
974901d04fcSVedant Kumar     auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer());
975901d04fcSVedant Kumar     if (!ReaderOrErr)
976901d04fcSVedant Kumar       return ReaderOrErr.takeError();
977901d04fcSVedant Kumar     Readers.push_back(std::move(ReaderOrErr.get()));
978c55cf4afSBill Wendling     return std::move(Readers);
979901d04fcSVedant Kumar   }
980dc707122SEaswaran Raman 
981901d04fcSVedant Kumar   auto BinOrErr = createBinary(ObjectBuffer);
982901d04fcSVedant Kumar   if (!BinOrErr)
983901d04fcSVedant Kumar     return BinOrErr.takeError();
984901d04fcSVedant Kumar   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
985901d04fcSVedant Kumar 
986*7fafaa07SVedant Kumar   if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
987*7fafaa07SVedant Kumar     return make_error<CoverageMapError>(
988*7fafaa07SVedant Kumar         coveragemap_error::invalid_or_missing_arch_specifier);
989*7fafaa07SVedant Kumar 
990901d04fcSVedant Kumar   // MachO universal binaries which contain archives need to be treated as
991901d04fcSVedant Kumar   // archives, not as regular binaries.
992901d04fcSVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
993901d04fcSVedant Kumar     for (auto &ObjForArch : Universal->objects()) {
994901d04fcSVedant Kumar       // Skip slices within the universal binary which target the wrong arch.
995901d04fcSVedant Kumar       std::string ObjArch = ObjForArch.getArchFlagName();
996901d04fcSVedant Kumar       if (Arch != ObjArch)
997901d04fcSVedant Kumar         continue;
998901d04fcSVedant Kumar 
999901d04fcSVedant Kumar       auto ArchiveOrErr = ObjForArch.getAsArchive();
1000901d04fcSVedant Kumar       if (!ArchiveOrErr) {
1001901d04fcSVedant Kumar         // If this is not an archive, try treating it as a regular object.
1002901d04fcSVedant Kumar         consumeError(ArchiveOrErr.takeError());
1003901d04fcSVedant Kumar         break;
1004901d04fcSVedant Kumar       }
1005901d04fcSVedant Kumar 
1006901d04fcSVedant Kumar       return BinaryCoverageReader::create(
1007901d04fcSVedant Kumar           ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers);
1008901d04fcSVedant Kumar     }
1009901d04fcSVedant Kumar   }
1010901d04fcSVedant Kumar 
1011901d04fcSVedant Kumar   // Load coverage out of archive members.
1012901d04fcSVedant Kumar   if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
1013901d04fcSVedant Kumar     Error Err = Error::success();
1014901d04fcSVedant Kumar     for (auto &Child : Ar->children(Err)) {
1015901d04fcSVedant Kumar       Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
1016901d04fcSVedant Kumar       if (!ChildBufOrErr)
1017901d04fcSVedant Kumar         return ChildBufOrErr.takeError();
1018901d04fcSVedant Kumar 
1019901d04fcSVedant Kumar       auto ChildReadersOrErr = BinaryCoverageReader::create(
1020901d04fcSVedant Kumar           ChildBufOrErr.get(), Arch, ObjectFileBuffers);
1021901d04fcSVedant Kumar       if (!ChildReadersOrErr)
1022901d04fcSVedant Kumar         return ChildReadersOrErr.takeError();
1023901d04fcSVedant Kumar       for (auto &Reader : ChildReadersOrErr.get())
1024901d04fcSVedant Kumar         Readers.push_back(std::move(Reader));
1025901d04fcSVedant Kumar     }
1026901d04fcSVedant Kumar     if (Err)
1027c55cf4afSBill Wendling       return std::move(Err);
1028901d04fcSVedant Kumar 
1029901d04fcSVedant Kumar     // Thin archives reference object files outside of the archive file, i.e.
1030901d04fcSVedant Kumar     // files which reside in memory not owned by the caller. Transfer ownership
1031901d04fcSVedant Kumar     // to the caller.
1032901d04fcSVedant Kumar     if (Ar->isThin())
1033901d04fcSVedant Kumar       for (auto &Buffer : Ar->takeThinBuffers())
1034901d04fcSVedant Kumar         ObjectFileBuffers.push_back(std::move(Buffer));
1035901d04fcSVedant Kumar 
1036c55cf4afSBill Wendling     return std::move(Readers);
1037901d04fcSVedant Kumar   }
1038901d04fcSVedant Kumar 
1039901d04fcSVedant Kumar   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch);
1040901d04fcSVedant Kumar   if (!ReaderOrErr)
1041901d04fcSVedant Kumar     return ReaderOrErr.takeError();
1042901d04fcSVedant Kumar   Readers.push_back(std::move(ReaderOrErr.get()));
1043c55cf4afSBill Wendling   return std::move(Readers);
1044dc707122SEaswaran Raman }
1045dc707122SEaswaran Raman 
10469152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
1047dc707122SEaswaran Raman   if (CurrentRecord >= MappingRecords.size())
10489152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::eof);
1049dc707122SEaswaran Raman 
1050dc707122SEaswaran Raman   FunctionsFilenames.clear();
1051dc707122SEaswaran Raman   Expressions.clear();
1052dc707122SEaswaran Raman   MappingRegions.clear();
1053dc707122SEaswaran Raman   auto &R = MappingRecords[CurrentRecord];
1054dc707122SEaswaran Raman   RawCoverageMappingReader Reader(
1055dc707122SEaswaran Raman       R.CoverageMapping,
1056dc707122SEaswaran Raman       makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
1057dc707122SEaswaran Raman       FunctionsFilenames, Expressions, MappingRegions);
1058dc707122SEaswaran Raman   if (auto Err = Reader.read())
1059dc707122SEaswaran Raman     return Err;
1060dc707122SEaswaran Raman 
1061dc707122SEaswaran Raman   Record.FunctionName = R.FunctionName;
1062dc707122SEaswaran Raman   Record.FunctionHash = R.FunctionHash;
1063dc707122SEaswaran Raman   Record.Filenames = FunctionsFilenames;
1064dc707122SEaswaran Raman   Record.Expressions = Expressions;
1065dc707122SEaswaran Raman   Record.MappingRegions = MappingRegions;
1066dc707122SEaswaran Raman 
1067dc707122SEaswaran Raman   ++CurrentRecord;
10689152fd17SVedant Kumar   return Error::success();
1069dc707122SEaswaran Raman }
1070