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"
23ba7a92c0SNico Weber #include "llvm/Object/COFF.h"
24e78d131aSEugene Zelenko #include "llvm/Object/Error.h"
25dc707122SEaswaran Raman #include "llvm/Object/MachOUniversal.h"
26dc707122SEaswaran Raman #include "llvm/Object/ObjectFile.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"
36ba7a92c0SNico Weber #include "llvm/Support/Path.h"
37dc707122SEaswaran Raman #include "llvm/Support/raw_ostream.h"
38e78d131aSEugene Zelenko #include <vector>
39dc707122SEaswaran Raman 
40dc707122SEaswaran Raman using namespace llvm;
41dc707122SEaswaran Raman using namespace coverage;
42dc707122SEaswaran Raman using namespace object;
43dc707122SEaswaran Raman 
44dc707122SEaswaran Raman #define DEBUG_TYPE "coverage-mapping"
45dc707122SEaswaran Raman 
46dd1ea9deSVedant Kumar STATISTIC(CovMapNumRecords, "The # of coverage function records");
47dd1ea9deSVedant Kumar STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");
48dd1ea9deSVedant Kumar 
49dc707122SEaswaran Raman void CoverageMappingIterator::increment() {
50bae83970SVedant Kumar   if (ReadErr != coveragemap_error::success)
51bae83970SVedant Kumar     return;
52bae83970SVedant Kumar 
53dc707122SEaswaran Raman   // Check if all the records were read or if an error occurred while reading
54dc707122SEaswaran Raman   // the next record.
55bae83970SVedant Kumar   if (auto E = Reader->readNextRecord(Record))
569152fd17SVedant Kumar     handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
579152fd17SVedant Kumar       if (CME.get() == coveragemap_error::eof)
58dc707122SEaswaran Raman         *this = CoverageMappingIterator();
599152fd17SVedant Kumar       else
60bae83970SVedant Kumar         ReadErr = CME.get();
619152fd17SVedant Kumar     });
629152fd17SVedant Kumar }
63dc707122SEaswaran Raman 
649152fd17SVedant Kumar Error RawCoverageReader::readULEB128(uint64_t &Result) {
6572208a82SEugene Zelenko   if (Data.empty())
669152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
67dc707122SEaswaran Raman   unsigned N = 0;
686a0746a9SFangrui Song   Result = decodeULEB128(Data.bytes_begin(), &N);
69dc707122SEaswaran Raman   if (N > Data.size())
709152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
71dc707122SEaswaran Raman   Data = Data.substr(N);
729152fd17SVedant Kumar   return Error::success();
73dc707122SEaswaran Raman }
74dc707122SEaswaran Raman 
759152fd17SVedant Kumar Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
76dc707122SEaswaran Raman   if (auto Err = readULEB128(Result))
77dc707122SEaswaran Raman     return Err;
78dc707122SEaswaran Raman   if (Result >= MaxPlus1)
799152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
809152fd17SVedant Kumar   return Error::success();
81dc707122SEaswaran Raman }
82dc707122SEaswaran Raman 
839152fd17SVedant Kumar Error RawCoverageReader::readSize(uint64_t &Result) {
84dc707122SEaswaran Raman   if (auto Err = readULEB128(Result))
85dc707122SEaswaran Raman     return Err;
86dc707122SEaswaran Raman   // Sanity check the number.
87dc707122SEaswaran Raman   if (Result > Data.size())
889152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
899152fd17SVedant Kumar   return Error::success();
90dc707122SEaswaran Raman }
91dc707122SEaswaran Raman 
929152fd17SVedant Kumar Error RawCoverageReader::readString(StringRef &Result) {
93dc707122SEaswaran Raman   uint64_t Length;
94dc707122SEaswaran Raman   if (auto Err = readSize(Length))
95dc707122SEaswaran Raman     return Err;
96dc707122SEaswaran Raman   Result = Data.substr(0, Length);
97dc707122SEaswaran Raman   Data = Data.substr(Length);
989152fd17SVedant Kumar   return Error::success();
99dc707122SEaswaran Raman }
100dc707122SEaswaran Raman 
1015fbd1a33SPetr Hosek Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
102dc707122SEaswaran Raman   uint64_t NumFilenames;
103dc707122SEaswaran Raman   if (auto Err = readSize(NumFilenames))
104dc707122SEaswaran Raman     return Err;
105dd1ea9deSVedant Kumar   if (!NumFilenames)
106dd1ea9deSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
107dd1ea9deSVedant Kumar 
108dd1ea9deSVedant Kumar   if (Version < CovMapVersion::Version4)
1095fbd1a33SPetr Hosek     return readUncompressed(Version, NumFilenames);
110dd1ea9deSVedant Kumar 
111dd1ea9deSVedant Kumar   // The uncompressed length may exceed the size of the encoded filenames.
112dd1ea9deSVedant Kumar   // Skip size validation.
113dd1ea9deSVedant Kumar   uint64_t UncompressedLen;
114dd1ea9deSVedant Kumar   if (auto Err = readULEB128(UncompressedLen))
115dd1ea9deSVedant Kumar     return Err;
116dd1ea9deSVedant Kumar 
117dd1ea9deSVedant Kumar   uint64_t CompressedLen;
118dd1ea9deSVedant Kumar   if (auto Err = readSize(CompressedLen))
119dd1ea9deSVedant Kumar     return Err;
120dd1ea9deSVedant Kumar 
121dd1ea9deSVedant Kumar   if (CompressedLen > 0) {
122dd1ea9deSVedant Kumar     if (!zlib::isAvailable())
123dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(
124dd1ea9deSVedant Kumar           coveragemap_error::decompression_failed);
125dd1ea9deSVedant Kumar 
1265fbd1a33SPetr Hosek     // Allocate memory for the decompressed filenames.
1275fbd1a33SPetr Hosek     SmallVector<char, 0> StorageBuf;
128dd1ea9deSVedant Kumar 
129dd1ea9deSVedant Kumar     // Read compressed filenames.
130dd1ea9deSVedant Kumar     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
131dd1ea9deSVedant Kumar     Data = Data.substr(CompressedLen);
132dd1ea9deSVedant Kumar     auto Err =
133dd1ea9deSVedant Kumar         zlib::uncompress(CompressedFilenames, StorageBuf, UncompressedLen);
134dd1ea9deSVedant Kumar     if (Err) {
135dd1ea9deSVedant Kumar       consumeError(std::move(Err));
136dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(
137dd1ea9deSVedant Kumar           coveragemap_error::decompression_failed);
138dd1ea9deSVedant Kumar     }
139dd1ea9deSVedant Kumar 
140dd1ea9deSVedant Kumar     StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
141*8280ece0SPetr Hosek     RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames,
142*8280ece0SPetr Hosek                                         CompilationDir);
1435fbd1a33SPetr Hosek     return Delegate.readUncompressed(Version, NumFilenames);
144dd1ea9deSVedant Kumar   }
145dd1ea9deSVedant Kumar 
1465fbd1a33SPetr Hosek   return readUncompressed(Version, NumFilenames);
147dd1ea9deSVedant Kumar }
148dd1ea9deSVedant Kumar 
1495fbd1a33SPetr Hosek Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
1505fbd1a33SPetr Hosek                                                    uint64_t NumFilenames) {
151dd1ea9deSVedant Kumar   // Read uncompressed filenames.
1525fbd1a33SPetr Hosek   if (Version < CovMapVersion::Version6) {
153dc707122SEaswaran Raman     for (size_t I = 0; I < NumFilenames; ++I) {
154dc707122SEaswaran Raman       StringRef Filename;
155dc707122SEaswaran Raman       if (auto Err = readString(Filename))
156dc707122SEaswaran Raman         return Err;
1575fbd1a33SPetr Hosek       Filenames.push_back(Filename.str());
1585fbd1a33SPetr Hosek     }
1595fbd1a33SPetr Hosek   } else {
1605fbd1a33SPetr Hosek     StringRef CWD;
1615fbd1a33SPetr Hosek     if (auto Err = readString(CWD))
1625fbd1a33SPetr Hosek       return Err;
1635fbd1a33SPetr Hosek     Filenames.push_back(CWD.str());
1645fbd1a33SPetr Hosek 
1655fbd1a33SPetr Hosek     for (size_t I = 1; I < NumFilenames; ++I) {
1665fbd1a33SPetr Hosek       StringRef Filename;
1675fbd1a33SPetr Hosek       if (auto Err = readString(Filename))
1685fbd1a33SPetr Hosek         return Err;
1695fbd1a33SPetr Hosek       if (sys::path::is_absolute(Filename)) {
1705fbd1a33SPetr Hosek         Filenames.push_back(Filename.str());
1715fbd1a33SPetr Hosek       } else {
172*8280ece0SPetr Hosek         SmallString<256> P;
173*8280ece0SPetr Hosek         if (!CompilationDir.empty())
174*8280ece0SPetr Hosek           P.assign(CompilationDir);
175*8280ece0SPetr Hosek         else
176*8280ece0SPetr Hosek           P.assign(CWD);
1775fbd1a33SPetr Hosek         llvm::sys::path::append(P, Filename);
1785fbd1a33SPetr Hosek         Filenames.push_back(static_cast<std::string>(P));
1795fbd1a33SPetr Hosek       }
1805fbd1a33SPetr Hosek     }
181dc707122SEaswaran Raman   }
1829152fd17SVedant Kumar   return Error::success();
183dc707122SEaswaran Raman }
184dc707122SEaswaran Raman 
1859152fd17SVedant Kumar Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
186dc707122SEaswaran Raman   auto Tag = Value & Counter::EncodingTagMask;
187dc707122SEaswaran Raman   switch (Tag) {
188dc707122SEaswaran Raman   case Counter::Zero:
189dc707122SEaswaran Raman     C = Counter::getZero();
1909152fd17SVedant Kumar     return Error::success();
191dc707122SEaswaran Raman   case Counter::CounterValueReference:
192dc707122SEaswaran Raman     C = Counter::getCounter(Value >> Counter::EncodingTagBits);
1939152fd17SVedant Kumar     return Error::success();
194dc707122SEaswaran Raman   default:
195dc707122SEaswaran Raman     break;
196dc707122SEaswaran Raman   }
197dc707122SEaswaran Raman   Tag -= Counter::Expression;
198dc707122SEaswaran Raman   switch (Tag) {
199dc707122SEaswaran Raman   case CounterExpression::Subtract:
200dc707122SEaswaran Raman   case CounterExpression::Add: {
201dc707122SEaswaran Raman     auto ID = Value >> Counter::EncodingTagBits;
202dc707122SEaswaran Raman     if (ID >= Expressions.size())
2039152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
204dc707122SEaswaran Raman     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
205dc707122SEaswaran Raman     C = Counter::getExpression(ID);
206dc707122SEaswaran Raman     break;
207dc707122SEaswaran Raman   }
208dc707122SEaswaran Raman   default:
2099152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
210dc707122SEaswaran Raman   }
2119152fd17SVedant Kumar   return Error::success();
212dc707122SEaswaran Raman }
213dc707122SEaswaran Raman 
2149152fd17SVedant Kumar Error RawCoverageMappingReader::readCounter(Counter &C) {
215dc707122SEaswaran Raman   uint64_t EncodedCounter;
216dc707122SEaswaran Raman   if (auto Err =
217dc707122SEaswaran Raman           readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
218dc707122SEaswaran Raman     return Err;
219dc707122SEaswaran Raman   if (auto Err = decodeCounter(EncodedCounter, C))
220dc707122SEaswaran Raman     return Err;
2219152fd17SVedant Kumar   return Error::success();
222dc707122SEaswaran Raman }
223dc707122SEaswaran Raman 
224dc707122SEaswaran Raman static const unsigned EncodingExpansionRegionBit = 1
225dc707122SEaswaran Raman                                                    << Counter::EncodingTagBits;
226dc707122SEaswaran Raman 
2275f8f34e4SAdrian Prantl /// Read the sub-array of regions for the given inferred file id.
228dc707122SEaswaran Raman /// \param NumFileIDs the number of file ids that are defined for this
229dc707122SEaswaran Raman /// function.
2309152fd17SVedant Kumar Error RawCoverageMappingReader::readMappingRegionsSubArray(
231dc707122SEaswaran Raman     std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
232dc707122SEaswaran Raman     size_t NumFileIDs) {
233dc707122SEaswaran Raman   uint64_t NumRegions;
234dc707122SEaswaran Raman   if (auto Err = readSize(NumRegions))
235dc707122SEaswaran Raman     return Err;
236dc707122SEaswaran Raman   unsigned LineStart = 0;
237dc707122SEaswaran Raman   for (size_t I = 0; I < NumRegions; ++I) {
2389f2967bcSAlan Phipps     Counter C, C2;
239dc707122SEaswaran Raman     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
240dc707122SEaswaran Raman 
241dc707122SEaswaran Raman     // Read the combined counter + region kind.
242dc707122SEaswaran Raman     uint64_t EncodedCounterAndRegion;
243dc707122SEaswaran Raman     if (auto Err = readIntMax(EncodedCounterAndRegion,
244dc707122SEaswaran Raman                               std::numeric_limits<unsigned>::max()))
245dc707122SEaswaran Raman       return Err;
246dc707122SEaswaran Raman     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
247dc707122SEaswaran Raman     uint64_t ExpandedFileID = 0;
2489f2967bcSAlan Phipps 
2499f2967bcSAlan Phipps     // If Tag does not represent a ZeroCounter, then it is understood to refer
2509f2967bcSAlan Phipps     // to a counter or counter expression with region kind assumed to be
2519f2967bcSAlan Phipps     // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
2529f2967bcSAlan Phipps     // referenced counter or counter expression (and nothing else).
2539f2967bcSAlan Phipps     //
2549f2967bcSAlan Phipps     // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
2559f2967bcSAlan Phipps     // then EncodedCounterAndRegion is interpreted to represent an
2569f2967bcSAlan Phipps     // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
2579f2967bcSAlan Phipps     // interpreted to refer to a specific region kind, after which additional
2589f2967bcSAlan Phipps     // fields may be read (e.g. BranchRegions have two encoded counters that
2599f2967bcSAlan Phipps     // follow an encoded region kind value).
260dc707122SEaswaran Raman     if (Tag != Counter::Zero) {
261dc707122SEaswaran Raman       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
262dc707122SEaswaran Raman         return Err;
263dc707122SEaswaran Raman     } else {
264dc707122SEaswaran Raman       // Is it an expansion region?
265dc707122SEaswaran Raman       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
266dc707122SEaswaran Raman         Kind = CounterMappingRegion::ExpansionRegion;
267dc707122SEaswaran Raman         ExpandedFileID = EncodedCounterAndRegion >>
268dc707122SEaswaran Raman                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
269dc707122SEaswaran Raman         if (ExpandedFileID >= NumFileIDs)
2709152fd17SVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
271dc707122SEaswaran Raman       } else {
272dc707122SEaswaran Raman         switch (EncodedCounterAndRegion >>
273dc707122SEaswaran Raman                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
274dc707122SEaswaran Raman         case CounterMappingRegion::CodeRegion:
275dc707122SEaswaran Raman           // Don't do anything when we have a code region with a zero counter.
276dc707122SEaswaran Raman           break;
277dc707122SEaswaran Raman         case CounterMappingRegion::SkippedRegion:
278dc707122SEaswaran Raman           Kind = CounterMappingRegion::SkippedRegion;
279dc707122SEaswaran Raman           break;
2809f2967bcSAlan Phipps         case CounterMappingRegion::BranchRegion:
2819f2967bcSAlan Phipps           // For a Branch Region, read two successive counters.
2829f2967bcSAlan Phipps           Kind = CounterMappingRegion::BranchRegion;
2839f2967bcSAlan Phipps           if (auto Err = readCounter(C))
2849f2967bcSAlan Phipps             return Err;
2859f2967bcSAlan Phipps           if (auto Err = readCounter(C2))
2869f2967bcSAlan Phipps             return Err;
2879f2967bcSAlan Phipps           break;
288dc707122SEaswaran Raman         default:
2899152fd17SVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
290dc707122SEaswaran Raman         }
291dc707122SEaswaran Raman       }
292dc707122SEaswaran Raman     }
293dc707122SEaswaran Raman 
294dc707122SEaswaran Raman     // Read the source range.
295dc707122SEaswaran Raman     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
296dc707122SEaswaran Raman     if (auto Err =
297dc707122SEaswaran Raman             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
298dc707122SEaswaran Raman       return Err;
299dc707122SEaswaran Raman     if (auto Err = readULEB128(ColumnStart))
300dc707122SEaswaran Raman       return Err;
301dc707122SEaswaran Raman     if (ColumnStart > std::numeric_limits<unsigned>::max())
3029152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
303dc707122SEaswaran Raman     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
304dc707122SEaswaran Raman       return Err;
305dc707122SEaswaran Raman     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
306dc707122SEaswaran Raman       return Err;
307dc707122SEaswaran Raman     LineStart += LineStartDelta;
308ad8f637bSVedant Kumar 
309ad8f637bSVedant Kumar     // If the high bit of ColumnEnd is set, this is a gap region.
310ad8f637bSVedant Kumar     if (ColumnEnd & (1U << 31)) {
311ad8f637bSVedant Kumar       Kind = CounterMappingRegion::GapRegion;
312ad8f637bSVedant Kumar       ColumnEnd &= ~(1U << 31);
313ad8f637bSVedant Kumar     }
314ad8f637bSVedant Kumar 
315dc707122SEaswaran Raman     // Adjust the column locations for the empty regions that are supposed to
316dc707122SEaswaran Raman     // cover whole lines. Those regions should be encoded with the
317dc707122SEaswaran Raman     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
318dc707122SEaswaran Raman     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
319dc707122SEaswaran Raman     // we set the column range to (0 -> 0) to ensure that the column start and
320dc707122SEaswaran Raman     // column end take up one byte each.
321dc707122SEaswaran Raman     // The std::numeric_limits<unsigned>::max() is used to represent a column
322dc707122SEaswaran Raman     // position at the end of the line without knowing the length of that line.
323dc707122SEaswaran Raman     if (ColumnStart == 0 && ColumnEnd == 0) {
324dc707122SEaswaran Raman       ColumnStart = 1;
325dc707122SEaswaran Raman       ColumnEnd = std::numeric_limits<unsigned>::max();
326dc707122SEaswaran Raman     }
327dc707122SEaswaran Raman 
328d34e60caSNicola Zaghen     LLVM_DEBUG({
329dc707122SEaswaran Raman       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
330dc707122SEaswaran Raman              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
331dc707122SEaswaran Raman              << ColumnEnd << ", ";
332dc707122SEaswaran Raman       if (Kind == CounterMappingRegion::ExpansionRegion)
333dc707122SEaswaran Raman         dbgs() << "Expands to file " << ExpandedFileID;
334dc707122SEaswaran Raman       else
335dc707122SEaswaran Raman         CounterMappingContext(Expressions).dump(C, dbgs());
336dc707122SEaswaran Raman       dbgs() << "\n";
337dc707122SEaswaran Raman     });
338dc707122SEaswaran Raman 
3399f2967bcSAlan Phipps     auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID,
340bae83970SVedant Kumar                                     LineStart, ColumnStart,
341bae83970SVedant Kumar                                     LineStart + NumLines, ColumnEnd, Kind);
342bae83970SVedant Kumar     if (CMR.startLoc() > CMR.endLoc())
343bae83970SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
344bae83970SVedant Kumar     MappingRegions.push_back(CMR);
345dc707122SEaswaran Raman   }
3469152fd17SVedant Kumar   return Error::success();
347dc707122SEaswaran Raman }
348dc707122SEaswaran Raman 
3499152fd17SVedant Kumar Error RawCoverageMappingReader::read() {
350dc707122SEaswaran Raman   // Read the virtual file mapping.
351e78d131aSEugene Zelenko   SmallVector<unsigned, 8> VirtualFileMapping;
352dc707122SEaswaran Raman   uint64_t NumFileMappings;
353dc707122SEaswaran Raman   if (auto Err = readSize(NumFileMappings))
354dc707122SEaswaran Raman     return Err;
355dc707122SEaswaran Raman   for (size_t I = 0; I < NumFileMappings; ++I) {
356dc707122SEaswaran Raman     uint64_t FilenameIndex;
357dc707122SEaswaran Raman     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
358dc707122SEaswaran Raman       return Err;
359dc707122SEaswaran Raman     VirtualFileMapping.push_back(FilenameIndex);
360dc707122SEaswaran Raman   }
361dc707122SEaswaran Raman 
362dc707122SEaswaran Raman   // Construct the files using unique filenames and virtual file mapping.
363dc707122SEaswaran Raman   for (auto I : VirtualFileMapping) {
364dc707122SEaswaran Raman     Filenames.push_back(TranslationUnitFilenames[I]);
365dc707122SEaswaran Raman   }
366dc707122SEaswaran Raman 
367dc707122SEaswaran Raman   // Read the expressions.
368dc707122SEaswaran Raman   uint64_t NumExpressions;
369dc707122SEaswaran Raman   if (auto Err = readSize(NumExpressions))
370dc707122SEaswaran Raman     return Err;
371dc707122SEaswaran Raman   // Create an array of dummy expressions that get the proper counters
372dc707122SEaswaran Raman   // when the expressions are read, and the proper kinds when the counters
373dc707122SEaswaran Raman   // are decoded.
374dc707122SEaswaran Raman   Expressions.resize(
375dc707122SEaswaran Raman       NumExpressions,
376dc707122SEaswaran Raman       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
377dc707122SEaswaran Raman   for (size_t I = 0; I < NumExpressions; ++I) {
378dc707122SEaswaran Raman     if (auto Err = readCounter(Expressions[I].LHS))
379dc707122SEaswaran Raman       return Err;
380dc707122SEaswaran Raman     if (auto Err = readCounter(Expressions[I].RHS))
381dc707122SEaswaran Raman       return Err;
382dc707122SEaswaran Raman   }
383dc707122SEaswaran Raman 
384dc707122SEaswaran Raman   // Read the mapping regions sub-arrays.
385dc707122SEaswaran Raman   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
386dc707122SEaswaran Raman        InferredFileID < S; ++InferredFileID) {
387dc707122SEaswaran Raman     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
388dc707122SEaswaran Raman                                               VirtualFileMapping.size()))
389dc707122SEaswaran Raman       return Err;
390dc707122SEaswaran Raman   }
391dc707122SEaswaran Raman 
392dc707122SEaswaran Raman   // Set the counters for the expansion regions.
393dc707122SEaswaran Raman   // i.e. Counter of expansion region = counter of the first region
394dc707122SEaswaran Raman   // from the expanded file.
395dc707122SEaswaran Raman   // Perform multiple passes to correctly propagate the counters through
396dc707122SEaswaran Raman   // all the nested expansion regions.
397dc707122SEaswaran Raman   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
398dc707122SEaswaran Raman   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
399dc707122SEaswaran Raman   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
400dc707122SEaswaran Raman     for (auto &R : MappingRegions) {
401dc707122SEaswaran Raman       if (R.Kind != CounterMappingRegion::ExpansionRegion)
402dc707122SEaswaran Raman         continue;
403dc707122SEaswaran Raman       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
404dc707122SEaswaran Raman       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
405dc707122SEaswaran Raman     }
406dc707122SEaswaran Raman     for (auto &R : MappingRegions) {
407dc707122SEaswaran Raman       if (FileIDExpansionRegionMapping[R.FileID]) {
408dc707122SEaswaran Raman         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
409dc707122SEaswaran Raman         FileIDExpansionRegionMapping[R.FileID] = nullptr;
410dc707122SEaswaran Raman       }
411dc707122SEaswaran Raman     }
412dc707122SEaswaran Raman   }
413dc707122SEaswaran Raman 
4149152fd17SVedant Kumar   return Error::success();
415dc707122SEaswaran Raman }
416dc707122SEaswaran Raman 
417ac40e819SIgor Kudrin Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
418ac40e819SIgor Kudrin   // A dummy coverage mapping data consists of just one region with zero count.
419ac40e819SIgor Kudrin   uint64_t NumFileMappings;
420ac40e819SIgor Kudrin   if (Error Err = readSize(NumFileMappings))
421c55cf4afSBill Wendling     return std::move(Err);
422ac40e819SIgor Kudrin   if (NumFileMappings != 1)
423ac40e819SIgor Kudrin     return false;
424ac40e819SIgor Kudrin   // We don't expect any specific value for the filename index, just skip it.
425ac40e819SIgor Kudrin   uint64_t FilenameIndex;
426ac40e819SIgor Kudrin   if (Error Err =
427ac40e819SIgor Kudrin           readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
428c55cf4afSBill Wendling     return std::move(Err);
429ac40e819SIgor Kudrin   uint64_t NumExpressions;
430ac40e819SIgor Kudrin   if (Error Err = readSize(NumExpressions))
431c55cf4afSBill Wendling     return std::move(Err);
432ac40e819SIgor Kudrin   if (NumExpressions != 0)
433ac40e819SIgor Kudrin     return false;
434ac40e819SIgor Kudrin   uint64_t NumRegions;
435ac40e819SIgor Kudrin   if (Error Err = readSize(NumRegions))
436c55cf4afSBill Wendling     return std::move(Err);
437ac40e819SIgor Kudrin   if (NumRegions != 1)
438ac40e819SIgor Kudrin     return false;
439ac40e819SIgor Kudrin   uint64_t EncodedCounterAndRegion;
440ac40e819SIgor Kudrin   if (Error Err = readIntMax(EncodedCounterAndRegion,
441ac40e819SIgor Kudrin                              std::numeric_limits<unsigned>::max()))
442c55cf4afSBill Wendling     return std::move(Err);
443ac40e819SIgor Kudrin   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
444ac40e819SIgor Kudrin   return Tag == Counter::Zero;
445ac40e819SIgor Kudrin }
446ac40e819SIgor Kudrin 
4479152fd17SVedant Kumar Error InstrProfSymtab::create(SectionRef &Section) {
448e183340cSFangrui Song   Expected<StringRef> DataOrErr = Section.getContents();
449e183340cSFangrui Song   if (!DataOrErr)
450e183340cSFangrui Song     return DataOrErr.takeError();
451e183340cSFangrui Song   Data = *DataOrErr;
452dc707122SEaswaran Raman   Address = Section.getAddress();
4538b6af001SReid Kleckner 
4548b6af001SReid Kleckner   // If this is a linked PE/COFF file, then we have to skip over the null byte
4558b6af001SReid Kleckner   // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
4568b6af001SReid Kleckner   const ObjectFile *Obj = Section.getObject();
4578b6af001SReid Kleckner   if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
4588b6af001SReid Kleckner     Data = Data.drop_front(1);
4598b6af001SReid Kleckner 
4609152fd17SVedant Kumar   return Error::success();
461dc707122SEaswaran Raman }
462dc707122SEaswaran Raman 
463dc707122SEaswaran Raman StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
464dc707122SEaswaran Raman   if (Pointer < Address)
465dc707122SEaswaran Raman     return StringRef();
466dc707122SEaswaran Raman   auto Offset = Pointer - Address;
467dc707122SEaswaran Raman   if (Offset + Size > Data.size())
468dc707122SEaswaran Raman     return StringRef();
469dc707122SEaswaran Raman   return Data.substr(Pointer - Address, Size);
470dc707122SEaswaran Raman }
471dc707122SEaswaran Raman 
472ac40e819SIgor Kudrin // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
473ac40e819SIgor Kudrin static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
474ac40e819SIgor Kudrin   // The hash value of dummy mapping records is always zero.
475ac40e819SIgor Kudrin   if (Hash)
476ac40e819SIgor Kudrin     return false;
477ac40e819SIgor Kudrin   return RawCoverageMappingDummyChecker(Mapping).isDummy();
478ac40e819SIgor Kudrin }
479ac40e819SIgor Kudrin 
480dd1ea9deSVedant Kumar /// A range of filename indices. Used to specify the location of a batch of
481dd1ea9deSVedant Kumar /// filenames in a vector-like container.
482dd1ea9deSVedant Kumar struct FilenameRange {
483dd1ea9deSVedant Kumar   unsigned StartingIndex;
484dd1ea9deSVedant Kumar   unsigned Length;
485dd1ea9deSVedant Kumar 
486dd1ea9deSVedant Kumar   FilenameRange(unsigned StartingIndex, unsigned Length)
487dd1ea9deSVedant Kumar       : StartingIndex(StartingIndex), Length(Length) {}
488dd1ea9deSVedant Kumar 
489dd1ea9deSVedant Kumar   void markInvalid() { Length = 0; }
490dd1ea9deSVedant Kumar   bool isInvalid() const { return Length == 0; }
491dd1ea9deSVedant Kumar };
492dd1ea9deSVedant Kumar 
493dc707122SEaswaran Raman namespace {
494e78d131aSEugene Zelenko 
495dd1ea9deSVedant Kumar /// The interface to read coverage mapping function records for a module.
496dc707122SEaswaran Raman struct CovMapFuncRecordReader {
497e78d131aSEugene Zelenko   virtual ~CovMapFuncRecordReader() = default;
498e78d131aSEugene Zelenko 
499dd1ea9deSVedant Kumar   // Read a coverage header.
5003739b95dSVedant Kumar   //
501dd1ea9deSVedant Kumar   // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
5023739b95dSVedant Kumar   // mapping data associated with the module.
5033739b95dSVedant Kumar   //
504dd1ea9deSVedant Kumar   // Returns a pointer to the next \c CovHeader if it exists, or to an address
505dd1ea9deSVedant Kumar   // greater than \p CovEnd if not.
5065fbd1a33SPetr Hosek   virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
5075fbd1a33SPetr Hosek                                                     const char *CovBufEnd) = 0;
508dd1ea9deSVedant Kumar 
509dd1ea9deSVedant Kumar   // Read function records.
510dd1ea9deSVedant Kumar   //
511dd1ea9deSVedant Kumar   // \p FuncRecBuf points to the buffer containing a batch of function records.
512dd1ea9deSVedant Kumar   // \p FuncRecBufEnd points past the end of the batch of records.
513dd1ea9deSVedant Kumar   //
514dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
515dd1ea9deSVedant Kumar   // associated with the function records. It is unused in Version4.
516dd1ea9deSVedant Kumar   //
517dd1ea9deSVedant Kumar   // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
518dd1ea9deSVedant Kumar   // mappings associated with the function records. It is unused in Version4.
519dd1ea9deSVedant Kumar   virtual Error readFunctionRecords(const char *FuncRecBuf,
520dd1ea9deSVedant Kumar                                     const char *FuncRecBufEnd,
521dd1ea9deSVedant Kumar                                     Optional<FilenameRange> OutOfLineFileRange,
522dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBuf,
523dd1ea9deSVedant Kumar                                     const char *OutOfLineMappingBufEnd) = 0;
524e78d131aSEugene Zelenko 
525dc707122SEaswaran Raman   template <class IntPtrT, support::endianness Endian>
5269152fd17SVedant Kumar   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
527e78d131aSEugene Zelenko   get(CovMapVersion Version, InstrProfSymtab &P,
528*8280ece0SPetr Hosek       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
5295fbd1a33SPetr Hosek       std::vector<std::string> &F);
530dc707122SEaswaran Raman };
531dc707122SEaswaran Raman 
532dc707122SEaswaran Raman // A class for reading coverage mapping function records for a module.
533e78d131aSEugene Zelenko template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
534dc707122SEaswaran Raman class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
53572208a82SEugene Zelenko   using FuncRecordType =
53672208a82SEugene Zelenko       typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
53772208a82SEugene Zelenko   using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
538dc707122SEaswaran Raman 
539ac40e819SIgor Kudrin   // Maps function's name references to the indexes of their records
540ac40e819SIgor Kudrin   // in \c Records.
541e78d131aSEugene Zelenko   DenseMap<NameRefType, size_t> FunctionRecords;
542dc707122SEaswaran Raman   InstrProfSymtab &ProfileNames;
543*8280ece0SPetr Hosek   StringRef CompilationDir;
5445fbd1a33SPetr Hosek   std::vector<std::string> &Filenames;
545dc707122SEaswaran Raman   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
546dc707122SEaswaran Raman 
547dd1ea9deSVedant Kumar   // Maps a hash of the filenames in a TU to a \c FileRange. The range
548dd1ea9deSVedant Kumar   // specifies the location of the hashed filenames in \c Filenames.
549dd1ea9deSVedant Kumar   DenseMap<uint64_t, FilenameRange> FileRangeMap;
550dd1ea9deSVedant Kumar 
551ac40e819SIgor Kudrin   // Add the record to the collection if we don't already have a record that
552ac40e819SIgor Kudrin   // points to the same function name. This is useful to ignore the redundant
553ac40e819SIgor Kudrin   // records for the functions with ODR linkage.
554ac40e819SIgor Kudrin   // In addition, prefer records with real coverage mapping data to dummy
555ac40e819SIgor Kudrin   // records, which were emitted for inline functions which were seen but
556ac40e819SIgor Kudrin   // not used in the corresponding translation unit.
557ac40e819SIgor Kudrin   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
558dd1ea9deSVedant Kumar                                      StringRef Mapping,
559dd1ea9deSVedant Kumar                                      FilenameRange FileRange) {
560dd1ea9deSVedant Kumar     ++CovMapNumRecords;
561ac40e819SIgor Kudrin     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
562ac40e819SIgor Kudrin     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
563ac40e819SIgor Kudrin     auto InsertResult =
564ac40e819SIgor Kudrin         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
565ac40e819SIgor Kudrin     if (InsertResult.second) {
566ac40e819SIgor Kudrin       StringRef FuncName;
567ac40e819SIgor Kudrin       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
568ac40e819SIgor Kudrin         return Err;
569b5794ca9SVedant Kumar       if (FuncName.empty())
570b5794ca9SVedant Kumar         return make_error<InstrProfError>(instrprof_error::malformed);
571dd1ea9deSVedant Kumar       ++CovMapNumUsedRecords;
572dd1ea9deSVedant Kumar       Records.emplace_back(Version, FuncName, FuncHash, Mapping,
573dd1ea9deSVedant Kumar                            FileRange.StartingIndex, FileRange.Length);
574ac40e819SIgor Kudrin       return Error::success();
575ac40e819SIgor Kudrin     }
576ac40e819SIgor Kudrin     // Update the existing record if it's a dummy and the new record is real.
577ac40e819SIgor Kudrin     size_t OldRecordIndex = InsertResult.first->second;
578ac40e819SIgor Kudrin     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
579ac40e819SIgor Kudrin         Records[OldRecordIndex];
580ac40e819SIgor Kudrin     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
581ac40e819SIgor Kudrin         OldRecord.FunctionHash, OldRecord.CoverageMapping);
582ac40e819SIgor Kudrin     if (Error Err = OldIsDummyExpected.takeError())
583ac40e819SIgor Kudrin       return Err;
584ac40e819SIgor Kudrin     if (!*OldIsDummyExpected)
585ac40e819SIgor Kudrin       return Error::success();
586ac40e819SIgor Kudrin     Expected<bool> NewIsDummyExpected =
587ac40e819SIgor Kudrin         isCoverageMappingDummy(FuncHash, Mapping);
588ac40e819SIgor Kudrin     if (Error Err = NewIsDummyExpected.takeError())
589ac40e819SIgor Kudrin       return Err;
590ac40e819SIgor Kudrin     if (*NewIsDummyExpected)
591ac40e819SIgor Kudrin       return Error::success();
592dd1ea9deSVedant Kumar     ++CovMapNumUsedRecords;
593ac40e819SIgor Kudrin     OldRecord.FunctionHash = FuncHash;
594ac40e819SIgor Kudrin     OldRecord.CoverageMapping = Mapping;
595dd1ea9deSVedant Kumar     OldRecord.FilenamesBegin = FileRange.StartingIndex;
596dd1ea9deSVedant Kumar     OldRecord.FilenamesSize = FileRange.Length;
597ac40e819SIgor Kudrin     return Error::success();
598ac40e819SIgor Kudrin   }
599ac40e819SIgor Kudrin 
600dc707122SEaswaran Raman public:
601dc707122SEaswaran Raman   VersionedCovMapFuncRecordReader(
602dc707122SEaswaran Raman       InstrProfSymtab &P,
603*8280ece0SPetr Hosek       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
6045fbd1a33SPetr Hosek       std::vector<std::string> &F)
605*8280ece0SPetr Hosek       : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
606e78d131aSEugene Zelenko 
607e78d131aSEugene Zelenko   ~VersionedCovMapFuncRecordReader() override = default;
608dc707122SEaswaran Raman 
6095fbd1a33SPetr Hosek   Expected<const char *> readCoverageHeader(const char *CovBuf,
6105fbd1a33SPetr Hosek                                             const char *CovBufEnd) override {
611dc707122SEaswaran Raman     using namespace support;
612e78d131aSEugene Zelenko 
613dd1ea9deSVedant Kumar     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
6149152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
615dd1ea9deSVedant Kumar     auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
616dc707122SEaswaran Raman     uint32_t NRecords = CovHeader->getNRecords<Endian>();
617dc707122SEaswaran Raman     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
618dc707122SEaswaran Raman     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
619dc707122SEaswaran Raman     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
620dd1ea9deSVedant Kumar     CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
621dc707122SEaswaran Raman 
622dc707122SEaswaran Raman     // Skip past the function records, saving the start and end for later.
623dd1ea9deSVedant Kumar     // This is a no-op in Version4 (function records are read after all headers
624dd1ea9deSVedant Kumar     // are read).
625dd1ea9deSVedant Kumar     const char *FuncRecBuf = nullptr;
626dd1ea9deSVedant Kumar     const char *FuncRecBufEnd = nullptr;
627dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
628dd1ea9deSVedant Kumar       FuncRecBuf = CovBuf;
629dd1ea9deSVedant Kumar     CovBuf += NRecords * sizeof(FuncRecordType);
630dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4)
631dd1ea9deSVedant Kumar       FuncRecBufEnd = CovBuf;
632dc707122SEaswaran Raman 
633dc707122SEaswaran Raman     // Get the filenames.
634dd1ea9deSVedant Kumar     if (CovBuf + FilenamesSize > CovBufEnd)
6359152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
636dc707122SEaswaran Raman     size_t FilenamesBegin = Filenames.size();
637dd1ea9deSVedant Kumar     StringRef FilenameRegion(CovBuf, FilenamesSize);
638*8280ece0SPetr Hosek     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
639*8280ece0SPetr Hosek                                       CompilationDir);
6405fbd1a33SPetr Hosek     if (auto Err = Reader.read(Version))
641c55cf4afSBill Wendling       return std::move(Err);
642dd1ea9deSVedant Kumar     CovBuf += FilenamesSize;
643dd1ea9deSVedant Kumar     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
644dd1ea9deSVedant Kumar 
6459f2967bcSAlan Phipps     if (Version >= CovMapVersion::Version4) {
646dd1ea9deSVedant Kumar       // Map a hash of the filenames region to the filename range associated
647dd1ea9deSVedant Kumar       // with this coverage header.
648dd1ea9deSVedant Kumar       int64_t FilenamesRef =
649dd1ea9deSVedant Kumar           llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
650dd1ea9deSVedant Kumar       auto Insert =
651dd1ea9deSVedant Kumar           FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
652dd1ea9deSVedant Kumar       if (!Insert.second) {
653dd1ea9deSVedant Kumar         // The same filenames ref was encountered twice. It's possible that
654dd1ea9deSVedant Kumar         // the associated filenames are the same.
655dd1ea9deSVedant Kumar         auto It = Filenames.begin();
656dd1ea9deSVedant Kumar         FilenameRange &OrigRange = Insert.first->getSecond();
657dd1ea9deSVedant Kumar         if (std::equal(It + OrigRange.StartingIndex,
658dd1ea9deSVedant Kumar                        It + OrigRange.StartingIndex + OrigRange.Length,
659dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex,
660dd1ea9deSVedant Kumar                        It + FileRange.StartingIndex + FileRange.Length))
661dd1ea9deSVedant Kumar           // Map the new range to the original one.
662dd1ea9deSVedant Kumar           FileRange = OrigRange;
663dd1ea9deSVedant Kumar         else
664dd1ea9deSVedant Kumar           // This is a hash collision. Mark the filenames ref invalid.
665dd1ea9deSVedant Kumar           OrigRange.markInvalid();
666dd1ea9deSVedant Kumar       }
667dd1ea9deSVedant Kumar     }
668dc707122SEaswaran Raman 
669dc707122SEaswaran Raman     // We'll read the coverage mapping records in the loop below.
670dd1ea9deSVedant Kumar     // This is a no-op in Version4 (coverage mappings are not affixed to the
671dd1ea9deSVedant Kumar     // coverage header).
672dd1ea9deSVedant Kumar     const char *MappingBuf = CovBuf;
6739f2967bcSAlan Phipps     if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
6749152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
675dd1ea9deSVedant Kumar     CovBuf += CoverageSize;
676dd1ea9deSVedant Kumar     const char *MappingEnd = CovBuf;
677dd1ea9deSVedant Kumar 
678dd1ea9deSVedant Kumar     if (CovBuf > CovBufEnd)
679dd1ea9deSVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
680dd1ea9deSVedant Kumar 
681dd1ea9deSVedant Kumar     if (Version < CovMapVersion::Version4) {
682dd1ea9deSVedant Kumar       // Read each function record.
683dd1ea9deSVedant Kumar       if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
684dd1ea9deSVedant Kumar                                         MappingBuf, MappingEnd))
685dd1ea9deSVedant Kumar         return std::move(E);
686dd1ea9deSVedant Kumar     }
687dd1ea9deSVedant Kumar 
688dc707122SEaswaran Raman     // Each coverage map has an alignment of 8, so we need to adjust alignment
689dc707122SEaswaran Raman     // before reading the next map.
690dd1ea9deSVedant Kumar     CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
691dc707122SEaswaran Raman 
692dd1ea9deSVedant Kumar     return CovBuf;
69399317124SVedant Kumar   }
694dd1ea9deSVedant Kumar 
695dd1ea9deSVedant Kumar   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
696dd1ea9deSVedant Kumar                             Optional<FilenameRange> OutOfLineFileRange,
697dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBuf,
698dd1ea9deSVedant Kumar                             const char *OutOfLineMappingBufEnd) override {
699dd1ea9deSVedant Kumar     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
700dd1ea9deSVedant Kumar     while ((const char *)CFR < FuncRecBufEnd) {
701dd1ea9deSVedant Kumar       // Validate the length of the coverage mapping for this function.
702dd1ea9deSVedant Kumar       const char *NextMappingBuf;
703dd1ea9deSVedant Kumar       const FuncRecordType *NextCFR;
704dd1ea9deSVedant Kumar       std::tie(NextMappingBuf, NextCFR) =
705dd1ea9deSVedant Kumar           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
706dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4)
707dd1ea9deSVedant Kumar         if (NextMappingBuf > OutOfLineMappingBufEnd)
708dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
709dd1ea9deSVedant Kumar 
710dd1ea9deSVedant Kumar       // Look up the set of filenames associated with this function record.
711dd1ea9deSVedant Kumar       Optional<FilenameRange> FileRange;
712dd1ea9deSVedant Kumar       if (Version < CovMapVersion::Version4) {
713dd1ea9deSVedant Kumar         FileRange = OutOfLineFileRange;
714dd1ea9deSVedant Kumar       } else {
715dd1ea9deSVedant Kumar         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
716dd1ea9deSVedant Kumar         auto It = FileRangeMap.find(FilenamesRef);
717dd1ea9deSVedant Kumar         if (It == FileRangeMap.end())
718dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
719dd1ea9deSVedant Kumar         else
720dd1ea9deSVedant Kumar           FileRange = It->getSecond();
721dd1ea9deSVedant Kumar       }
722dd1ea9deSVedant Kumar 
723dd1ea9deSVedant Kumar       // Now, read the coverage data.
724dd1ea9deSVedant Kumar       if (FileRange && !FileRange->isInvalid()) {
725dd1ea9deSVedant Kumar         StringRef Mapping =
726dd1ea9deSVedant Kumar             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
7279f2967bcSAlan Phipps         if (Version >= CovMapVersion::Version4 &&
728dd1ea9deSVedant Kumar             Mapping.data() + Mapping.size() > FuncRecBufEnd)
729dd1ea9deSVedant Kumar           return make_error<CoverageMapError>(coveragemap_error::malformed);
730dd1ea9deSVedant Kumar         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
731dd1ea9deSVedant Kumar           return Err;
732dd1ea9deSVedant Kumar       }
733dd1ea9deSVedant Kumar 
734dd1ea9deSVedant Kumar       std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
735dd1ea9deSVedant Kumar     }
736dd1ea9deSVedant Kumar     return Error::success();
737dc707122SEaswaran Raman   }
738dc707122SEaswaran Raman };
739e78d131aSEugene Zelenko 
740dc707122SEaswaran Raman } // end anonymous namespace
741dc707122SEaswaran Raman 
742dc707122SEaswaran Raman template <class IntPtrT, support::endianness Endian>
7439152fd17SVedant Kumar Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
744e78d131aSEugene Zelenko     CovMapVersion Version, InstrProfSymtab &P,
745*8280ece0SPetr Hosek     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
7465fbd1a33SPetr Hosek     std::vector<std::string> &F) {
747dc707122SEaswaran Raman   using namespace coverage;
748e78d131aSEugene Zelenko 
749dc707122SEaswaran Raman   switch (Version) {
750dc707122SEaswaran Raman   case CovMapVersion::Version1:
7510eaee545SJonas Devlieghere     return std::make_unique<VersionedCovMapFuncRecordReader<
752*8280ece0SPetr Hosek         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
753dc707122SEaswaran Raman   case CovMapVersion::Version2:
754ad8f637bSVedant Kumar   case CovMapVersion::Version3:
755dd1ea9deSVedant Kumar   case CovMapVersion::Version4:
7569f2967bcSAlan Phipps   case CovMapVersion::Version5:
7575fbd1a33SPetr Hosek   case CovMapVersion::Version6:
758dc707122SEaswaran Raman     // Decompress the name data.
7599152fd17SVedant Kumar     if (Error E = P.create(P.getNameData()))
760c55cf4afSBill Wendling       return std::move(E);
761ad8f637bSVedant Kumar     if (Version == CovMapVersion::Version2)
7620eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
763*8280ece0SPetr Hosek           CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
764dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version3)
7650eaee545SJonas Devlieghere       return std::make_unique<VersionedCovMapFuncRecordReader<
766*8280ece0SPetr Hosek           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
767dd1ea9deSVedant Kumar     else if (Version == CovMapVersion::Version4)
768dd1ea9deSVedant Kumar       return std::make_unique<VersionedCovMapFuncRecordReader<
769*8280ece0SPetr Hosek           CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
7709f2967bcSAlan Phipps     else if (Version == CovMapVersion::Version5)
7719f2967bcSAlan Phipps       return std::make_unique<VersionedCovMapFuncRecordReader<
772*8280ece0SPetr Hosek           CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
7735fbd1a33SPetr Hosek     else if (Version == CovMapVersion::Version6)
7745fbd1a33SPetr Hosek       return std::make_unique<VersionedCovMapFuncRecordReader<
775*8280ece0SPetr Hosek           CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
776dc707122SEaswaran Raman   }
777dc707122SEaswaran Raman   llvm_unreachable("Unsupported version");
778dc707122SEaswaran Raman }
779dc707122SEaswaran Raman 
780dc707122SEaswaran Raman template <typename T, support::endianness Endian>
7819152fd17SVedant Kumar static Error readCoverageMappingData(
782dd1ea9deSVedant Kumar     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
783dc707122SEaswaran Raman     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
784*8280ece0SPetr Hosek     StringRef CompilationDir, std::vector<std::string> &Filenames) {
785dc707122SEaswaran Raman   using namespace coverage;
786e78d131aSEugene Zelenko 
787dc707122SEaswaran Raman   // Read the records in the coverage data section.
788dc707122SEaswaran Raman   auto CovHeader =
789dd1ea9deSVedant Kumar       reinterpret_cast<const CovMapHeader *>(CovMap.data());
790dc707122SEaswaran Raman   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
791e78d131aSEugene Zelenko   if (Version > CovMapVersion::CurrentVersion)
7929152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
7939152fd17SVedant Kumar   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
794dc707122SEaswaran Raman       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
795*8280ece0SPetr Hosek                                              CompilationDir, Filenames);
7969152fd17SVedant Kumar   if (Error E = ReaderExpected.takeError())
7979152fd17SVedant Kumar     return E;
7989152fd17SVedant Kumar   auto Reader = std::move(ReaderExpected.get());
799dd1ea9deSVedant Kumar   const char *CovBuf = CovMap.data();
800dd1ea9deSVedant Kumar   const char *CovBufEnd = CovBuf + CovMap.size();
801dd1ea9deSVedant Kumar   const char *FuncRecBuf = FuncRecords.data();
802dd1ea9deSVedant Kumar   const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
803dd1ea9deSVedant Kumar   while (CovBuf < CovBufEnd) {
804dd1ea9deSVedant Kumar     // Read the current coverage header & filename data.
805dd1ea9deSVedant Kumar     //
806dd1ea9deSVedant Kumar     // Prior to Version4, this also reads all function records affixed to the
807dd1ea9deSVedant Kumar     // header.
808dd1ea9deSVedant Kumar     //
809dd1ea9deSVedant Kumar     // Return a pointer to the next coverage header.
8105fbd1a33SPetr Hosek     auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
811dd1ea9deSVedant Kumar     if (auto E = NextOrErr.takeError())
8129152fd17SVedant Kumar       return E;
813dd1ea9deSVedant Kumar     CovBuf = NextOrErr.get();
814dc707122SEaswaran Raman   }
815dd1ea9deSVedant Kumar   // In Version4, function records are not affixed to coverage headers. Read
816dd1ea9deSVedant Kumar   // the records from their dedicated section.
8179f2967bcSAlan Phipps   if (Version >= CovMapVersion::Version4)
818dd1ea9deSVedant Kumar     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, None, nullptr,
819dd1ea9deSVedant Kumar                                        nullptr);
8209152fd17SVedant Kumar   return Error::success();
821dc707122SEaswaran Raman }
822e78d131aSEugene Zelenko 
823dc707122SEaswaran Raman static const char *TestingFormatMagic = "llvmcovmtestdata";
824dc707122SEaswaran Raman 
825901d04fcSVedant Kumar Expected<std::unique_ptr<BinaryCoverageReader>>
826901d04fcSVedant Kumar BinaryCoverageReader::createCoverageReaderFromBuffer(
827*8280ece0SPetr Hosek     StringRef Coverage, std::string &&FuncRecords,
828*8280ece0SPetr Hosek     InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
829*8280ece0SPetr Hosek     support::endianness Endian, StringRef CompilationDir) {
83080cd518bSVedant Kumar   std::unique_ptr<BinaryCoverageReader> Reader(
83180cd518bSVedant Kumar       new BinaryCoverageReader(std::move(FuncRecords)));
832901d04fcSVedant Kumar   Reader->ProfileNames = std::move(ProfileNames);
83380cd518bSVedant Kumar   StringRef FuncRecordsRef = Reader->FuncRecords;
834901d04fcSVedant Kumar   if (BytesInAddress == 4 && Endian == support::endianness::little) {
835901d04fcSVedant Kumar     if (Error E =
836901d04fcSVedant Kumar             readCoverageMappingData<uint32_t, support::endianness::little>(
83780cd518bSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecordsRef,
838*8280ece0SPetr Hosek                 Reader->MappingRecords, CompilationDir, Reader->Filenames))
839c55cf4afSBill Wendling       return std::move(E);
840901d04fcSVedant Kumar   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
841901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
84280cd518bSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecordsRef,
843*8280ece0SPetr Hosek             Reader->MappingRecords, CompilationDir, Reader->Filenames))
844c55cf4afSBill Wendling       return std::move(E);
845901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
846901d04fcSVedant Kumar     if (Error E =
847901d04fcSVedant Kumar             readCoverageMappingData<uint64_t, support::endianness::little>(
84880cd518bSVedant Kumar                 Reader->ProfileNames, Coverage, FuncRecordsRef,
849*8280ece0SPetr Hosek                 Reader->MappingRecords, CompilationDir, Reader->Filenames))
850c55cf4afSBill Wendling       return std::move(E);
851901d04fcSVedant Kumar   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
852901d04fcSVedant Kumar     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
85380cd518bSVedant Kumar             Reader->ProfileNames, Coverage, FuncRecordsRef,
854*8280ece0SPetr Hosek             Reader->MappingRecords, CompilationDir, Reader->Filenames))
855c55cf4afSBill Wendling       return std::move(E);
856901d04fcSVedant Kumar   } else
857901d04fcSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
858c55cf4afSBill Wendling   return std::move(Reader);
859901d04fcSVedant Kumar }
860901d04fcSVedant Kumar 
861901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
862*8280ece0SPetr Hosek loadTestingFormat(StringRef Data, StringRef CompilationDir) {
863901d04fcSVedant Kumar   uint8_t BytesInAddress = 8;
864901d04fcSVedant Kumar   support::endianness Endian = support::endianness::little;
865dc707122SEaswaran Raman 
866dc707122SEaswaran Raman   Data = Data.substr(StringRef(TestingFormatMagic).size());
86772208a82SEugene Zelenko   if (Data.empty())
8689152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
869dc707122SEaswaran Raman   unsigned N = 0;
8706a0746a9SFangrui Song   uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
871dc707122SEaswaran Raman   if (N > Data.size())
8729152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
873dc707122SEaswaran Raman   Data = Data.substr(N);
87472208a82SEugene Zelenko   if (Data.empty())
8759152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::truncated);
876dc707122SEaswaran Raman   N = 0;
8776a0746a9SFangrui Song   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
878dc707122SEaswaran Raman   if (N > Data.size())
8799152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
880dc707122SEaswaran Raman   Data = Data.substr(N);
881dc707122SEaswaran Raman   if (Data.size() < ProfileNamesSize)
8829152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
883901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
8849152fd17SVedant Kumar   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
885c55cf4afSBill Wendling     return std::move(E);
886489a3531SPetr Hosek   Data = Data.substr(ProfileNamesSize);
887eb103073SIgor Kudrin   // Skip the padding bytes because coverage map data has an alignment of 8.
888489a3531SPetr Hosek   size_t Pad = offsetToAlignedAddr(Data.data(), Align(8));
889489a3531SPetr Hosek   if (Data.size() < Pad)
890489a3531SPetr Hosek     return make_error<CoverageMapError>(coveragemap_error::malformed);
891489a3531SPetr Hosek   Data = Data.substr(Pad);
892489a3531SPetr Hosek   if (Data.size() < sizeof(CovMapHeader))
893489a3531SPetr Hosek     return make_error<CoverageMapError>(coveragemap_error::malformed);
894489a3531SPetr Hosek   auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
895489a3531SPetr Hosek       Data.substr(0, sizeof(CovMapHeader)).data());
896489a3531SPetr Hosek   CovMapVersion Version =
897489a3531SPetr Hosek       (CovMapVersion)CovHeader->getVersion<support::endianness::little>();
898489a3531SPetr Hosek   StringRef CoverageMapping, CoverageRecords;
899489a3531SPetr Hosek   if (Version < CovMapVersion::Version4) {
900489a3531SPetr Hosek     CoverageMapping = Data;
90172208a82SEugene Zelenko     if (CoverageMapping.empty())
9029152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::truncated);
903489a3531SPetr Hosek   } else {
904489a3531SPetr Hosek     uint32_t FilenamesSize =
905489a3531SPetr Hosek         CovHeader->getFilenamesSize<support::endianness::little>();
906489a3531SPetr Hosek     uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
907489a3531SPetr Hosek     CoverageMapping = Data.substr(0, CoverageMappingSize);
908489a3531SPetr Hosek     if (CoverageMapping.empty())
909489a3531SPetr Hosek       return make_error<CoverageMapError>(coveragemap_error::truncated);
910489a3531SPetr Hosek     Data = Data.substr(CoverageMappingSize);
911489a3531SPetr Hosek     // Skip the padding bytes because coverage records data has an alignment
912489a3531SPetr Hosek     // of 8.
913489a3531SPetr Hosek     Pad = offsetToAlignedAddr(Data.data(), Align(8));
914489a3531SPetr Hosek     if (Data.size() < Pad)
9159152fd17SVedant Kumar       return make_error<CoverageMapError>(coveragemap_error::malformed);
916489a3531SPetr Hosek     CoverageRecords = Data.substr(Pad);
917489a3531SPetr Hosek     if (CoverageRecords.empty())
918489a3531SPetr Hosek       return make_error<CoverageMapError>(coveragemap_error::truncated);
919489a3531SPetr Hosek   }
920901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
921489a3531SPetr Hosek       CoverageMapping, CoverageRecords.str(), std::move(ProfileNames),
922*8280ece0SPetr Hosek       BytesInAddress, Endian, CompilationDir);
923dc707122SEaswaran Raman }
924dc707122SEaswaran Raman 
92580cd518bSVedant Kumar /// Find all sections that match \p Name. There may be more than one if comdats
92680cd518bSVedant Kumar /// are in use, e.g. for the __llvm_covfun section on ELF.
92780cd518bSVedant Kumar static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
92880cd518bSVedant Kumar                                                         StringRef Name) {
9298b6af001SReid Kleckner   // On COFF, the object file section name may end in "$M". This tells the
9308b6af001SReid Kleckner   // linker to sort these sections between "$A" and "$Z". The linker removes the
9318b6af001SReid Kleckner   // dollar and everything after it in the final binary. Do the same to match.
9328b6af001SReid Kleckner   bool IsCOFF = isa<COFFObjectFile>(OF);
9338b6af001SReid Kleckner   auto stripSuffix = [IsCOFF](StringRef N) {
9348b6af001SReid Kleckner     return IsCOFF ? N.split('$').first : N;
9358b6af001SReid Kleckner   };
9368b6af001SReid Kleckner   Name = stripSuffix(Name);
9378b6af001SReid Kleckner 
93880cd518bSVedant Kumar   std::vector<SectionRef> Sections;
939dc707122SEaswaran Raman   for (const auto &Section : OF.sections()) {
940bcc00e1aSGeorge Rimar     Expected<StringRef> NameOrErr = Section.getName();
941bcc00e1aSGeorge Rimar     if (!NameOrErr)
942bcc00e1aSGeorge Rimar       return NameOrErr.takeError();
943bcc00e1aSGeorge Rimar     if (stripSuffix(*NameOrErr) == Name)
94480cd518bSVedant Kumar       Sections.push_back(Section);
945dc707122SEaswaran Raman   }
94680cd518bSVedant Kumar   if (Sections.empty())
9479152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
94880cd518bSVedant Kumar   return Sections;
949dc707122SEaswaran Raman }
950dc707122SEaswaran Raman 
951901d04fcSVedant Kumar static Expected<std::unique_ptr<BinaryCoverageReader>>
952*8280ece0SPetr Hosek loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
953*8280ece0SPetr Hosek                  StringRef CompilationDir = "") {
954dc707122SEaswaran Raman   std::unique_ptr<ObjectFile> OF;
955e78d131aSEugene Zelenko   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
956dc707122SEaswaran Raman     // If we have a universal binary, try to look up the object for the
957dc707122SEaswaran Raman     // appropriate architecture.
9584fd11c1eSAlexander Shaposhnikov     auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
9599acb1099SKevin Enderby     if (!ObjectFileOrErr)
9609acb1099SKevin Enderby       return ObjectFileOrErr.takeError();
961dc707122SEaswaran Raman     OF = std::move(ObjectFileOrErr.get());
962e78d131aSEugene Zelenko   } else if (isa<ObjectFile>(Bin.get())) {
963dc707122SEaswaran Raman     // For any other object file, upcast and take ownership.
964e78d131aSEugene Zelenko     OF.reset(cast<ObjectFile>(Bin.release()));
965dc707122SEaswaran Raman     // If we've asked for a particular arch, make sure they match.
966dc707122SEaswaran Raman     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
9679152fd17SVedant Kumar       return errorCodeToError(object_error::arch_not_found);
968dc707122SEaswaran Raman   } else
969dc707122SEaswaran Raman     // We can only handle object files.
9709152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
971dc707122SEaswaran Raman 
972dc707122SEaswaran Raman   // The coverage uses native pointer sizes for the object it's written in.
973901d04fcSVedant Kumar   uint8_t BytesInAddress = OF->getBytesInAddress();
974901d04fcSVedant Kumar   support::endianness Endian = OF->isLittleEndian()
975901d04fcSVedant Kumar                                    ? support::endianness::little
976dc707122SEaswaran Raman                                    : support::endianness::big;
977dc707122SEaswaran Raman 
978dc707122SEaswaran Raman   // Look for the sections that we are interested in.
9791a6a2b64SVedant Kumar   auto ObjFormat = OF->getTripleObjectFormat();
9804a5ddf80SXinliang David Li   auto NamesSection =
98180cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
9821a6a2b64SVedant Kumar                                                  /*AddSegmentInfo=*/false));
9839152fd17SVedant Kumar   if (auto E = NamesSection.takeError())
984c55cf4afSBill Wendling     return std::move(E);
9854a5ddf80SXinliang David Li   auto CoverageSection =
98680cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
9871a6a2b64SVedant Kumar                                                   /*AddSegmentInfo=*/false));
9889152fd17SVedant Kumar   if (auto E = CoverageSection.takeError())
989c55cf4afSBill Wendling     return std::move(E);
99080cd518bSVedant Kumar   std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
99180cd518bSVedant Kumar   if (CoverageSectionRefs.size() != 1)
99280cd518bSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
99380cd518bSVedant Kumar   auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
994901d04fcSVedant Kumar   if (!CoverageMappingOrErr)
995901d04fcSVedant Kumar     return CoverageMappingOrErr.takeError();
996dd1ea9deSVedant Kumar   StringRef CoverageMapping = CoverageMappingOrErr.get();
997e183340cSFangrui Song 
998901d04fcSVedant Kumar   InstrProfSymtab ProfileNames;
99980cd518bSVedant Kumar   std::vector<SectionRef> NamesSectionRefs = *NamesSection;
100080cd518bSVedant Kumar   if (NamesSectionRefs.size() != 1)
100180cd518bSVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::malformed);
100280cd518bSVedant Kumar   if (Error E = ProfileNames.create(NamesSectionRefs.back()))
1003c55cf4afSBill Wendling     return std::move(E);
1004dc707122SEaswaran Raman 
1005dd1ea9deSVedant Kumar   // Look for the coverage records section (Version4 only).
100680cd518bSVedant Kumar   std::string FuncRecords;
100780cd518bSVedant Kumar   auto CoverageRecordsSections =
100880cd518bSVedant Kumar       lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
1009dd1ea9deSVedant Kumar                                                   /*AddSegmentInfo=*/false));
101080cd518bSVedant Kumar   if (auto E = CoverageRecordsSections.takeError())
1011dd1ea9deSVedant Kumar     consumeError(std::move(E));
1012dd1ea9deSVedant Kumar   else {
101380cd518bSVedant Kumar     for (SectionRef Section : *CoverageRecordsSections) {
101480cd518bSVedant Kumar       auto CoverageRecordsOrErr = Section.getContents();
1015dd1ea9deSVedant Kumar       if (!CoverageRecordsOrErr)
1016dd1ea9deSVedant Kumar         return CoverageRecordsOrErr.takeError();
101780cd518bSVedant Kumar       FuncRecords += CoverageRecordsOrErr.get();
101880cd518bSVedant Kumar       while (FuncRecords.size() % 8 != 0)
101980cd518bSVedant Kumar         FuncRecords += '\0';
102080cd518bSVedant Kumar     }
1021dd1ea9deSVedant Kumar   }
1022dd1ea9deSVedant Kumar 
1023901d04fcSVedant Kumar   return BinaryCoverageReader::createCoverageReaderFromBuffer(
102480cd518bSVedant Kumar       CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
1025*8280ece0SPetr Hosek       BytesInAddress, Endian, CompilationDir);
1026dc707122SEaswaran Raman }
1027dc707122SEaswaran Raman 
10287fafaa07SVedant Kumar /// Determine whether \p Arch is invalid or empty, given \p Bin.
10297fafaa07SVedant Kumar static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
10307fafaa07SVedant Kumar   // If we have a universal binary and Arch doesn't identify any of its slices,
10317fafaa07SVedant Kumar   // it's user error.
10327fafaa07SVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
10337fafaa07SVedant Kumar     for (auto &ObjForArch : Universal->objects())
10347fafaa07SVedant Kumar       if (Arch == ObjForArch.getArchFlagName())
10357fafaa07SVedant Kumar         return false;
10367fafaa07SVedant Kumar     return true;
10377fafaa07SVedant Kumar   }
10387fafaa07SVedant Kumar   return false;
10397fafaa07SVedant Kumar }
10407fafaa07SVedant Kumar 
1041901d04fcSVedant Kumar Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
1042901d04fcSVedant Kumar BinaryCoverageReader::create(
1043901d04fcSVedant Kumar     MemoryBufferRef ObjectBuffer, StringRef Arch,
1044*8280ece0SPetr Hosek     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
1045*8280ece0SPetr Hosek     StringRef CompilationDir) {
1046901d04fcSVedant Kumar   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
1047dc707122SEaswaran Raman 
1048901d04fcSVedant Kumar   if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
1049dc707122SEaswaran Raman     // This is a special format used for testing.
1050*8280ece0SPetr Hosek     auto ReaderOrErr =
1051*8280ece0SPetr Hosek         loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
1052901d04fcSVedant Kumar     if (!ReaderOrErr)
1053901d04fcSVedant Kumar       return ReaderOrErr.takeError();
1054901d04fcSVedant Kumar     Readers.push_back(std::move(ReaderOrErr.get()));
1055c55cf4afSBill Wendling     return std::move(Readers);
1056901d04fcSVedant Kumar   }
1057dc707122SEaswaran Raman 
1058901d04fcSVedant Kumar   auto BinOrErr = createBinary(ObjectBuffer);
1059901d04fcSVedant Kumar   if (!BinOrErr)
1060901d04fcSVedant Kumar     return BinOrErr.takeError();
1061901d04fcSVedant Kumar   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
1062901d04fcSVedant Kumar 
10637fafaa07SVedant Kumar   if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
10647fafaa07SVedant Kumar     return make_error<CoverageMapError>(
10657fafaa07SVedant Kumar         coveragemap_error::invalid_or_missing_arch_specifier);
10667fafaa07SVedant Kumar 
1067901d04fcSVedant Kumar   // MachO universal binaries which contain archives need to be treated as
1068901d04fcSVedant Kumar   // archives, not as regular binaries.
1069901d04fcSVedant Kumar   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
1070901d04fcSVedant Kumar     for (auto &ObjForArch : Universal->objects()) {
1071901d04fcSVedant Kumar       // Skip slices within the universal binary which target the wrong arch.
1072901d04fcSVedant Kumar       std::string ObjArch = ObjForArch.getArchFlagName();
1073901d04fcSVedant Kumar       if (Arch != ObjArch)
1074901d04fcSVedant Kumar         continue;
1075901d04fcSVedant Kumar 
1076901d04fcSVedant Kumar       auto ArchiveOrErr = ObjForArch.getAsArchive();
1077901d04fcSVedant Kumar       if (!ArchiveOrErr) {
1078901d04fcSVedant Kumar         // If this is not an archive, try treating it as a regular object.
1079901d04fcSVedant Kumar         consumeError(ArchiveOrErr.takeError());
1080901d04fcSVedant Kumar         break;
1081901d04fcSVedant Kumar       }
1082901d04fcSVedant Kumar 
1083901d04fcSVedant Kumar       return BinaryCoverageReader::create(
1084*8280ece0SPetr Hosek           ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
1085*8280ece0SPetr Hosek           CompilationDir);
1086901d04fcSVedant Kumar     }
1087901d04fcSVedant Kumar   }
1088901d04fcSVedant Kumar 
1089901d04fcSVedant Kumar   // Load coverage out of archive members.
1090901d04fcSVedant Kumar   if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
1091901d04fcSVedant Kumar     Error Err = Error::success();
1092901d04fcSVedant Kumar     for (auto &Child : Ar->children(Err)) {
1093901d04fcSVedant Kumar       Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
1094901d04fcSVedant Kumar       if (!ChildBufOrErr)
1095901d04fcSVedant Kumar         return ChildBufOrErr.takeError();
1096901d04fcSVedant Kumar 
1097901d04fcSVedant Kumar       auto ChildReadersOrErr = BinaryCoverageReader::create(
1098*8280ece0SPetr Hosek           ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir);
1099901d04fcSVedant Kumar       if (!ChildReadersOrErr)
1100901d04fcSVedant Kumar         return ChildReadersOrErr.takeError();
1101901d04fcSVedant Kumar       for (auto &Reader : ChildReadersOrErr.get())
1102901d04fcSVedant Kumar         Readers.push_back(std::move(Reader));
1103901d04fcSVedant Kumar     }
1104901d04fcSVedant Kumar     if (Err)
1105c55cf4afSBill Wendling       return std::move(Err);
1106901d04fcSVedant Kumar 
1107901d04fcSVedant Kumar     // Thin archives reference object files outside of the archive file, i.e.
1108901d04fcSVedant Kumar     // files which reside in memory not owned by the caller. Transfer ownership
1109901d04fcSVedant Kumar     // to the caller.
1110901d04fcSVedant Kumar     if (Ar->isThin())
1111901d04fcSVedant Kumar       for (auto &Buffer : Ar->takeThinBuffers())
1112901d04fcSVedant Kumar         ObjectFileBuffers.push_back(std::move(Buffer));
1113901d04fcSVedant Kumar 
1114c55cf4afSBill Wendling     return std::move(Readers);
1115901d04fcSVedant Kumar   }
1116901d04fcSVedant Kumar 
1117*8280ece0SPetr Hosek   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir);
1118901d04fcSVedant Kumar   if (!ReaderOrErr)
1119901d04fcSVedant Kumar     return ReaderOrErr.takeError();
1120901d04fcSVedant Kumar   Readers.push_back(std::move(ReaderOrErr.get()));
1121c55cf4afSBill Wendling   return std::move(Readers);
1122dc707122SEaswaran Raman }
1123dc707122SEaswaran Raman 
11249152fd17SVedant Kumar Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
1125dc707122SEaswaran Raman   if (CurrentRecord >= MappingRecords.size())
11269152fd17SVedant Kumar     return make_error<CoverageMapError>(coveragemap_error::eof);
1127dc707122SEaswaran Raman 
1128dc707122SEaswaran Raman   FunctionsFilenames.clear();
1129dc707122SEaswaran Raman   Expressions.clear();
1130dc707122SEaswaran Raman   MappingRegions.clear();
1131dc707122SEaswaran Raman   auto &R = MappingRecords[CurrentRecord];
11325fbd1a33SPetr Hosek   auto F = makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
11335fbd1a33SPetr Hosek   RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
11345fbd1a33SPetr Hosek                                   Expressions, MappingRegions);
1135dc707122SEaswaran Raman   if (auto Err = Reader.read())
1136dc707122SEaswaran Raman     return Err;
1137dc707122SEaswaran Raman 
1138dc707122SEaswaran Raman   Record.FunctionName = R.FunctionName;
1139dc707122SEaswaran Raman   Record.FunctionHash = R.FunctionHash;
1140dc707122SEaswaran Raman   Record.Filenames = FunctionsFilenames;
1141dc707122SEaswaran Raman   Record.Expressions = Expressions;
1142dc707122SEaswaran Raman   Record.MappingRegions = MappingRegions;
1143dc707122SEaswaran Raman 
1144dc707122SEaswaran Raman   ++CurrentRecord;
11459152fd17SVedant Kumar   return Error::success();
1146dc707122SEaswaran Raman }
1147