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"
19*dd1ea9deSVedant 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"
29*dd1ea9deSVedant 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 
45*dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records");
46*dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");
47*dd1ea9deSVedant 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 
100*dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::read(
101*dd1ea9deSVedant Kumar     CovMapVersion Version,
102*dd1ea9deSVedant Kumar     BinaryCoverageReader::DecompressedData &Decompressed) {
103dc707122SEaswaran Raman   uint64_t NumFilenames;
104dc707122SEaswaran Raman   if (auto Err = readSize(NumFilenames))
105dc707122SEaswaran Raman     return Err;
106*dd1ea9deSVedant Kumar   if (!NumFilenames)
107*dd1ea9deSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
108*dd1ea9deSVedant Kumar 
109*dd1ea9deSVedant Kumar   if (Version < CovMapVersion::Version4)
110*dd1ea9deSVedant Kumar     return readUncompressed(NumFilenames);
111*dd1ea9deSVedant Kumar 
112*dd1ea9deSVedant Kumar   // The uncompressed length may exceed the size of the encoded filenames.
113*dd1ea9deSVedant Kumar   // Skip size validation.
114*dd1ea9deSVedant Kumar   uint64_t UncompressedLen;
115*dd1ea9deSVedant Kumar   if (auto Err = readULEB128(UncompressedLen))
116*dd1ea9deSVedant Kumar     return Err;
117*dd1ea9deSVedant Kumar 
118*dd1ea9deSVedant Kumar   uint64_t CompressedLen;
119*dd1ea9deSVedant Kumar   if (auto Err = readSize(CompressedLen))
120*dd1ea9deSVedant Kumar     return Err;
121*dd1ea9deSVedant Kumar 
122*dd1ea9deSVedant Kumar   if (CompressedLen > 0) {
123*dd1ea9deSVedant Kumar     if (!zlib::isAvailable())
124*dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(
125*dd1ea9deSVedant Kumar           coveragemap_error::decompression_failed);
126*dd1ea9deSVedant Kumar 
127*dd1ea9deSVedant Kumar     // Allocate memory for the decompressed filenames. Transfer ownership of
128*dd1ea9deSVedant Kumar     // the memory to BinaryCoverageReader.
129*dd1ea9deSVedant Kumar     auto DecompressedStorage = std::make_unique<SmallVector<char, 0>>();
130*dd1ea9deSVedant Kumar     SmallVectorImpl<char> &StorageBuf = *DecompressedStorage.get();
131*dd1ea9deSVedant Kumar     Decompressed.push_back(std::move(DecompressedStorage));
132*dd1ea9deSVedant Kumar 
133*dd1ea9deSVedant Kumar     // Read compressed filenames.
134*dd1ea9deSVedant Kumar     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
135*dd1ea9deSVedant Kumar     Data = Data.substr(CompressedLen);
136*dd1ea9deSVedant Kumar     auto Err =
137*dd1ea9deSVedant Kumar         zlib::uncompress(CompressedFilenames, StorageBuf, UncompressedLen);
138*dd1ea9deSVedant Kumar     if (Err) {
139*dd1ea9deSVedant Kumar       consumeError(std::move(Err));
140*dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(
141*dd1ea9deSVedant Kumar           coveragemap_error::decompression_failed);
142*dd1ea9deSVedant Kumar     }
143*dd1ea9deSVedant Kumar 
144*dd1ea9deSVedant Kumar     StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
145*dd1ea9deSVedant Kumar     RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames);
146*dd1ea9deSVedant Kumar     return Delegate.readUncompressed(NumFilenames);
147*dd1ea9deSVedant Kumar   }
148*dd1ea9deSVedant Kumar 
149*dd1ea9deSVedant Kumar   return readUncompressed(NumFilenames);
150*dd1ea9deSVedant Kumar }
151*dd1ea9deSVedant Kumar 
152*dd1ea9deSVedant Kumar Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) {
153*dd1ea9deSVedant 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 
438*dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of
439*dd1ea9deSVedant Kumar /// filenames in a vector-like container.
440*dd1ea9deSVedant Kumar struct FilenameRange {
441*dd1ea9deSVedant Kumar   unsigned StartingIndex;
442*dd1ea9deSVedant Kumar   unsigned Length;
443*dd1ea9deSVedant Kumar 
444*dd1ea9deSVedant Kumar   FilenameRange(unsigned StartingIndex, unsigned Length)
445*dd1ea9deSVedant Kumar       : StartingIndex(StartingIndex), Length(Length) {}
446*dd1ea9deSVedant Kumar 
447*dd1ea9deSVedant Kumar   void markInvalid() { Length = 0; }
448*dd1ea9deSVedant Kumar   bool isInvalid() const { return Length == 0; }
449*dd1ea9deSVedant Kumar };
450*dd1ea9deSVedant Kumar 
451dc707122SEaswaran Raman namespace {
452e78d131aSEugene Zelenko 
453*dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module.
454dc707122SEaswaran Raman struct CovMapFuncRecordReader {
455e78d131aSEugene Zelenko   virtual ~CovMapFuncRecordReader() = default;
456e78d131aSEugene Zelenko 
457*dd1ea9deSVedant Kumar   // Read a coverage header.
4583739b95dSVedant Kumar   //
459*dd1ea9deSVedant Kumar   // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
4603739b95dSVedant Kumar   // mapping data associated with the module.
4613739b95dSVedant Kumar   //
462*dd1ea9deSVedant Kumar   // Returns a pointer to the next \c CovHeader if it exists, or to an address
463*dd1ea9deSVedant Kumar   // greater than \p CovEnd if not.
464*dd1ea9deSVedant Kumar   virtual Expected<const char *>
465*dd1ea9deSVedant Kumar   readCoverageHeader(const char *CovBuf, const char *CovBufEnd,
466*dd1ea9deSVedant Kumar                      BinaryCoverageReader::DecompressedData &Decompressed) = 0;
467*dd1ea9deSVedant Kumar 
468*dd1ea9deSVedant Kumar   // Read function records.
469*dd1ea9deSVedant Kumar   //
470*dd1ea9deSVedant Kumar   // \p FuncRecBuf points to the buffer containing a batch of function records.
471*dd1ea9deSVedant Kumar   // \p FuncRecBufEnd points past the end of the batch of records.
472*dd1ea9deSVedant Kumar   //
473*dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
474*dd1ea9deSVedant Kumar   // associated with the function records. It is unused in Version4.
475*dd1ea9deSVedant Kumar   //
476*dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
477*dd1ea9deSVedant Kumar   // mappings associated with the function records. It is unused in Version4.
478*dd1ea9deSVedant Kumar   virtual Error readFunctionRecords(const char *FuncRecBuf,
479*dd1ea9deSVedant Kumar                                     const char *FuncRecBufEnd,
480*dd1ea9deSVedant Kumar                                     Optional<FilenameRange> OutOfLineFileRange,
481*dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBuf,
482*dd1ea9deSVedant 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 
505*dd1ea9deSVedant Kumar   // Maps a hash of the filenames in a TU to a \c FileRange. The range
506*dd1ea9deSVedant Kumar   // specifies the location of the hashed filenames in \c Filenames.
507*dd1ea9deSVedant Kumar   DenseMap<uint64_t, FilenameRange> FileRangeMap;
508*dd1ea9deSVedant 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,
516*dd1ea9deSVedant Kumar                                      StringRef Mapping,
517*dd1ea9deSVedant Kumar                                      FilenameRange FileRange) {
518*dd1ea9deSVedant 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);
529*dd1ea9deSVedant Kumar       ++CovMapNumUsedRecords;
530*dd1ea9deSVedant Kumar       Records.emplace_back(Version, FuncName, FuncHash, Mapping,
531*dd1ea9deSVedant 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();
550*dd1ea9deSVedant Kumar     ++CovMapNumUsedRecords;
551ac40e819SIgor Kudrin     OldRecord.FunctionHash = FuncHash;
552ac40e819SIgor Kudrin     OldRecord.CoverageMapping = Mapping;
553*dd1ea9deSVedant Kumar     OldRecord.FilenamesBegin = FileRange.StartingIndex;
554*dd1ea9deSVedant 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 
567*dd1ea9deSVedant Kumar   Expected<const char *> readCoverageHeader(
568*dd1ea9deSVedant Kumar       const char *CovBuf, const char *CovBufEnd,
569*dd1ea9deSVedant Kumar       BinaryCoverageReader::DecompressedData &Decompressed) override {
570dc707122SEaswaran Raman     using namespace support;
571e78d131aSEugene Zelenko 
572*dd1ea9deSVedant Kumar     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
5739152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
574*dd1ea9deSVedant 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);
579*dd1ea9deSVedant Kumar     CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
580dc707122SEaswaran Raman 
581dc707122SEaswaran Raman     // Skip past the function records, saving the start and end for later.
582*dd1ea9deSVedant Kumar     // This is a no-op in Version4 (function records are read after all headers
583*dd1ea9deSVedant Kumar     // are read).
584*dd1ea9deSVedant Kumar     const char *FuncRecBuf = nullptr;
585*dd1ea9deSVedant Kumar     const char *FuncRecBufEnd = nullptr;
586*dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
587*dd1ea9deSVedant Kumar       FuncRecBuf = CovBuf;
588*dd1ea9deSVedant Kumar     CovBuf += NRecords * sizeof(FuncRecordType);
589*dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
590*dd1ea9deSVedant Kumar       FuncRecBufEnd = CovBuf;
591dc707122SEaswaran Raman 
592dc707122SEaswaran Raman     // Get the filenames.
593*dd1ea9deSVedant Kumar     if (CovBuf + FilenamesSize > CovBufEnd)
5949152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
595dc707122SEaswaran Raman     size_t FilenamesBegin = Filenames.size();
596*dd1ea9deSVedant Kumar     StringRef FilenameRegion(CovBuf, FilenamesSize);
597*dd1ea9deSVedant Kumar     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
598*dd1ea9deSVedant Kumar     if (auto Err = Reader.read(Version, Decompressed))
599c55cf4afSBill Wendling       return std::move(Err);
600*dd1ea9deSVedant Kumar     CovBuf += FilenamesSize;
601*dd1ea9deSVedant Kumar     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
602*dd1ea9deSVedant Kumar 
603*dd1ea9deSVedant Kumar     if (Version == CovMapVersion::Version4) {
604*dd1ea9deSVedant Kumar       // Map a hash of the filenames region to the filename range associated
605*dd1ea9deSVedant Kumar       // with this coverage header.
606*dd1ea9deSVedant Kumar       int64_t FilenamesRef =
607*dd1ea9deSVedant Kumar           llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
608*dd1ea9deSVedant Kumar       auto Insert =
609*dd1ea9deSVedant Kumar           FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
610*dd1ea9deSVedant Kumar       if (!Insert.second) {
611*dd1ea9deSVedant Kumar         // The same filenames ref was encountered twice. It's possible that
612*dd1ea9deSVedant Kumar         // the associated filenames are the same.
613*dd1ea9deSVedant Kumar         auto It = Filenames.begin();
614*dd1ea9deSVedant Kumar         FilenameRange &OrigRange = Insert.first->getSecond();
615*dd1ea9deSVedant Kumar         if (std::equal(It + OrigRange.StartingIndex,
616*dd1ea9deSVedant Kumar                        It + OrigRange.StartingIndex + OrigRange.Length,
617*dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex,
618*dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex + FileRange.Length))
619*dd1ea9deSVedant Kumar           // Map the new range to the original one.
620*dd1ea9deSVedant Kumar           FileRange = OrigRange;
621*dd1ea9deSVedant Kumar         else
622*dd1ea9deSVedant Kumar           // This is a hash collision. Mark the filenames ref invalid.
623*dd1ea9deSVedant Kumar           OrigRange.markInvalid();
624*dd1ea9deSVedant Kumar       }
625*dd1ea9deSVedant Kumar     }
626dc707122SEaswaran Raman 
627dc707122SEaswaran Raman     // We'll read the coverage mapping records in the loop below.
628*dd1ea9deSVedant Kumar     // This is a no-op in Version4 (coverage mappings are not affixed to the
629*dd1ea9deSVedant Kumar     // coverage header).
630*dd1ea9deSVedant Kumar     const char *MappingBuf = CovBuf;
631*dd1ea9deSVedant Kumar     if (Version == CovMapVersion::Version4 && CoverageSize != 0)
6329152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
633*dd1ea9deSVedant Kumar     CovBuf += CoverageSize;
634*dd1ea9deSVedant Kumar     const char *MappingEnd = CovBuf;
635*dd1ea9deSVedant Kumar 
636*dd1ea9deSVedant Kumar     if (CovBuf > CovBufEnd)
637*dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
638*dd1ea9deSVedant Kumar 
639*dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4) {
640*dd1ea9deSVedant Kumar       // Read each function record.
641*dd1ea9deSVedant Kumar       if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
642*dd1ea9deSVedant Kumar                                         MappingBuf, MappingEnd))
643*dd1ea9deSVedant Kumar         return std::move(E);
644*dd1ea9deSVedant Kumar     }
645*dd1ea9deSVedant Kumar 
646dc707122SEaswaran Raman     // Each coverage map has an alignment of 8, so we need to adjust alignment
647dc707122SEaswaran Raman     // before reading the next map.
648*dd1ea9deSVedant Kumar     CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
649dc707122SEaswaran Raman 
650*dd1ea9deSVedant Kumar     return CovBuf;
65199317124SVedant Kumar   }
652*dd1ea9deSVedant Kumar 
653*dd1ea9deSVedant Kumar   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
654*dd1ea9deSVedant Kumar                             Optional<FilenameRange> OutOfLineFileRange,
655*dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBuf,
656*dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBufEnd) override {
657*dd1ea9deSVedant Kumar     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
658*dd1ea9deSVedant Kumar     while ((const char *)CFR < FuncRecBufEnd) {
659*dd1ea9deSVedant Kumar       // Validate the length of the coverage mapping for this function.
660*dd1ea9deSVedant Kumar       const char *NextMappingBuf;
661*dd1ea9deSVedant Kumar       const FuncRecordType *NextCFR;
662*dd1ea9deSVedant Kumar       std::tie(NextMappingBuf, NextCFR) =
663*dd1ea9deSVedant Kumar           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
664*dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4)
665*dd1ea9deSVedant Kumar         if (NextMappingBuf > OutOfLineMappingBufEnd)
666*dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
667*dd1ea9deSVedant Kumar 
668*dd1ea9deSVedant Kumar       // Look up the set of filenames associated with this function record.
669*dd1ea9deSVedant Kumar       Optional<FilenameRange> FileRange;
670*dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4) {
671*dd1ea9deSVedant Kumar         FileRange = OutOfLineFileRange;
672*dd1ea9deSVedant Kumar       } else {
673*dd1ea9deSVedant Kumar         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
674*dd1ea9deSVedant Kumar         auto It = FileRangeMap.find(FilenamesRef);
675*dd1ea9deSVedant Kumar         if (It == FileRangeMap.end())
676*dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
677*dd1ea9deSVedant Kumar         else
678*dd1ea9deSVedant Kumar           FileRange = It->getSecond();
679*dd1ea9deSVedant Kumar       }
680*dd1ea9deSVedant Kumar 
681*dd1ea9deSVedant Kumar       // Now, read the coverage data.
682*dd1ea9deSVedant Kumar       if (FileRange && !FileRange->isInvalid()) {
683*dd1ea9deSVedant Kumar         StringRef Mapping =
684*dd1ea9deSVedant Kumar             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
685*dd1ea9deSVedant Kumar         if (Version == CovMapVersion::Version4 &&
686*dd1ea9deSVedant Kumar             Mapping.data() + Mapping.size() > FuncRecBufEnd)
687*dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
688*dd1ea9deSVedant Kumar         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
689*dd1ea9deSVedant Kumar           return Err;
690*dd1ea9deSVedant Kumar       }
691*dd1ea9deSVedant Kumar 
692*dd1ea9deSVedant Kumar       std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
693*dd1ea9deSVedant Kumar     }
694*dd1ea9deSVedant 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:
713*dd1ea9deSVedant 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);
720*dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version3)
7210eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
722ad8f637bSVedant Kumar           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F);
723*dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version4)
724*dd1ea9deSVedant Kumar       return std::make_unique<VersionedCovMapFuncRecordReader<
725*dd1ea9deSVedant 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(
732*dd1ea9deSVedant Kumar     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
733dc707122SEaswaran Raman     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
734*dd1ea9deSVedant Kumar     std::vector<StringRef> &Filenames,
735*dd1ea9deSVedant 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 =
740*dd1ea9deSVedant 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());
750*dd1ea9deSVedant Kumar   const char *CovBuf = CovMap.data();
751*dd1ea9deSVedant Kumar   const char *CovBufEnd = CovBuf + CovMap.size();
752*dd1ea9deSVedant Kumar   const char *FuncRecBuf = FuncRecords.data();
753*dd1ea9deSVedant Kumar   const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
754*dd1ea9deSVedant Kumar   while (CovBuf < CovBufEnd) {
755*dd1ea9deSVedant Kumar     // Read the current coverage header & filename data.
756*dd1ea9deSVedant Kumar     //
757*dd1ea9deSVedant Kumar     // Prior to Version4, this also reads all function records affixed to the
758*dd1ea9deSVedant Kumar     // header.
759*dd1ea9deSVedant Kumar     //
760*dd1ea9deSVedant Kumar     // Return a pointer to the next coverage header.
761*dd1ea9deSVedant Kumar     auto NextOrErr =
762*dd1ea9deSVedant Kumar         Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed);
763*dd1ea9deSVedant Kumar     if (auto E = NextOrErr.takeError())
7649152fd17SVedant Kumar       return E;
765*dd1ea9deSVedant Kumar     CovBuf = NextOrErr.get();
766dc707122SEaswaran Raman   }
767*dd1ea9deSVedant Kumar   // In Version4, function records are not affixed to coverage headers. Read
768*dd1ea9deSVedant Kumar   // the records from their dedicated section.
769*dd1ea9deSVedant Kumar   if (Version == CovMapVersion::Version4)
770*dd1ea9deSVedant Kumar     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr,
771*dd1ea9deSVedant 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(
779*dd1ea9deSVedant Kumar     StringRef Coverage, StringRef FuncRecords, InstrProfSymtab &&ProfileNames,
780*dd1ea9deSVedant Kumar     uint8_t BytesInAddress, support::endianness Endian) {
781901d04fcSVedant Kumar   std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
782901d04fcSVedant Kumar   Reader->ProfileNames = std::move(ProfileNames);
783901d04fcSVedant Kumar   if (BytesInAddress == 4 && Endian == support::endianness::little) {
784901d04fcSVedant Kumar     if (Error E =
785901d04fcSVedant Kumar             readCoverageMappingData<uint32_t, support::endianness::little>(
786*dd1ea9deSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecords,
787*dd1ea9deSVedant Kumar                 Reader->MappingRecords, Reader->Filenames,
788*dd1ea9deSVedant Kumar                 Reader->Decompressed))
789c55cf4afSBill Wendling       return std::move(E);
790901d04fcSVedant Kumar   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
791901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
792*dd1ea9deSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecords, Reader->MappingRecords,
793*dd1ea9deSVedant Kumar             Reader->Filenames, Reader->Decompressed))
794c55cf4afSBill Wendling       return std::move(E);
795901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
796901d04fcSVedant Kumar     if (Error E =
797901d04fcSVedant Kumar             readCoverageMappingData<uint64_t, support::endianness::little>(
798*dd1ea9deSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecords,
799*dd1ea9deSVedant Kumar                 Reader->MappingRecords, Reader->Filenames,
800*dd1ea9deSVedant Kumar                 Reader->Decompressed))
801c55cf4afSBill Wendling       return std::move(E);
802901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
803901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
804*dd1ea9deSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecords, Reader->MappingRecords,
805*dd1ea9deSVedant Kumar             Reader->Filenames, Reader->Decompressed))
806c55cf4afSBill Wendling       return std::move(E);
807901d04fcSVedant Kumar   } else
808901d04fcSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
809c55cf4afSBill Wendling   return std::move(Reader);
810901d04fcSVedant Kumar }
811901d04fcSVedant Kumar 
812901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
813901d04fcSVedant Kumar loadTestingFormat(StringRef Data) {
814901d04fcSVedant Kumar   uint8_t BytesInAddress = 8;
815901d04fcSVedant Kumar   support::endianness Endian = support::endianness::little;
816dc707122SEaswaran Raman 
817dc707122SEaswaran Raman   Data = Data.substr(StringRef(TestingFormatMagic).size());
81872208a82SEugene Zelenko   if (Data.empty())
8199152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
820dc707122SEaswaran Raman   unsigned N = 0;
8216a0746a9SFangrui Song   uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
822dc707122SEaswaran Raman   if (N > Data.size())
8239152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
824dc707122SEaswaran Raman   Data = Data.substr(N);
82572208a82SEugene Zelenko   if (Data.empty())
8269152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
827dc707122SEaswaran Raman   N = 0;
8286a0746a9SFangrui Song   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
829dc707122SEaswaran Raman   if (N > Data.size())
8309152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
831dc707122SEaswaran Raman   Data = Data.substr(N);
832dc707122SEaswaran Raman   if (Data.size() < ProfileNamesSize)
8339152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
834901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
8359152fd17SVedant Kumar   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
836c55cf4afSBill Wendling     return std::move(E);
837901d04fcSVedant Kumar   StringRef CoverageMapping = Data.substr(ProfileNamesSize);
838eb103073SIgor Kudrin   // Skip the padding bytes because coverage map data has an alignment of 8.
83972208a82SEugene Zelenko   if (CoverageMapping.empty())
8409152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
841ce56e1a1SGuillaume Chatelet   size_t Pad = offsetToAlignedAddr(CoverageMapping.data(), Align(8));
842eb103073SIgor Kudrin   if (CoverageMapping.size() < Pad)
8439152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
844eb103073SIgor Kudrin   CoverageMapping = CoverageMapping.substr(Pad);
845901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
846*dd1ea9deSVedant Kumar       CoverageMapping, "", std::move(ProfileNames), BytesInAddress, Endian);
847dc707122SEaswaran Raman }
848dc707122SEaswaran Raman 
8499152fd17SVedant Kumar static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) {
8508b6af001SReid Kleckner   // On COFF, the object file section name may end in "$M". This tells the
8518b6af001SReid Kleckner   // linker to sort these sections between "$A" and "$Z". The linker removes the
8528b6af001SReid Kleckner   // dollar and everything after it in the final binary. Do the same to match.
8538b6af001SReid Kleckner   bool IsCOFF = isa<COFFObjectFile>(OF);
8548b6af001SReid Kleckner   auto stripSuffix = [IsCOFF](StringRef N) {
8558b6af001SReid Kleckner     return IsCOFF ? N.split('$').first : N;
8568b6af001SReid Kleckner   };
8578b6af001SReid Kleckner   Name = stripSuffix(Name);
8588b6af001SReid Kleckner 
859dc707122SEaswaran Raman   for (const auto &Section : OF.sections()) {
860bcc00e1aSGeorge Rimar     Expected<StringRef> NameOrErr = Section.getName();
861bcc00e1aSGeorge Rimar     if (!NameOrErr)
862bcc00e1aSGeorge Rimar       return NameOrErr.takeError();
863bcc00e1aSGeorge Rimar     if (stripSuffix(*NameOrErr) == Name)
864dc707122SEaswaran Raman       return Section;
865dc707122SEaswaran Raman   }
8669152fd17SVedant Kumar   return make_error<CoverageMapError>(coveragemap_error::no_data_found);
867dc707122SEaswaran Raman }
868dc707122SEaswaran Raman 
869901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
870901d04fcSVedant Kumar loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
871dc707122SEaswaran Raman   std::unique_ptr<ObjectFile> OF;
872e78d131aSEugene Zelenko   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
873dc707122SEaswaran Raman     // If we have a universal binary, try to look up the object for the
874dc707122SEaswaran Raman     // appropriate architecture.
8754fd11c1eSAlexander Shaposhnikov     auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
8769acb1099SKevin Enderby     if (!ObjectFileOrErr)
8779acb1099SKevin Enderby       return ObjectFileOrErr.takeError();
878dc707122SEaswaran Raman     OF = std::move(ObjectFileOrErr.get());
879e78d131aSEugene Zelenko   } else if (isa<ObjectFile>(Bin.get())) {
880dc707122SEaswaran Raman     // For any other object file, upcast and take ownership.
881e78d131aSEugene Zelenko     OF.reset(cast<ObjectFile>(Bin.release()));
882dc707122SEaswaran Raman     // If we've asked for a particular arch, make sure they match.
883dc707122SEaswaran Raman     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
8849152fd17SVedant Kumar       return errorCodeToError(object_error::arch_not_found);
885dc707122SEaswaran Raman   } else
886dc707122SEaswaran Raman     // We can only handle object files.
8879152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
888dc707122SEaswaran Raman 
889dc707122SEaswaran Raman   // The coverage uses native pointer sizes for the object it's written in.
890901d04fcSVedant Kumar   uint8_t BytesInAddress = OF->getBytesInAddress();
891901d04fcSVedant Kumar   support::endianness Endian = OF->isLittleEndian()
892901d04fcSVedant Kumar                                    ? support::endianness::little
893dc707122SEaswaran Raman                                    : support::endianness::big;
894dc707122SEaswaran Raman 
895dc707122SEaswaran Raman   // Look for the sections that we are interested in.
8961a6a2b64SVedant Kumar   auto ObjFormat = OF->getTripleObjectFormat();
8974a5ddf80SXinliang David Li   auto NamesSection =
8981a6a2b64SVedant Kumar       lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
8991a6a2b64SVedant Kumar                                                  /*AddSegmentInfo=*/false));
9009152fd17SVedant Kumar   if (auto E = NamesSection.takeError())
901c55cf4afSBill Wendling     return std::move(E);
9024a5ddf80SXinliang David Li   auto CoverageSection =
9031a6a2b64SVedant Kumar       lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
9041a6a2b64SVedant Kumar                                                  /*AddSegmentInfo=*/false));
9059152fd17SVedant Kumar   if (auto E = CoverageSection.takeError())
906c55cf4afSBill Wendling     return std::move(E);
907901d04fcSVedant Kumar   auto CoverageMappingOrErr = CoverageSection->getContents();
908901d04fcSVedant Kumar   if (!CoverageMappingOrErr)
909901d04fcSVedant Kumar     return CoverageMappingOrErr.takeError();
910*dd1ea9deSVedant Kumar   StringRef CoverageMapping = CoverageMappingOrErr.get();
911e183340cSFangrui Song 
912901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
9139152fd17SVedant Kumar   if (Error E = ProfileNames.create(*NamesSection))
914c55cf4afSBill Wendling     return std::move(E);
915dc707122SEaswaran Raman 
916*dd1ea9deSVedant Kumar   // Look for the coverage records section (Version4 only).
917*dd1ea9deSVedant Kumar   StringRef FuncRecords;
918*dd1ea9deSVedant Kumar   auto CoverageRecordsSection =
919*dd1ea9deSVedant Kumar       lookupSection(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
920*dd1ea9deSVedant Kumar                                                  /*AddSegmentInfo=*/false));
921*dd1ea9deSVedant Kumar   if (auto E = CoverageRecordsSection.takeError())
922*dd1ea9deSVedant Kumar     consumeError(std::move(E));
923*dd1ea9deSVedant Kumar   else {
924*dd1ea9deSVedant Kumar     auto CoverageRecordsOrErr = CoverageRecordsSection->getContents();
925*dd1ea9deSVedant Kumar     if (!CoverageRecordsOrErr)
926*dd1ea9deSVedant Kumar       return CoverageRecordsOrErr.takeError();
927*dd1ea9deSVedant Kumar     FuncRecords = CoverageRecordsOrErr.get();
928*dd1ea9deSVedant Kumar   }
929*dd1ea9deSVedant Kumar 
930901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
931*dd1ea9deSVedant Kumar       CoverageMapping, FuncRecords, std::move(ProfileNames), BytesInAddress,
932901d04fcSVedant Kumar       Endian);
933dc707122SEaswaran Raman }
934dc707122SEaswaran Raman 
935901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
936901d04fcSVedant Kumar BinaryCoverageReader::create(
937901d04fcSVedant Kumar     MemoryBufferRef ObjectBuffer, StringRef Arch,
938901d04fcSVedant Kumar     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) {
939901d04fcSVedant Kumar   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
940dc707122SEaswaran Raman 
941901d04fcSVedant Kumar   if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
942dc707122SEaswaran Raman     // This is a special format used for testing.
943901d04fcSVedant Kumar     auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer());
944901d04fcSVedant Kumar     if (!ReaderOrErr)
945901d04fcSVedant Kumar       return ReaderOrErr.takeError();
946901d04fcSVedant Kumar     Readers.push_back(std::move(ReaderOrErr.get()));
947c55cf4afSBill Wendling     return std::move(Readers);
948901d04fcSVedant Kumar   }
949dc707122SEaswaran Raman 
950901d04fcSVedant Kumar   auto BinOrErr = createBinary(ObjectBuffer);
951901d04fcSVedant Kumar   if (!BinOrErr)
952901d04fcSVedant Kumar     return BinOrErr.takeError();
953901d04fcSVedant Kumar   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
954901d04fcSVedant Kumar 
955901d04fcSVedant Kumar   // MachO universal binaries which contain archives need to be treated as
956901d04fcSVedant Kumar   // archives, not as regular binaries.
957901d04fcSVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
958901d04fcSVedant Kumar     for (auto &ObjForArch : Universal->objects()) {
959901d04fcSVedant Kumar       // Skip slices within the universal binary which target the wrong arch.
960901d04fcSVedant Kumar       std::string ObjArch = ObjForArch.getArchFlagName();
961901d04fcSVedant Kumar       if (Arch != ObjArch)
962901d04fcSVedant Kumar         continue;
963901d04fcSVedant Kumar 
964901d04fcSVedant Kumar       auto ArchiveOrErr = ObjForArch.getAsArchive();
965901d04fcSVedant Kumar       if (!ArchiveOrErr) {
966901d04fcSVedant Kumar         // If this is not an archive, try treating it as a regular object.
967901d04fcSVedant Kumar         consumeError(ArchiveOrErr.takeError());
968901d04fcSVedant Kumar         break;
969901d04fcSVedant Kumar       }
970901d04fcSVedant Kumar 
971901d04fcSVedant Kumar       return BinaryCoverageReader::create(
972901d04fcSVedant Kumar           ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers);
973901d04fcSVedant Kumar     }
974901d04fcSVedant Kumar   }
975901d04fcSVedant Kumar 
976901d04fcSVedant Kumar   // Load coverage out of archive members.
977901d04fcSVedant Kumar   if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
978901d04fcSVedant Kumar     Error Err = Error::success();
979901d04fcSVedant Kumar     for (auto &Child : Ar->children(Err)) {
980901d04fcSVedant Kumar       Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
981901d04fcSVedant Kumar       if (!ChildBufOrErr)
982901d04fcSVedant Kumar         return ChildBufOrErr.takeError();
983901d04fcSVedant Kumar 
984901d04fcSVedant Kumar       auto ChildReadersOrErr = BinaryCoverageReader::create(
985901d04fcSVedant Kumar           ChildBufOrErr.get(), Arch, ObjectFileBuffers);
986901d04fcSVedant Kumar       if (!ChildReadersOrErr)
987901d04fcSVedant Kumar         return ChildReadersOrErr.takeError();
988901d04fcSVedant Kumar       for (auto &Reader : ChildReadersOrErr.get())
989901d04fcSVedant Kumar         Readers.push_back(std::move(Reader));
990901d04fcSVedant Kumar     }
991901d04fcSVedant Kumar     if (Err)
992c55cf4afSBill Wendling       return std::move(Err);
993901d04fcSVedant Kumar 
994901d04fcSVedant Kumar     // Thin archives reference object files outside of the archive file, i.e.
995901d04fcSVedant Kumar     // files which reside in memory not owned by the caller. Transfer ownership
996901d04fcSVedant Kumar     // to the caller.
997901d04fcSVedant Kumar     if (Ar->isThin())
998901d04fcSVedant Kumar       for (auto &Buffer : Ar->takeThinBuffers())
999901d04fcSVedant Kumar         ObjectFileBuffers.push_back(std::move(Buffer));
1000901d04fcSVedant Kumar 
1001c55cf4afSBill Wendling     return std::move(Readers);
1002901d04fcSVedant Kumar   }
1003901d04fcSVedant Kumar 
1004901d04fcSVedant Kumar   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch);
1005901d04fcSVedant Kumar   if (!ReaderOrErr)
1006901d04fcSVedant Kumar     return ReaderOrErr.takeError();
1007901d04fcSVedant Kumar   Readers.push_back(std::move(ReaderOrErr.get()));
1008c55cf4afSBill Wendling   return std::move(Readers);
1009dc707122SEaswaran Raman }
1010dc707122SEaswaran Raman 
10119152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
1012dc707122SEaswaran Raman   if (CurrentRecord >= MappingRecords.size())
10139152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::eof);
1014dc707122SEaswaran Raman 
1015dc707122SEaswaran Raman   FunctionsFilenames.clear();
1016dc707122SEaswaran Raman   Expressions.clear();
1017dc707122SEaswaran Raman   MappingRegions.clear();
1018dc707122SEaswaran Raman   auto &R = MappingRecords[CurrentRecord];
1019dc707122SEaswaran Raman   RawCoverageMappingReader Reader(
1020dc707122SEaswaran Raman       R.CoverageMapping,
1021dc707122SEaswaran Raman       makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
1022dc707122SEaswaran Raman       FunctionsFilenames, Expressions, MappingRegions);
1023dc707122SEaswaran Raman   if (auto Err = Reader.read())
1024dc707122SEaswaran Raman     return Err;
1025dc707122SEaswaran Raman 
1026dc707122SEaswaran Raman   Record.FunctionName = R.FunctionName;
1027dc707122SEaswaran Raman   Record.FunctionHash = R.FunctionHash;
1028dc707122SEaswaran Raman   Record.Filenames = FunctionsFilenames;
1029dc707122SEaswaran Raman   Record.Expressions = Expressions;
1030dc707122SEaswaran Raman   Record.MappingRegions = MappingRegions;
1031dc707122SEaswaran Raman 
1032dc707122SEaswaran Raman   ++CurrentRecord;
10339152fd17SVedant Kumar   return Error::success();
1034dc707122SEaswaran Raman }
1035