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) {
216*9f2967bcSAlan Phipps     Counter C, C2;
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;
226*9f2967bcSAlan Phipps 
227*9f2967bcSAlan Phipps     // If Tag does not represent a ZeroCounter, then it is understood to refer
228*9f2967bcSAlan Phipps     // to a counter or counter expression with region kind assumed to be
229*9f2967bcSAlan Phipps     // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
230*9f2967bcSAlan Phipps     // referenced counter or counter expression (and nothing else).
231*9f2967bcSAlan Phipps     //
232*9f2967bcSAlan Phipps     // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
233*9f2967bcSAlan Phipps     // then EncodedCounterAndRegion is interpreted to represent an
234*9f2967bcSAlan Phipps     // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
235*9f2967bcSAlan Phipps     // interpreted to refer to a specific region kind, after which additional
236*9f2967bcSAlan Phipps     // fields may be read (e.g. BranchRegions have two encoded counters that
237*9f2967bcSAlan Phipps     // follow an encoded region kind value).
238dc707122SEaswaran Raman     if (Tag != Counter::Zero) {
239dc707122SEaswaran Raman       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
240dc707122SEaswaran Raman         return Err;
241dc707122SEaswaran Raman     } else {
242dc707122SEaswaran Raman       // Is it an expansion region?
243dc707122SEaswaran Raman       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
244dc707122SEaswaran Raman         Kind = CounterMappingRegion::ExpansionRegion;
245dc707122SEaswaran Raman         ExpandedFileID = EncodedCounterAndRegion >>
246dc707122SEaswaran Raman                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
247dc707122SEaswaran Raman         if (ExpandedFileID >= NumFileIDs)
2489152fd17SVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
249dc707122SEaswaran Raman       } else {
250dc707122SEaswaran Raman         switch (EncodedCounterAndRegion >>
251dc707122SEaswaran Raman                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
252dc707122SEaswaran Raman         case CounterMappingRegion::CodeRegion:
253dc707122SEaswaran Raman           // Don't do anything when we have a code region with a zero counter.
254dc707122SEaswaran Raman           break;
255dc707122SEaswaran Raman         case CounterMappingRegion::SkippedRegion:
256dc707122SEaswaran Raman           Kind = CounterMappingRegion::SkippedRegion;
257dc707122SEaswaran Raman           break;
258*9f2967bcSAlan Phipps         case CounterMappingRegion::BranchRegion:
259*9f2967bcSAlan Phipps           // For a Branch Region, read two successive counters.
260*9f2967bcSAlan Phipps           Kind = CounterMappingRegion::BranchRegion;
261*9f2967bcSAlan Phipps           if (auto Err = readCounter(C))
262*9f2967bcSAlan Phipps             return Err;
263*9f2967bcSAlan Phipps           if (auto Err = readCounter(C2))
264*9f2967bcSAlan Phipps             return Err;
265*9f2967bcSAlan Phipps           break;
266dc707122SEaswaran Raman         default:
2679152fd17SVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
268dc707122SEaswaran Raman         }
269dc707122SEaswaran Raman       }
270dc707122SEaswaran Raman     }
271dc707122SEaswaran Raman 
272dc707122SEaswaran Raman     // Read the source range.
273dc707122SEaswaran Raman     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
274dc707122SEaswaran Raman     if (auto Err =
275dc707122SEaswaran Raman             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
276dc707122SEaswaran Raman       return Err;
277dc707122SEaswaran Raman     if (auto Err = readULEB128(ColumnStart))
278dc707122SEaswaran Raman       return Err;
279dc707122SEaswaran Raman     if (ColumnStart > std::numeric_limits<unsigned>::max())
2809152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
281dc707122SEaswaran Raman     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
282dc707122SEaswaran Raman       return Err;
283dc707122SEaswaran Raman     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
284dc707122SEaswaran Raman       return Err;
285dc707122SEaswaran Raman     LineStart += LineStartDelta;
286ad8f637bSVedant Kumar 
287ad8f637bSVedant Kumar     // If the high bit of ColumnEnd is set, this is a gap region.
288ad8f637bSVedant Kumar     if (ColumnEnd & (1U << 31)) {
289ad8f637bSVedant Kumar       Kind = CounterMappingRegion::GapRegion;
290ad8f637bSVedant Kumar       ColumnEnd &= ~(1U << 31);
291ad8f637bSVedant Kumar     }
292ad8f637bSVedant Kumar 
293dc707122SEaswaran Raman     // Adjust the column locations for the empty regions that are supposed to
294dc707122SEaswaran Raman     // cover whole lines. Those regions should be encoded with the
295dc707122SEaswaran Raman     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
296dc707122SEaswaran Raman     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
297dc707122SEaswaran Raman     // we set the column range to (0 -> 0) to ensure that the column start and
298dc707122SEaswaran Raman     // column end take up one byte each.
299dc707122SEaswaran Raman     // The std::numeric_limits<unsigned>::max() is used to represent a column
300dc707122SEaswaran Raman     // position at the end of the line without knowing the length of that line.
301dc707122SEaswaran Raman     if (ColumnStart == 0 && ColumnEnd == 0) {
302dc707122SEaswaran Raman       ColumnStart = 1;
303dc707122SEaswaran Raman       ColumnEnd = std::numeric_limits<unsigned>::max();
304dc707122SEaswaran Raman     }
305dc707122SEaswaran Raman 
306d34e60caSNicola Zaghen     LLVM_DEBUG({
307dc707122SEaswaran Raman       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
308dc707122SEaswaran Raman              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
309dc707122SEaswaran Raman              << ColumnEnd << ", ";
310dc707122SEaswaran Raman       if (Kind == CounterMappingRegion::ExpansionRegion)
311dc707122SEaswaran Raman         dbgs() << "Expands to file " << ExpandedFileID;
312dc707122SEaswaran Raman       else
313dc707122SEaswaran Raman         CounterMappingContext(Expressions).dump(C, dbgs());
314dc707122SEaswaran Raman       dbgs() << "\n";
315dc707122SEaswaran Raman     });
316dc707122SEaswaran Raman 
317*9f2967bcSAlan Phipps     auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID,
318bae83970SVedant Kumar                                     LineStart, ColumnStart,
319bae83970SVedant Kumar                                     LineStart + NumLines, ColumnEnd, Kind);
320bae83970SVedant Kumar     if (CMR.startLoc() > CMR.endLoc())
321bae83970SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
322bae83970SVedant Kumar     MappingRegions.push_back(CMR);
323dc707122SEaswaran Raman   }
3249152fd17SVedant Kumar   return Error::success();
325dc707122SEaswaran Raman }
326dc707122SEaswaran Raman 
3279152fd17SVedant Kumar Error RawCoverageMappingReader::read() {
328dc707122SEaswaran Raman   // Read the virtual file mapping.
329e78d131aSEugene Zelenko   SmallVector<unsigned, 8> VirtualFileMapping;
330dc707122SEaswaran Raman   uint64_t NumFileMappings;
331dc707122SEaswaran Raman   if (auto Err = readSize(NumFileMappings))
332dc707122SEaswaran Raman     return Err;
333dc707122SEaswaran Raman   for (size_t I = 0; I < NumFileMappings; ++I) {
334dc707122SEaswaran Raman     uint64_t FilenameIndex;
335dc707122SEaswaran Raman     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
336dc707122SEaswaran Raman       return Err;
337dc707122SEaswaran Raman     VirtualFileMapping.push_back(FilenameIndex);
338dc707122SEaswaran Raman   }
339dc707122SEaswaran Raman 
340dc707122SEaswaran Raman   // Construct the files using unique filenames and virtual file mapping.
341dc707122SEaswaran Raman   for (auto I : VirtualFileMapping) {
342dc707122SEaswaran Raman     Filenames.push_back(TranslationUnitFilenames[I]);
343dc707122SEaswaran Raman   }
344dc707122SEaswaran Raman 
345dc707122SEaswaran Raman   // Read the expressions.
346dc707122SEaswaran Raman   uint64_t NumExpressions;
347dc707122SEaswaran Raman   if (auto Err = readSize(NumExpressions))
348dc707122SEaswaran Raman     return Err;
349dc707122SEaswaran Raman   // Create an array of dummy expressions that get the proper counters
350dc707122SEaswaran Raman   // when the expressions are read, and the proper kinds when the counters
351dc707122SEaswaran Raman   // are decoded.
352dc707122SEaswaran Raman   Expressions.resize(
353dc707122SEaswaran Raman       NumExpressions,
354dc707122SEaswaran Raman       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
355dc707122SEaswaran Raman   for (size_t I = 0; I < NumExpressions; ++I) {
356dc707122SEaswaran Raman     if (auto Err = readCounter(Expressions[I].LHS))
357dc707122SEaswaran Raman       return Err;
358dc707122SEaswaran Raman     if (auto Err = readCounter(Expressions[I].RHS))
359dc707122SEaswaran Raman       return Err;
360dc707122SEaswaran Raman   }
361dc707122SEaswaran Raman 
362dc707122SEaswaran Raman   // Read the mapping regions sub-arrays.
363dc707122SEaswaran Raman   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
364dc707122SEaswaran Raman        InferredFileID < S; ++InferredFileID) {
365dc707122SEaswaran Raman     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
366dc707122SEaswaran Raman                                               VirtualFileMapping.size()))
367dc707122SEaswaran Raman       return Err;
368dc707122SEaswaran Raman   }
369dc707122SEaswaran Raman 
370dc707122SEaswaran Raman   // Set the counters for the expansion regions.
371dc707122SEaswaran Raman   // i.e. Counter of expansion region = counter of the first region
372dc707122SEaswaran Raman   // from the expanded file.
373dc707122SEaswaran Raman   // Perform multiple passes to correctly propagate the counters through
374dc707122SEaswaran Raman   // all the nested expansion regions.
375dc707122SEaswaran Raman   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
376dc707122SEaswaran Raman   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
377dc707122SEaswaran Raman   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
378dc707122SEaswaran Raman     for (auto &R : MappingRegions) {
379dc707122SEaswaran Raman       if (R.Kind != CounterMappingRegion::ExpansionRegion)
380dc707122SEaswaran Raman         continue;
381dc707122SEaswaran Raman       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
382dc707122SEaswaran Raman       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
383dc707122SEaswaran Raman     }
384dc707122SEaswaran Raman     for (auto &R : MappingRegions) {
385dc707122SEaswaran Raman       if (FileIDExpansionRegionMapping[R.FileID]) {
386dc707122SEaswaran Raman         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
387dc707122SEaswaran Raman         FileIDExpansionRegionMapping[R.FileID] = nullptr;
388dc707122SEaswaran Raman       }
389dc707122SEaswaran Raman     }
390dc707122SEaswaran Raman   }
391dc707122SEaswaran Raman 
3929152fd17SVedant Kumar   return Error::success();
393dc707122SEaswaran Raman }
394dc707122SEaswaran Raman 
395ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
396ac40e819SIgor Kudrin   // A dummy coverage mapping data consists of just one region with zero count.
397ac40e819SIgor Kudrin   uint64_t NumFileMappings;
398ac40e819SIgor Kudrin   if (Error Err = readSize(NumFileMappings))
399c55cf4afSBill Wendling     return std::move(Err);
400ac40e819SIgor Kudrin   if (NumFileMappings != 1)
401ac40e819SIgor Kudrin     return false;
402ac40e819SIgor Kudrin   // We don't expect any specific value for the filename index, just skip it.
403ac40e819SIgor Kudrin   uint64_t FilenameIndex;
404ac40e819SIgor Kudrin   if (Error Err =
405ac40e819SIgor Kudrin           readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
406c55cf4afSBill Wendling     return std::move(Err);
407ac40e819SIgor Kudrin   uint64_t NumExpressions;
408ac40e819SIgor Kudrin   if (Error Err = readSize(NumExpressions))
409c55cf4afSBill Wendling     return std::move(Err);
410ac40e819SIgor Kudrin   if (NumExpressions != 0)
411ac40e819SIgor Kudrin     return false;
412ac40e819SIgor Kudrin   uint64_t NumRegions;
413ac40e819SIgor Kudrin   if (Error Err = readSize(NumRegions))
414c55cf4afSBill Wendling     return std::move(Err);
415ac40e819SIgor Kudrin   if (NumRegions != 1)
416ac40e819SIgor Kudrin     return false;
417ac40e819SIgor Kudrin   uint64_t EncodedCounterAndRegion;
418ac40e819SIgor Kudrin   if (Error Err = readIntMax(EncodedCounterAndRegion,
419ac40e819SIgor Kudrin                              std::numeric_limits<unsigned>::max()))
420c55cf4afSBill Wendling     return std::move(Err);
421ac40e819SIgor Kudrin   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
422ac40e819SIgor Kudrin   return Tag == Counter::Zero;
423ac40e819SIgor Kudrin }
424ac40e819SIgor Kudrin 
4259152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) {
426e183340cSFangrui Song   Expected<StringRef> DataOrErr = Section.getContents();
427e183340cSFangrui Song   if (!DataOrErr)
428e183340cSFangrui Song     return DataOrErr.takeError();
429e183340cSFangrui Song   Data = *DataOrErr;
430dc707122SEaswaran Raman   Address = Section.getAddress();
4318b6af001SReid Kleckner 
4328b6af001SReid Kleckner   // If this is a linked PE/COFF file, then we have to skip over the null byte
4338b6af001SReid Kleckner   // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
4348b6af001SReid Kleckner   const ObjectFile *Obj = Section.getObject();
4358b6af001SReid Kleckner   if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
4368b6af001SReid Kleckner     Data = Data.drop_front(1);
4378b6af001SReid Kleckner 
4389152fd17SVedant Kumar   return Error::success();
439dc707122SEaswaran Raman }
440dc707122SEaswaran Raman 
441dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
442dc707122SEaswaran Raman   if (Pointer < Address)
443dc707122SEaswaran Raman     return StringRef();
444dc707122SEaswaran Raman   auto Offset = Pointer - Address;
445dc707122SEaswaran Raman   if (Offset + Size > Data.size())
446dc707122SEaswaran Raman     return StringRef();
447dc707122SEaswaran Raman   return Data.substr(Pointer - Address, Size);
448dc707122SEaswaran Raman }
449dc707122SEaswaran Raman 
450ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
451ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
452ac40e819SIgor Kudrin   // The hash value of dummy mapping records is always zero.
453ac40e819SIgor Kudrin   if (Hash)
454ac40e819SIgor Kudrin     return false;
455ac40e819SIgor Kudrin   return RawCoverageMappingDummyChecker(Mapping).isDummy();
456ac40e819SIgor Kudrin }
457ac40e819SIgor Kudrin 
458dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of
459dd1ea9deSVedant Kumar /// filenames in a vector-like container.
460dd1ea9deSVedant Kumar struct FilenameRange {
461dd1ea9deSVedant Kumar   unsigned StartingIndex;
462dd1ea9deSVedant Kumar   unsigned Length;
463dd1ea9deSVedant Kumar 
464dd1ea9deSVedant Kumar   FilenameRange(unsigned StartingIndex, unsigned Length)
465dd1ea9deSVedant Kumar       : StartingIndex(StartingIndex), Length(Length) {}
466dd1ea9deSVedant Kumar 
467dd1ea9deSVedant Kumar   void markInvalid() { Length = 0; }
468dd1ea9deSVedant Kumar   bool isInvalid() const { return Length == 0; }
469dd1ea9deSVedant Kumar };
470dd1ea9deSVedant Kumar 
471dc707122SEaswaran Raman namespace {
472e78d131aSEugene Zelenko 
473dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module.
474dc707122SEaswaran Raman struct CovMapFuncRecordReader {
475e78d131aSEugene Zelenko   virtual ~CovMapFuncRecordReader() = default;
476e78d131aSEugene Zelenko 
477dd1ea9deSVedant Kumar   // Read a coverage header.
4783739b95dSVedant Kumar   //
479dd1ea9deSVedant Kumar   // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
4803739b95dSVedant Kumar   // mapping data associated with the module.
4813739b95dSVedant Kumar   //
482dd1ea9deSVedant Kumar   // Returns a pointer to the next \c CovHeader if it exists, or to an address
483dd1ea9deSVedant Kumar   // greater than \p CovEnd if not.
484dd1ea9deSVedant Kumar   virtual Expected<const char *>
485dd1ea9deSVedant Kumar   readCoverageHeader(const char *CovBuf, const char *CovBufEnd,
486dd1ea9deSVedant Kumar                      BinaryCoverageReader::DecompressedData &Decompressed) = 0;
487dd1ea9deSVedant Kumar 
488dd1ea9deSVedant Kumar   // Read function records.
489dd1ea9deSVedant Kumar   //
490dd1ea9deSVedant Kumar   // \p FuncRecBuf points to the buffer containing a batch of function records.
491dd1ea9deSVedant Kumar   // \p FuncRecBufEnd points past the end of the batch of records.
492dd1ea9deSVedant Kumar   //
493dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
494dd1ea9deSVedant Kumar   // associated with the function records. It is unused in Version4.
495dd1ea9deSVedant Kumar   //
496dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
497dd1ea9deSVedant Kumar   // mappings associated with the function records. It is unused in Version4.
498dd1ea9deSVedant Kumar   virtual Error readFunctionRecords(const char *FuncRecBuf,
499dd1ea9deSVedant Kumar                                     const char *FuncRecBufEnd,
500dd1ea9deSVedant Kumar                                     Optional<FilenameRange> OutOfLineFileRange,
501dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBuf,
502dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBufEnd) = 0;
503e78d131aSEugene Zelenko 
504dc707122SEaswaran Raman   template <class IntPtrT, support::endianness Endian>
5059152fd17SVedant Kumar   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
506e78d131aSEugene Zelenko   get(CovMapVersion Version, InstrProfSymtab &P,
507dc707122SEaswaran Raman       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
508dc707122SEaswaran Raman       std::vector<StringRef> &F);
509dc707122SEaswaran Raman };
510dc707122SEaswaran Raman 
511dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module.
512e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
513dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
51472208a82SEugene Zelenko   using FuncRecordType =
51572208a82SEugene Zelenko       typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
51672208a82SEugene Zelenko   using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
517dc707122SEaswaran Raman 
518ac40e819SIgor Kudrin   // Maps function's name references to the indexes of their records
519ac40e819SIgor Kudrin   // in \c Records.
520e78d131aSEugene Zelenko   DenseMap<NameRefType, size_t> FunctionRecords;
521dc707122SEaswaran Raman   InstrProfSymtab &ProfileNames;
522dc707122SEaswaran Raman   std::vector<StringRef> &Filenames;
523dc707122SEaswaran Raman   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
524dc707122SEaswaran Raman 
525dd1ea9deSVedant Kumar   // Maps a hash of the filenames in a TU to a \c FileRange. The range
526dd1ea9deSVedant Kumar   // specifies the location of the hashed filenames in \c Filenames.
527dd1ea9deSVedant Kumar   DenseMap<uint64_t, FilenameRange> FileRangeMap;
528dd1ea9deSVedant Kumar 
529ac40e819SIgor Kudrin   // Add the record to the collection if we don't already have a record that
530ac40e819SIgor Kudrin   // points to the same function name. This is useful to ignore the redundant
531ac40e819SIgor Kudrin   // records for the functions with ODR linkage.
532ac40e819SIgor Kudrin   // In addition, prefer records with real coverage mapping data to dummy
533ac40e819SIgor Kudrin   // records, which were emitted for inline functions which were seen but
534ac40e819SIgor Kudrin   // not used in the corresponding translation unit.
535ac40e819SIgor Kudrin   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
536dd1ea9deSVedant Kumar                                      StringRef Mapping,
537dd1ea9deSVedant Kumar                                      FilenameRange FileRange) {
538dd1ea9deSVedant Kumar     ++CovMapNumRecords;
539ac40e819SIgor Kudrin     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
540ac40e819SIgor Kudrin     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
541ac40e819SIgor Kudrin     auto InsertResult =
542ac40e819SIgor Kudrin         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
543ac40e819SIgor Kudrin     if (InsertResult.second) {
544ac40e819SIgor Kudrin       StringRef FuncName;
545ac40e819SIgor Kudrin       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
546ac40e819SIgor Kudrin         return Err;
547b5794ca9SVedant Kumar       if (FuncName.empty())
548b5794ca9SVedant Kumar         return make_error<InstrProfError>(instrprof_error::malformed);
549dd1ea9deSVedant Kumar       ++CovMapNumUsedRecords;
550dd1ea9deSVedant Kumar       Records.emplace_back(Version, FuncName, FuncHash, Mapping,
551dd1ea9deSVedant Kumar                            FileRange.StartingIndex, FileRange.Length);
552ac40e819SIgor Kudrin       return Error::success();
553ac40e819SIgor Kudrin     }
554ac40e819SIgor Kudrin     // Update the existing record if it's a dummy and the new record is real.
555ac40e819SIgor Kudrin     size_t OldRecordIndex = InsertResult.first->second;
556ac40e819SIgor Kudrin     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
557ac40e819SIgor Kudrin         Records[OldRecordIndex];
558ac40e819SIgor Kudrin     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
559ac40e819SIgor Kudrin         OldRecord.FunctionHash, OldRecord.CoverageMapping);
560ac40e819SIgor Kudrin     if (Error Err = OldIsDummyExpected.takeError())
561ac40e819SIgor Kudrin       return Err;
562ac40e819SIgor Kudrin     if (!*OldIsDummyExpected)
563ac40e819SIgor Kudrin       return Error::success();
564ac40e819SIgor Kudrin     Expected<bool> NewIsDummyExpected =
565ac40e819SIgor Kudrin         isCoverageMappingDummy(FuncHash, Mapping);
566ac40e819SIgor Kudrin     if (Error Err = NewIsDummyExpected.takeError())
567ac40e819SIgor Kudrin       return Err;
568ac40e819SIgor Kudrin     if (*NewIsDummyExpected)
569ac40e819SIgor Kudrin       return Error::success();
570dd1ea9deSVedant Kumar     ++CovMapNumUsedRecords;
571ac40e819SIgor Kudrin     OldRecord.FunctionHash = FuncHash;
572ac40e819SIgor Kudrin     OldRecord.CoverageMapping = Mapping;
573dd1ea9deSVedant Kumar     OldRecord.FilenamesBegin = FileRange.StartingIndex;
574dd1ea9deSVedant Kumar     OldRecord.FilenamesSize = FileRange.Length;
575ac40e819SIgor Kudrin     return Error::success();
576ac40e819SIgor Kudrin   }
577ac40e819SIgor Kudrin 
578dc707122SEaswaran Raman public:
579dc707122SEaswaran Raman   VersionedCovMapFuncRecordReader(
580dc707122SEaswaran Raman       InstrProfSymtab &P,
581dc707122SEaswaran Raman       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
582dc707122SEaswaran Raman       std::vector<StringRef> &F)
583dc707122SEaswaran Raman       : ProfileNames(P), Filenames(F), Records(R) {}
584e78d131aSEugene Zelenko 
585e78d131aSEugene Zelenko   ~VersionedCovMapFuncRecordReader() override = default;
586dc707122SEaswaran Raman 
587dd1ea9deSVedant Kumar   Expected<const char *> readCoverageHeader(
588dd1ea9deSVedant Kumar       const char *CovBuf, const char *CovBufEnd,
589dd1ea9deSVedant Kumar       BinaryCoverageReader::DecompressedData &Decompressed) override {
590dc707122SEaswaran Raman     using namespace support;
591e78d131aSEugene Zelenko 
592dd1ea9deSVedant Kumar     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
5939152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
594dd1ea9deSVedant Kumar     auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
595dc707122SEaswaran Raman     uint32_t NRecords = CovHeader->getNRecords<Endian>();
596dc707122SEaswaran Raman     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
597dc707122SEaswaran Raman     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
598dc707122SEaswaran Raman     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
599dd1ea9deSVedant Kumar     CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
600dc707122SEaswaran Raman 
601dc707122SEaswaran Raman     // Skip past the function records, saving the start and end for later.
602dd1ea9deSVedant Kumar     // This is a no-op in Version4 (function records are read after all headers
603dd1ea9deSVedant Kumar     // are read).
604dd1ea9deSVedant Kumar     const char *FuncRecBuf = nullptr;
605dd1ea9deSVedant Kumar     const char *FuncRecBufEnd = nullptr;
606dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
607dd1ea9deSVedant Kumar       FuncRecBuf = CovBuf;
608dd1ea9deSVedant Kumar     CovBuf += NRecords * sizeof(FuncRecordType);
609dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
610dd1ea9deSVedant Kumar       FuncRecBufEnd = CovBuf;
611dc707122SEaswaran Raman 
612dc707122SEaswaran Raman     // Get the filenames.
613dd1ea9deSVedant Kumar     if (CovBuf + FilenamesSize > CovBufEnd)
6149152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
615dc707122SEaswaran Raman     size_t FilenamesBegin = Filenames.size();
616dd1ea9deSVedant Kumar     StringRef FilenameRegion(CovBuf, FilenamesSize);
617dd1ea9deSVedant Kumar     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
618dd1ea9deSVedant Kumar     if (auto Err = Reader.read(Version, Decompressed))
619c55cf4afSBill Wendling       return std::move(Err);
620dd1ea9deSVedant Kumar     CovBuf += FilenamesSize;
621dd1ea9deSVedant Kumar     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
622dd1ea9deSVedant Kumar 
623*9f2967bcSAlan Phipps     if (Version >= CovMapVersion::Version4) {
624dd1ea9deSVedant Kumar       // Map a hash of the filenames region to the filename range associated
625dd1ea9deSVedant Kumar       // with this coverage header.
626dd1ea9deSVedant Kumar       int64_t FilenamesRef =
627dd1ea9deSVedant Kumar           llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
628dd1ea9deSVedant Kumar       auto Insert =
629dd1ea9deSVedant Kumar           FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
630dd1ea9deSVedant Kumar       if (!Insert.second) {
631dd1ea9deSVedant Kumar         // The same filenames ref was encountered twice. It's possible that
632dd1ea9deSVedant Kumar         // the associated filenames are the same.
633dd1ea9deSVedant Kumar         auto It = Filenames.begin();
634dd1ea9deSVedant Kumar         FilenameRange &OrigRange = Insert.first->getSecond();
635dd1ea9deSVedant Kumar         if (std::equal(It + OrigRange.StartingIndex,
636dd1ea9deSVedant Kumar                        It + OrigRange.StartingIndex + OrigRange.Length,
637dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex,
638dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex + FileRange.Length))
639dd1ea9deSVedant Kumar           // Map the new range to the original one.
640dd1ea9deSVedant Kumar           FileRange = OrigRange;
641dd1ea9deSVedant Kumar         else
642dd1ea9deSVedant Kumar           // This is a hash collision. Mark the filenames ref invalid.
643dd1ea9deSVedant Kumar           OrigRange.markInvalid();
644dd1ea9deSVedant Kumar       }
645dd1ea9deSVedant Kumar     }
646dc707122SEaswaran Raman 
647dc707122SEaswaran Raman     // We'll read the coverage mapping records in the loop below.
648dd1ea9deSVedant Kumar     // This is a no-op in Version4 (coverage mappings are not affixed to the
649dd1ea9deSVedant Kumar     // coverage header).
650dd1ea9deSVedant Kumar     const char *MappingBuf = CovBuf;
651*9f2967bcSAlan Phipps     if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
6529152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
653dd1ea9deSVedant Kumar     CovBuf += CoverageSize;
654dd1ea9deSVedant Kumar     const char *MappingEnd = CovBuf;
655dd1ea9deSVedant Kumar 
656dd1ea9deSVedant Kumar     if (CovBuf > CovBufEnd)
657dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
658dd1ea9deSVedant Kumar 
659dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4) {
660dd1ea9deSVedant Kumar       // Read each function record.
661dd1ea9deSVedant Kumar       if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
662dd1ea9deSVedant Kumar                                         MappingBuf, MappingEnd))
663dd1ea9deSVedant Kumar         return std::move(E);
664dd1ea9deSVedant Kumar     }
665dd1ea9deSVedant Kumar 
666dc707122SEaswaran Raman     // Each coverage map has an alignment of 8, so we need to adjust alignment
667dc707122SEaswaran Raman     // before reading the next map.
668dd1ea9deSVedant Kumar     CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
669dc707122SEaswaran Raman 
670dd1ea9deSVedant Kumar     return CovBuf;
67199317124SVedant Kumar   }
672dd1ea9deSVedant Kumar 
673dd1ea9deSVedant Kumar   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
674dd1ea9deSVedant Kumar                             Optional<FilenameRange> OutOfLineFileRange,
675dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBuf,
676dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBufEnd) override {
677dd1ea9deSVedant Kumar     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
678dd1ea9deSVedant Kumar     while ((const char *)CFR < FuncRecBufEnd) {
679dd1ea9deSVedant Kumar       // Validate the length of the coverage mapping for this function.
680dd1ea9deSVedant Kumar       const char *NextMappingBuf;
681dd1ea9deSVedant Kumar       const FuncRecordType *NextCFR;
682dd1ea9deSVedant Kumar       std::tie(NextMappingBuf, NextCFR) =
683dd1ea9deSVedant Kumar           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
684dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4)
685dd1ea9deSVedant Kumar         if (NextMappingBuf > OutOfLineMappingBufEnd)
686dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
687dd1ea9deSVedant Kumar 
688dd1ea9deSVedant Kumar       // Look up the set of filenames associated with this function record.
689dd1ea9deSVedant Kumar       Optional<FilenameRange> FileRange;
690dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4) {
691dd1ea9deSVedant Kumar         FileRange = OutOfLineFileRange;
692dd1ea9deSVedant Kumar       } else {
693dd1ea9deSVedant Kumar         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
694dd1ea9deSVedant Kumar         auto It = FileRangeMap.find(FilenamesRef);
695dd1ea9deSVedant Kumar         if (It == FileRangeMap.end())
696dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
697dd1ea9deSVedant Kumar         else
698dd1ea9deSVedant Kumar           FileRange = It->getSecond();
699dd1ea9deSVedant Kumar       }
700dd1ea9deSVedant Kumar 
701dd1ea9deSVedant Kumar       // Now, read the coverage data.
702dd1ea9deSVedant Kumar       if (FileRange && !FileRange->isInvalid()) {
703dd1ea9deSVedant Kumar         StringRef Mapping =
704dd1ea9deSVedant Kumar             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
705*9f2967bcSAlan Phipps         if (Version >= CovMapVersion::Version4 &&
706dd1ea9deSVedant Kumar             Mapping.data() + Mapping.size() > FuncRecBufEnd)
707dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
708dd1ea9deSVedant Kumar         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
709dd1ea9deSVedant Kumar           return Err;
710dd1ea9deSVedant Kumar       }
711dd1ea9deSVedant Kumar 
712dd1ea9deSVedant Kumar       std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
713dd1ea9deSVedant Kumar     }
714dd1ea9deSVedant Kumar     return Error::success();
715dc707122SEaswaran Raman   }
716dc707122SEaswaran Raman };
717e78d131aSEugene Zelenko 
718dc707122SEaswaran Raman } // end anonymous namespace
719dc707122SEaswaran Raman 
720dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian>
7219152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
722e78d131aSEugene Zelenko     CovMapVersion Version, InstrProfSymtab &P,
723dc707122SEaswaran Raman     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
724dc707122SEaswaran Raman     std::vector<StringRef> &F) {
725dc707122SEaswaran Raman   using namespace coverage;
726e78d131aSEugene Zelenko 
727dc707122SEaswaran Raman   switch (Version) {
728dc707122SEaswaran Raman   case CovMapVersion::Version1:
7290eaee545SJonas Devlieghere     return std::make_unique<VersionedCovMapFuncRecordReader<
730dc707122SEaswaran Raman         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
731dc707122SEaswaran Raman   case CovMapVersion::Version2:
732ad8f637bSVedant Kumar   case CovMapVersion::Version3:
733dd1ea9deSVedant Kumar   case CovMapVersion::Version4:
734*9f2967bcSAlan Phipps   case CovMapVersion::Version5:
735dc707122SEaswaran Raman     // Decompress the name data.
7369152fd17SVedant Kumar     if (Error E = P.create(P.getNameData()))
737c55cf4afSBill Wendling       return std::move(E);
738ad8f637bSVedant Kumar     if (Version == CovMapVersion::Version2)
7390eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
740dc707122SEaswaran Raman           CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
741dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version3)
7420eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
743ad8f637bSVedant Kumar           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F);
744dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version4)
745dd1ea9deSVedant Kumar       return std::make_unique<VersionedCovMapFuncRecordReader<
746dd1ea9deSVedant Kumar           CovMapVersion::Version4, IntPtrT, Endian>>(P, R, F);
747*9f2967bcSAlan Phipps     else if (Version == CovMapVersion::Version5)
748*9f2967bcSAlan Phipps       return std::make_unique<VersionedCovMapFuncRecordReader<
749*9f2967bcSAlan Phipps           CovMapVersion::Version5, IntPtrT, Endian>>(P, R, F);
750dc707122SEaswaran Raman   }
751dc707122SEaswaran Raman   llvm_unreachable("Unsupported version");
752dc707122SEaswaran Raman }
753dc707122SEaswaran Raman 
754dc707122SEaswaran Raman template <typename T, support::endianness Endian>
7559152fd17SVedant Kumar static Error readCoverageMappingData(
756dd1ea9deSVedant Kumar     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
757dc707122SEaswaran Raman     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
758dd1ea9deSVedant Kumar     std::vector<StringRef> &Filenames,
759dd1ea9deSVedant Kumar     BinaryCoverageReader::DecompressedData &Decompressed) {
760dc707122SEaswaran Raman   using namespace coverage;
761e78d131aSEugene Zelenko 
762dc707122SEaswaran Raman   // Read the records in the coverage data section.
763dc707122SEaswaran Raman   auto CovHeader =
764dd1ea9deSVedant Kumar       reinterpret_cast<const CovMapHeader *>(CovMap.data());
765dc707122SEaswaran Raman   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
766e78d131aSEugene Zelenko   if (Version > CovMapVersion::CurrentVersion)
7679152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
7689152fd17SVedant Kumar   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
769dc707122SEaswaran Raman       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
770dc707122SEaswaran Raman                                              Filenames);
7719152fd17SVedant Kumar   if (Error E = ReaderExpected.takeError())
7729152fd17SVedant Kumar     return E;
7739152fd17SVedant Kumar   auto Reader = std::move(ReaderExpected.get());
774dd1ea9deSVedant Kumar   const char *CovBuf = CovMap.data();
775dd1ea9deSVedant Kumar   const char *CovBufEnd = CovBuf + CovMap.size();
776dd1ea9deSVedant Kumar   const char *FuncRecBuf = FuncRecords.data();
777dd1ea9deSVedant Kumar   const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
778dd1ea9deSVedant Kumar   while (CovBuf < CovBufEnd) {
779dd1ea9deSVedant Kumar     // Read the current coverage header & filename data.
780dd1ea9deSVedant Kumar     //
781dd1ea9deSVedant Kumar     // Prior to Version4, this also reads all function records affixed to the
782dd1ea9deSVedant Kumar     // header.
783dd1ea9deSVedant Kumar     //
784dd1ea9deSVedant Kumar     // Return a pointer to the next coverage header.
785dd1ea9deSVedant Kumar     auto NextOrErr =
786dd1ea9deSVedant Kumar         Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed);
787dd1ea9deSVedant Kumar     if (auto E = NextOrErr.takeError())
7889152fd17SVedant Kumar       return E;
789dd1ea9deSVedant Kumar     CovBuf = NextOrErr.get();
790dc707122SEaswaran Raman   }
791dd1ea9deSVedant Kumar   // In Version4, function records are not affixed to coverage headers. Read
792dd1ea9deSVedant Kumar   // the records from their dedicated section.
793*9f2967bcSAlan Phipps   if (Version >= CovMapVersion::Version4)
794dd1ea9deSVedant Kumar     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr,
795dd1ea9deSVedant Kumar                                        nullptr);
7969152fd17SVedant Kumar   return Error::success();
797dc707122SEaswaran Raman }
798e78d131aSEugene Zelenko 
799dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata";
800dc707122SEaswaran Raman 
801901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>>
802901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer(
80380cd518bSVedant Kumar     StringRef Coverage, std::string &&FuncRecords, InstrProfSymtab &&ProfileNames,
804dd1ea9deSVedant Kumar     uint8_t BytesInAddress, support::endianness Endian) {
80580cd518bSVedant Kumar   std::unique_ptr<BinaryCoverageReader> Reader(
80680cd518bSVedant Kumar       new BinaryCoverageReader(std::move(FuncRecords)));
807901d04fcSVedant Kumar   Reader->ProfileNames = std::move(ProfileNames);
80880cd518bSVedant Kumar   StringRef FuncRecordsRef = Reader->FuncRecords;
809901d04fcSVedant Kumar   if (BytesInAddress == 4 && Endian == support::endianness::little) {
810901d04fcSVedant Kumar     if (Error E =
811901d04fcSVedant Kumar             readCoverageMappingData<uint32_t, support::endianness::little>(
81280cd518bSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecordsRef,
813dd1ea9deSVedant Kumar                 Reader->MappingRecords, Reader->Filenames,
814dd1ea9deSVedant Kumar                 Reader->Decompressed))
815c55cf4afSBill Wendling       return std::move(E);
816901d04fcSVedant Kumar   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
817901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
81880cd518bSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecordsRef,
81980cd518bSVedant Kumar             Reader->MappingRecords, Reader->Filenames, Reader->Decompressed))
820c55cf4afSBill Wendling       return std::move(E);
821901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
822901d04fcSVedant Kumar     if (Error E =
823901d04fcSVedant Kumar             readCoverageMappingData<uint64_t, support::endianness::little>(
82480cd518bSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecordsRef,
825dd1ea9deSVedant Kumar                 Reader->MappingRecords, Reader->Filenames,
826dd1ea9deSVedant Kumar                 Reader->Decompressed))
827c55cf4afSBill Wendling       return std::move(E);
828901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
829901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
83080cd518bSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecordsRef,
83180cd518bSVedant Kumar             Reader->MappingRecords, Reader->Filenames, Reader->Decompressed))
832c55cf4afSBill Wendling       return std::move(E);
833901d04fcSVedant Kumar   } else
834901d04fcSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
835c55cf4afSBill Wendling   return std::move(Reader);
836901d04fcSVedant Kumar }
837901d04fcSVedant Kumar 
838901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
839901d04fcSVedant Kumar loadTestingFormat(StringRef Data) {
840901d04fcSVedant Kumar   uint8_t BytesInAddress = 8;
841901d04fcSVedant Kumar   support::endianness Endian = support::endianness::little;
842dc707122SEaswaran Raman 
843dc707122SEaswaran Raman   Data = Data.substr(StringRef(TestingFormatMagic).size());
84472208a82SEugene Zelenko   if (Data.empty())
8459152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
846dc707122SEaswaran Raman   unsigned N = 0;
8476a0746a9SFangrui Song   uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
848dc707122SEaswaran Raman   if (N > Data.size())
8499152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
850dc707122SEaswaran Raman   Data = Data.substr(N);
85172208a82SEugene Zelenko   if (Data.empty())
8529152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
853dc707122SEaswaran Raman   N = 0;
8546a0746a9SFangrui Song   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
855dc707122SEaswaran Raman   if (N > Data.size())
8569152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
857dc707122SEaswaran Raman   Data = Data.substr(N);
858dc707122SEaswaran Raman   if (Data.size() < ProfileNamesSize)
8599152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
860901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
8619152fd17SVedant Kumar   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
862c55cf4afSBill Wendling     return std::move(E);
863901d04fcSVedant Kumar   StringRef CoverageMapping = Data.substr(ProfileNamesSize);
864eb103073SIgor Kudrin   // Skip the padding bytes because coverage map data has an alignment of 8.
86572208a82SEugene Zelenko   if (CoverageMapping.empty())
8669152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
867ce56e1a1SGuillaume Chatelet   size_t Pad = offsetToAlignedAddr(CoverageMapping.data(), Align(8));
868eb103073SIgor Kudrin   if (CoverageMapping.size() < Pad)
8699152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
870eb103073SIgor Kudrin   CoverageMapping = CoverageMapping.substr(Pad);
871901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
872dd1ea9deSVedant Kumar       CoverageMapping, "", std::move(ProfileNames), BytesInAddress, Endian);
873dc707122SEaswaran Raman }
874dc707122SEaswaran Raman 
87580cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats
87680cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF.
87780cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
87880cd518bSVedant Kumar                                                         StringRef Name) {
8798b6af001SReid Kleckner   // On COFF, the object file section name may end in "$M". This tells the
8808b6af001SReid Kleckner   // linker to sort these sections between "$A" and "$Z". The linker removes the
8818b6af001SReid Kleckner   // dollar and everything after it in the final binary. Do the same to match.
8828b6af001SReid Kleckner   bool IsCOFF = isa<COFFObjectFile>(OF);
8838b6af001SReid Kleckner   auto stripSuffix = [IsCOFF](StringRef N) {
8848b6af001SReid Kleckner     return IsCOFF ? N.split('$').first : N;
8858b6af001SReid Kleckner   };
8868b6af001SReid Kleckner   Name = stripSuffix(Name);
8878b6af001SReid Kleckner 
88880cd518bSVedant Kumar   std::vector<SectionRef> Sections;
889dc707122SEaswaran Raman   for (const auto &Section : OF.sections()) {
890bcc00e1aSGeorge Rimar     Expected<StringRef> NameOrErr = Section.getName();
891bcc00e1aSGeorge Rimar     if (!NameOrErr)
892bcc00e1aSGeorge Rimar       return NameOrErr.takeError();
893bcc00e1aSGeorge Rimar     if (stripSuffix(*NameOrErr) == Name)
89480cd518bSVedant Kumar       Sections.push_back(Section);
895dc707122SEaswaran Raman   }
89680cd518bSVedant Kumar   if (Sections.empty())
8979152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
89880cd518bSVedant Kumar   return Sections;
899dc707122SEaswaran Raman }
900dc707122SEaswaran Raman 
901901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
902901d04fcSVedant Kumar loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch) {
903dc707122SEaswaran Raman   std::unique_ptr<ObjectFile> OF;
904e78d131aSEugene Zelenko   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
905dc707122SEaswaran Raman     // If we have a universal binary, try to look up the object for the
906dc707122SEaswaran Raman     // appropriate architecture.
9074fd11c1eSAlexander Shaposhnikov     auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
9089acb1099SKevin Enderby     if (!ObjectFileOrErr)
9099acb1099SKevin Enderby       return ObjectFileOrErr.takeError();
910dc707122SEaswaran Raman     OF = std::move(ObjectFileOrErr.get());
911e78d131aSEugene Zelenko   } else if (isa<ObjectFile>(Bin.get())) {
912dc707122SEaswaran Raman     // For any other object file, upcast and take ownership.
913e78d131aSEugene Zelenko     OF.reset(cast<ObjectFile>(Bin.release()));
914dc707122SEaswaran Raman     // If we've asked for a particular arch, make sure they match.
915dc707122SEaswaran Raman     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
9169152fd17SVedant Kumar       return errorCodeToError(object_error::arch_not_found);
917dc707122SEaswaran Raman   } else
918dc707122SEaswaran Raman     // We can only handle object files.
9199152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
920dc707122SEaswaran Raman 
921dc707122SEaswaran Raman   // The coverage uses native pointer sizes for the object it's written in.
922901d04fcSVedant Kumar   uint8_t BytesInAddress = OF->getBytesInAddress();
923901d04fcSVedant Kumar   support::endianness Endian = OF->isLittleEndian()
924901d04fcSVedant Kumar                                    ? support::endianness::little
925dc707122SEaswaran Raman                                    : support::endianness::big;
926dc707122SEaswaran Raman 
927dc707122SEaswaran Raman   // Look for the sections that we are interested in.
9281a6a2b64SVedant Kumar   auto ObjFormat = OF->getTripleObjectFormat();
9294a5ddf80SXinliang David Li   auto NamesSection =
93080cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
9311a6a2b64SVedant Kumar                                                  /*AddSegmentInfo=*/false));
9329152fd17SVedant Kumar   if (auto E = NamesSection.takeError())
933c55cf4afSBill Wendling     return std::move(E);
9344a5ddf80SXinliang David Li   auto CoverageSection =
93580cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
9361a6a2b64SVedant Kumar                                                   /*AddSegmentInfo=*/false));
9379152fd17SVedant Kumar   if (auto E = CoverageSection.takeError())
938c55cf4afSBill Wendling     return std::move(E);
93980cd518bSVedant Kumar   std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
94080cd518bSVedant Kumar   if (CoverageSectionRefs.size() != 1)
94180cd518bSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
94280cd518bSVedant Kumar   auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
943901d04fcSVedant Kumar   if (!CoverageMappingOrErr)
944901d04fcSVedant Kumar     return CoverageMappingOrErr.takeError();
945dd1ea9deSVedant Kumar   StringRef CoverageMapping = CoverageMappingOrErr.get();
946e183340cSFangrui Song 
947901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
94880cd518bSVedant Kumar   std::vector<SectionRef> NamesSectionRefs = *NamesSection;
94980cd518bSVedant Kumar   if (NamesSectionRefs.size() != 1)
95080cd518bSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
95180cd518bSVedant Kumar   if (Error E = ProfileNames.create(NamesSectionRefs.back()))
952c55cf4afSBill Wendling     return std::move(E);
953dc707122SEaswaran Raman 
954dd1ea9deSVedant Kumar   // Look for the coverage records section (Version4 only).
95580cd518bSVedant Kumar   std::string FuncRecords;
95680cd518bSVedant Kumar   auto CoverageRecordsSections =
95780cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
958dd1ea9deSVedant Kumar                                                   /*AddSegmentInfo=*/false));
95980cd518bSVedant Kumar   if (auto E = CoverageRecordsSections.takeError())
960dd1ea9deSVedant Kumar     consumeError(std::move(E));
961dd1ea9deSVedant Kumar   else {
96280cd518bSVedant Kumar     for (SectionRef Section : *CoverageRecordsSections) {
96380cd518bSVedant Kumar       auto CoverageRecordsOrErr = Section.getContents();
964dd1ea9deSVedant Kumar       if (!CoverageRecordsOrErr)
965dd1ea9deSVedant Kumar         return CoverageRecordsOrErr.takeError();
96680cd518bSVedant Kumar       FuncRecords += CoverageRecordsOrErr.get();
96780cd518bSVedant Kumar       while (FuncRecords.size() % 8 != 0)
96880cd518bSVedant Kumar         FuncRecords += '\0';
96980cd518bSVedant Kumar     }
970dd1ea9deSVedant Kumar   }
971dd1ea9deSVedant Kumar 
972901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
97380cd518bSVedant Kumar       CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
97480cd518bSVedant Kumar       BytesInAddress, Endian);
975dc707122SEaswaran Raman }
976dc707122SEaswaran Raman 
9777fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin.
9787fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
9797fafaa07SVedant Kumar   // If we have a universal binary and Arch doesn't identify any of its slices,
9807fafaa07SVedant Kumar   // it's user error.
9817fafaa07SVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
9827fafaa07SVedant Kumar     for (auto &ObjForArch : Universal->objects())
9837fafaa07SVedant Kumar       if (Arch == ObjForArch.getArchFlagName())
9847fafaa07SVedant Kumar         return false;
9857fafaa07SVedant Kumar     return true;
9867fafaa07SVedant Kumar   }
9877fafaa07SVedant Kumar   return false;
9887fafaa07SVedant Kumar }
9897fafaa07SVedant Kumar 
990901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
991901d04fcSVedant Kumar BinaryCoverageReader::create(
992901d04fcSVedant Kumar     MemoryBufferRef ObjectBuffer, StringRef Arch,
993901d04fcSVedant Kumar     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers) {
994901d04fcSVedant Kumar   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
995dc707122SEaswaran Raman 
996901d04fcSVedant Kumar   if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
997dc707122SEaswaran Raman     // This is a special format used for testing.
998901d04fcSVedant Kumar     auto ReaderOrErr = loadTestingFormat(ObjectBuffer.getBuffer());
999901d04fcSVedant Kumar     if (!ReaderOrErr)
1000901d04fcSVedant Kumar       return ReaderOrErr.takeError();
1001901d04fcSVedant Kumar     Readers.push_back(std::move(ReaderOrErr.get()));
1002c55cf4afSBill Wendling     return std::move(Readers);
1003901d04fcSVedant Kumar   }
1004dc707122SEaswaran Raman 
1005901d04fcSVedant Kumar   auto BinOrErr = createBinary(ObjectBuffer);
1006901d04fcSVedant Kumar   if (!BinOrErr)
1007901d04fcSVedant Kumar     return BinOrErr.takeError();
1008901d04fcSVedant Kumar   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
1009901d04fcSVedant Kumar 
10107fafaa07SVedant Kumar   if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
10117fafaa07SVedant Kumar     return make_error<CoverageMapError>(
10127fafaa07SVedant Kumar         coveragemap_error::invalid_or_missing_arch_specifier);
10137fafaa07SVedant Kumar 
1014901d04fcSVedant Kumar   // MachO universal binaries which contain archives need to be treated as
1015901d04fcSVedant Kumar   // archives, not as regular binaries.
1016901d04fcSVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
1017901d04fcSVedant Kumar     for (auto &ObjForArch : Universal->objects()) {
1018901d04fcSVedant Kumar       // Skip slices within the universal binary which target the wrong arch.
1019901d04fcSVedant Kumar       std::string ObjArch = ObjForArch.getArchFlagName();
1020901d04fcSVedant Kumar       if (Arch != ObjArch)
1021901d04fcSVedant Kumar         continue;
1022901d04fcSVedant Kumar 
1023901d04fcSVedant Kumar       auto ArchiveOrErr = ObjForArch.getAsArchive();
1024901d04fcSVedant Kumar       if (!ArchiveOrErr) {
1025901d04fcSVedant Kumar         // If this is not an archive, try treating it as a regular object.
1026901d04fcSVedant Kumar         consumeError(ArchiveOrErr.takeError());
1027901d04fcSVedant Kumar         break;
1028901d04fcSVedant Kumar       }
1029901d04fcSVedant Kumar 
1030901d04fcSVedant Kumar       return BinaryCoverageReader::create(
1031901d04fcSVedant Kumar           ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers);
1032901d04fcSVedant Kumar     }
1033901d04fcSVedant Kumar   }
1034901d04fcSVedant Kumar 
1035901d04fcSVedant Kumar   // Load coverage out of archive members.
1036901d04fcSVedant Kumar   if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
1037901d04fcSVedant Kumar     Error Err = Error::success();
1038901d04fcSVedant Kumar     for (auto &Child : Ar->children(Err)) {
1039901d04fcSVedant Kumar       Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
1040901d04fcSVedant Kumar       if (!ChildBufOrErr)
1041901d04fcSVedant Kumar         return ChildBufOrErr.takeError();
1042901d04fcSVedant Kumar 
1043901d04fcSVedant Kumar       auto ChildReadersOrErr = BinaryCoverageReader::create(
1044901d04fcSVedant Kumar           ChildBufOrErr.get(), Arch, ObjectFileBuffers);
1045901d04fcSVedant Kumar       if (!ChildReadersOrErr)
1046901d04fcSVedant Kumar         return ChildReadersOrErr.takeError();
1047901d04fcSVedant Kumar       for (auto &Reader : ChildReadersOrErr.get())
1048901d04fcSVedant Kumar         Readers.push_back(std::move(Reader));
1049901d04fcSVedant Kumar     }
1050901d04fcSVedant Kumar     if (Err)
1051c55cf4afSBill Wendling       return std::move(Err);
1052901d04fcSVedant Kumar 
1053901d04fcSVedant Kumar     // Thin archives reference object files outside of the archive file, i.e.
1054901d04fcSVedant Kumar     // files which reside in memory not owned by the caller. Transfer ownership
1055901d04fcSVedant Kumar     // to the caller.
1056901d04fcSVedant Kumar     if (Ar->isThin())
1057901d04fcSVedant Kumar       for (auto &Buffer : Ar->takeThinBuffers())
1058901d04fcSVedant Kumar         ObjectFileBuffers.push_back(std::move(Buffer));
1059901d04fcSVedant Kumar 
1060c55cf4afSBill Wendling     return std::move(Readers);
1061901d04fcSVedant Kumar   }
1062901d04fcSVedant Kumar 
1063901d04fcSVedant Kumar   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch);
1064901d04fcSVedant Kumar   if (!ReaderOrErr)
1065901d04fcSVedant Kumar     return ReaderOrErr.takeError();
1066901d04fcSVedant Kumar   Readers.push_back(std::move(ReaderOrErr.get()));
1067c55cf4afSBill Wendling   return std::move(Readers);
1068dc707122SEaswaran Raman }
1069dc707122SEaswaran Raman 
10709152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
1071dc707122SEaswaran Raman   if (CurrentRecord >= MappingRecords.size())
10729152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::eof);
1073dc707122SEaswaran Raman 
1074dc707122SEaswaran Raman   FunctionsFilenames.clear();
1075dc707122SEaswaran Raman   Expressions.clear();
1076dc707122SEaswaran Raman   MappingRegions.clear();
1077dc707122SEaswaran Raman   auto &R = MappingRecords[CurrentRecord];
1078dc707122SEaswaran Raman   RawCoverageMappingReader Reader(
1079dc707122SEaswaran Raman       R.CoverageMapping,
1080dc707122SEaswaran Raman       makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
1081dc707122SEaswaran Raman       FunctionsFilenames, Expressions, MappingRegions);
1082dc707122SEaswaran Raman   if (auto Err = Reader.read())
1083dc707122SEaswaran Raman     return Err;
1084dc707122SEaswaran Raman 
1085dc707122SEaswaran Raman   Record.FunctionName = R.FunctionName;
1086dc707122SEaswaran Raman   Record.FunctionHash = R.FunctionHash;
1087dc707122SEaswaran Raman   Record.Filenames = FunctionsFilenames;
1088dc707122SEaswaran Raman   Record.Expressions = Expressions;
1089dc707122SEaswaran Raman   Record.MappingRegions = MappingRegions;
1090dc707122SEaswaran Raman 
1091dc707122SEaswaran Raman   ++CurrentRecord;
10929152fd17SVedant Kumar   return Error::success();
1093dc707122SEaswaran Raman }
1094