xref: /src/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
108bbd35aSDimitry Andric //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric //
901095a5dSDimitry Andric // This file contains support for reading coverage mapping data for
1001095a5dSDimitry Andric // instrumentation based coverage.
1101095a5dSDimitry Andric //
1201095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1301095a5dSDimitry Andric 
1401095a5dSDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
1571d5a254SDimitry Andric #include "llvm/ADT/ArrayRef.h"
1601095a5dSDimitry Andric #include "llvm/ADT/DenseMap.h"
1771d5a254SDimitry Andric #include "llvm/ADT/STLExtras.h"
1871d5a254SDimitry Andric #include "llvm/ADT/SmallVector.h"
19cfca06d7SDimitry Andric #include "llvm/ADT/Statistic.h"
2071d5a254SDimitry Andric #include "llvm/ADT/StringRef.h"
21145449b1SDimitry Andric #include "llvm/Object/Archive.h"
2271d5a254SDimitry Andric #include "llvm/Object/Binary.h"
23344a3780SDimitry Andric #include "llvm/Object/COFF.h"
2471d5a254SDimitry Andric #include "llvm/Object/Error.h"
2501095a5dSDimitry Andric #include "llvm/Object/MachOUniversal.h"
2601095a5dSDimitry Andric #include "llvm/Object/ObjectFile.h"
2771d5a254SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
2871d5a254SDimitry Andric #include "llvm/Support/Casting.h"
29cfca06d7SDimitry Andric #include "llvm/Support/Compression.h"
3001095a5dSDimitry Andric #include "llvm/Support/Debug.h"
3101095a5dSDimitry Andric #include "llvm/Support/Endian.h"
3271d5a254SDimitry Andric #include "llvm/Support/Error.h"
3371d5a254SDimitry Andric #include "llvm/Support/ErrorHandling.h"
3401095a5dSDimitry Andric #include "llvm/Support/LEB128.h"
3501095a5dSDimitry Andric #include "llvm/Support/MathExtras.h"
36344a3780SDimitry Andric #include "llvm/Support/Path.h"
3701095a5dSDimitry Andric #include "llvm/Support/raw_ostream.h"
387fa27ce4SDimitry Andric #include "llvm/TargetParser/Triple.h"
3971d5a254SDimitry Andric #include <vector>
4001095a5dSDimitry Andric 
4101095a5dSDimitry Andric using namespace llvm;
4201095a5dSDimitry Andric using namespace coverage;
4301095a5dSDimitry Andric using namespace object;
4401095a5dSDimitry Andric 
4501095a5dSDimitry Andric #define DEBUG_TYPE "coverage-mapping"
4601095a5dSDimitry Andric 
47cfca06d7SDimitry Andric STATISTIC(CovMapNumRecords, "The # of coverage function records");
48cfca06d7SDimitry Andric STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");
49cfca06d7SDimitry Andric 
increment()5001095a5dSDimitry Andric void CoverageMappingIterator::increment() {
51044eb2f6SDimitry Andric   if (ReadErr != coveragemap_error::success)
52044eb2f6SDimitry Andric     return;
53044eb2f6SDimitry Andric 
5401095a5dSDimitry Andric   // Check if all the records were read or if an error occurred while reading
5501095a5dSDimitry Andric   // the next record.
56044eb2f6SDimitry Andric   if (auto E = Reader->readNextRecord(Record))
5701095a5dSDimitry Andric     handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
5801095a5dSDimitry Andric       if (CME.get() == coveragemap_error::eof)
5901095a5dSDimitry Andric         *this = CoverageMappingIterator();
6001095a5dSDimitry Andric       else
61044eb2f6SDimitry Andric         ReadErr = CME.get();
6201095a5dSDimitry Andric     });
6301095a5dSDimitry Andric }
6401095a5dSDimitry Andric 
readULEB128(uint64_t & Result)6501095a5dSDimitry Andric Error RawCoverageReader::readULEB128(uint64_t &Result) {
6608bbd35aSDimitry Andric   if (Data.empty())
6701095a5dSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
6801095a5dSDimitry Andric   unsigned N = 0;
69e6d15924SDimitry Andric   Result = decodeULEB128(Data.bytes_begin(), &N);
7001095a5dSDimitry Andric   if (N > Data.size())
71b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
72b1c73532SDimitry Andric                                         "the size of ULEB128 is too big");
7301095a5dSDimitry Andric   Data = Data.substr(N);
7401095a5dSDimitry Andric   return Error::success();
7501095a5dSDimitry Andric }
7601095a5dSDimitry Andric 
readIntMax(uint64_t & Result,uint64_t MaxPlus1)7701095a5dSDimitry Andric Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
7801095a5dSDimitry Andric   if (auto Err = readULEB128(Result))
7901095a5dSDimitry Andric     return Err;
8001095a5dSDimitry Andric   if (Result >= MaxPlus1)
81b1c73532SDimitry Andric     return make_error<CoverageMapError>(
82b1c73532SDimitry Andric         coveragemap_error::malformed,
83b1c73532SDimitry Andric         "the value of ULEB128 is greater than or equal to MaxPlus1");
8401095a5dSDimitry Andric   return Error::success();
8501095a5dSDimitry Andric }
8601095a5dSDimitry Andric 
readSize(uint64_t & Result)8701095a5dSDimitry Andric Error RawCoverageReader::readSize(uint64_t &Result) {
8801095a5dSDimitry Andric   if (auto Err = readULEB128(Result))
8901095a5dSDimitry Andric     return Err;
9001095a5dSDimitry Andric   if (Result > Data.size())
91b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
92b1c73532SDimitry Andric                                         "the value of ULEB128 is too big");
9301095a5dSDimitry Andric   return Error::success();
9401095a5dSDimitry Andric }
9501095a5dSDimitry Andric 
readString(StringRef & Result)9601095a5dSDimitry Andric Error RawCoverageReader::readString(StringRef &Result) {
9701095a5dSDimitry Andric   uint64_t Length;
9801095a5dSDimitry Andric   if (auto Err = readSize(Length))
9901095a5dSDimitry Andric     return Err;
10001095a5dSDimitry Andric   Result = Data.substr(0, Length);
10101095a5dSDimitry Andric   Data = Data.substr(Length);
10201095a5dSDimitry Andric   return Error::success();
10301095a5dSDimitry Andric }
10401095a5dSDimitry Andric 
read(CovMapVersion Version)105344a3780SDimitry Andric Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
10601095a5dSDimitry Andric   uint64_t NumFilenames;
10701095a5dSDimitry Andric   if (auto Err = readSize(NumFilenames))
10801095a5dSDimitry Andric     return Err;
109cfca06d7SDimitry Andric   if (!NumFilenames)
110b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
111b1c73532SDimitry Andric                                         "number of filenames is zero");
112cfca06d7SDimitry Andric 
113cfca06d7SDimitry Andric   if (Version < CovMapVersion::Version4)
114344a3780SDimitry Andric     return readUncompressed(Version, NumFilenames);
115cfca06d7SDimitry Andric 
116cfca06d7SDimitry Andric   // The uncompressed length may exceed the size of the encoded filenames.
117cfca06d7SDimitry Andric   // Skip size validation.
118cfca06d7SDimitry Andric   uint64_t UncompressedLen;
119cfca06d7SDimitry Andric   if (auto Err = readULEB128(UncompressedLen))
120cfca06d7SDimitry Andric     return Err;
121cfca06d7SDimitry Andric 
122cfca06d7SDimitry Andric   uint64_t CompressedLen;
123cfca06d7SDimitry Andric   if (auto Err = readSize(CompressedLen))
124cfca06d7SDimitry Andric     return Err;
125cfca06d7SDimitry Andric 
126cfca06d7SDimitry Andric   if (CompressedLen > 0) {
1271f917f69SDimitry Andric     if (!compression::zlib::isAvailable())
128cfca06d7SDimitry Andric       return make_error<CoverageMapError>(
129cfca06d7SDimitry Andric           coveragemap_error::decompression_failed);
130cfca06d7SDimitry Andric 
131344a3780SDimitry Andric     // Allocate memory for the decompressed filenames.
1321f917f69SDimitry Andric     SmallVector<uint8_t, 0> StorageBuf;
133cfca06d7SDimitry Andric 
134cfca06d7SDimitry Andric     // Read compressed filenames.
135cfca06d7SDimitry Andric     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
136cfca06d7SDimitry Andric     Data = Data.substr(CompressedLen);
137e3b55780SDimitry Andric     auto Err = compression::zlib::decompress(
1381f917f69SDimitry Andric         arrayRefFromStringRef(CompressedFilenames), StorageBuf,
1391f917f69SDimitry Andric         UncompressedLen);
140cfca06d7SDimitry Andric     if (Err) {
141cfca06d7SDimitry Andric       consumeError(std::move(Err));
142cfca06d7SDimitry Andric       return make_error<CoverageMapError>(
143cfca06d7SDimitry Andric           coveragemap_error::decompression_failed);
144cfca06d7SDimitry Andric     }
145cfca06d7SDimitry Andric 
1461f917f69SDimitry Andric     RawCoverageFilenamesReader Delegate(toStringRef(StorageBuf), Filenames,
147344a3780SDimitry Andric                                         CompilationDir);
148344a3780SDimitry Andric     return Delegate.readUncompressed(Version, NumFilenames);
149cfca06d7SDimitry Andric   }
150cfca06d7SDimitry Andric 
151344a3780SDimitry Andric   return readUncompressed(Version, NumFilenames);
152cfca06d7SDimitry Andric }
153cfca06d7SDimitry Andric 
readUncompressed(CovMapVersion Version,uint64_t NumFilenames)154344a3780SDimitry Andric Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
155344a3780SDimitry Andric                                                    uint64_t NumFilenames) {
156cfca06d7SDimitry Andric   // Read uncompressed filenames.
157344a3780SDimitry Andric   if (Version < CovMapVersion::Version6) {
15801095a5dSDimitry Andric     for (size_t I = 0; I < NumFilenames; ++I) {
15901095a5dSDimitry Andric       StringRef Filename;
16001095a5dSDimitry Andric       if (auto Err = readString(Filename))
16101095a5dSDimitry Andric         return Err;
162344a3780SDimitry Andric       Filenames.push_back(Filename.str());
163344a3780SDimitry Andric     }
164344a3780SDimitry Andric   } else {
165344a3780SDimitry Andric     StringRef CWD;
166344a3780SDimitry Andric     if (auto Err = readString(CWD))
167344a3780SDimitry Andric       return Err;
168344a3780SDimitry Andric     Filenames.push_back(CWD.str());
169344a3780SDimitry Andric 
170344a3780SDimitry Andric     for (size_t I = 1; I < NumFilenames; ++I) {
171344a3780SDimitry Andric       StringRef Filename;
172344a3780SDimitry Andric       if (auto Err = readString(Filename))
173344a3780SDimitry Andric         return Err;
174344a3780SDimitry Andric       if (sys::path::is_absolute(Filename)) {
175344a3780SDimitry Andric         Filenames.push_back(Filename.str());
176344a3780SDimitry Andric       } else {
177344a3780SDimitry Andric         SmallString<256> P;
178344a3780SDimitry Andric         if (!CompilationDir.empty())
179344a3780SDimitry Andric           P.assign(CompilationDir);
180344a3780SDimitry Andric         else
181344a3780SDimitry Andric           P.assign(CWD);
182344a3780SDimitry Andric         llvm::sys::path::append(P, Filename);
183145449b1SDimitry Andric         sys::path::remove_dots(P, /*remove_dot_dot=*/true);
184145449b1SDimitry Andric         Filenames.push_back(static_cast<std::string>(P.str()));
185344a3780SDimitry Andric       }
186344a3780SDimitry Andric     }
18701095a5dSDimitry Andric   }
18801095a5dSDimitry Andric   return Error::success();
18901095a5dSDimitry Andric }
19001095a5dSDimitry Andric 
decodeCounter(unsigned Value,Counter & C)19101095a5dSDimitry Andric Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
19201095a5dSDimitry Andric   auto Tag = Value & Counter::EncodingTagMask;
19301095a5dSDimitry Andric   switch (Tag) {
19401095a5dSDimitry Andric   case Counter::Zero:
19501095a5dSDimitry Andric     C = Counter::getZero();
19601095a5dSDimitry Andric     return Error::success();
19701095a5dSDimitry Andric   case Counter::CounterValueReference:
19801095a5dSDimitry Andric     C = Counter::getCounter(Value >> Counter::EncodingTagBits);
19901095a5dSDimitry Andric     return Error::success();
20001095a5dSDimitry Andric   default:
20101095a5dSDimitry Andric     break;
20201095a5dSDimitry Andric   }
20301095a5dSDimitry Andric   Tag -= Counter::Expression;
20401095a5dSDimitry Andric   switch (Tag) {
20501095a5dSDimitry Andric   case CounterExpression::Subtract:
20601095a5dSDimitry Andric   case CounterExpression::Add: {
20701095a5dSDimitry Andric     auto ID = Value >> Counter::EncodingTagBits;
20801095a5dSDimitry Andric     if (ID >= Expressions.size())
209b1c73532SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed,
210b1c73532SDimitry Andric                                           "counter expression is invalid");
21101095a5dSDimitry Andric     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
21201095a5dSDimitry Andric     C = Counter::getExpression(ID);
21301095a5dSDimitry Andric     break;
21401095a5dSDimitry Andric   }
21501095a5dSDimitry Andric   default:
216b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
217b1c73532SDimitry Andric                                         "counter expression kind is invalid");
21801095a5dSDimitry Andric   }
21901095a5dSDimitry Andric   return Error::success();
22001095a5dSDimitry Andric }
22101095a5dSDimitry Andric 
readCounter(Counter & C)22201095a5dSDimitry Andric Error RawCoverageMappingReader::readCounter(Counter &C) {
22301095a5dSDimitry Andric   uint64_t EncodedCounter;
22401095a5dSDimitry Andric   if (auto Err =
22501095a5dSDimitry Andric           readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
22601095a5dSDimitry Andric     return Err;
22701095a5dSDimitry Andric   if (auto Err = decodeCounter(EncodedCounter, C))
22801095a5dSDimitry Andric     return Err;
22901095a5dSDimitry Andric   return Error::success();
23001095a5dSDimitry Andric }
23101095a5dSDimitry Andric 
23201095a5dSDimitry Andric static const unsigned EncodingExpansionRegionBit = 1
23301095a5dSDimitry Andric                                                    << Counter::EncodingTagBits;
23401095a5dSDimitry Andric 
235eb11fae6SDimitry Andric /// Read the sub-array of regions for the given inferred file id.
23601095a5dSDimitry Andric /// \param NumFileIDs the number of file ids that are defined for this
23701095a5dSDimitry Andric /// function.
readMappingRegionsSubArray(std::vector<CounterMappingRegion> & MappingRegions,unsigned InferredFileID,size_t NumFileIDs)23801095a5dSDimitry Andric Error RawCoverageMappingReader::readMappingRegionsSubArray(
23901095a5dSDimitry Andric     std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
24001095a5dSDimitry Andric     size_t NumFileIDs) {
24101095a5dSDimitry Andric   uint64_t NumRegions;
24201095a5dSDimitry Andric   if (auto Err = readSize(NumRegions))
24301095a5dSDimitry Andric     return Err;
24401095a5dSDimitry Andric   unsigned LineStart = 0;
24501095a5dSDimitry Andric   for (size_t I = 0; I < NumRegions; ++I) {
246b60736ecSDimitry Andric     Counter C, C2;
247ac9a064cSDimitry Andric     uint64_t BIDX, NC;
248ac9a064cSDimitry Andric     // They are stored as internal values plus 1 (min is -1)
249ac9a064cSDimitry Andric     uint64_t ID1, TID1, FID1;
250ac9a064cSDimitry Andric     mcdc::Parameters Params;
25101095a5dSDimitry Andric     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
25201095a5dSDimitry Andric 
25301095a5dSDimitry Andric     // Read the combined counter + region kind.
25401095a5dSDimitry Andric     uint64_t EncodedCounterAndRegion;
25501095a5dSDimitry Andric     if (auto Err = readIntMax(EncodedCounterAndRegion,
25601095a5dSDimitry Andric                               std::numeric_limits<unsigned>::max()))
25701095a5dSDimitry Andric       return Err;
25801095a5dSDimitry Andric     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
25901095a5dSDimitry Andric     uint64_t ExpandedFileID = 0;
260b60736ecSDimitry Andric 
261b60736ecSDimitry Andric     // If Tag does not represent a ZeroCounter, then it is understood to refer
262b60736ecSDimitry Andric     // to a counter or counter expression with region kind assumed to be
263b60736ecSDimitry Andric     // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
264b60736ecSDimitry Andric     // referenced counter or counter expression (and nothing else).
265b60736ecSDimitry Andric     //
266b60736ecSDimitry Andric     // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
267b60736ecSDimitry Andric     // then EncodedCounterAndRegion is interpreted to represent an
268b60736ecSDimitry Andric     // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
269b60736ecSDimitry Andric     // interpreted to refer to a specific region kind, after which additional
270b60736ecSDimitry Andric     // fields may be read (e.g. BranchRegions have two encoded counters that
271b60736ecSDimitry Andric     // follow an encoded region kind value).
27201095a5dSDimitry Andric     if (Tag != Counter::Zero) {
27301095a5dSDimitry Andric       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
27401095a5dSDimitry Andric         return Err;
27501095a5dSDimitry Andric     } else {
27601095a5dSDimitry Andric       // Is it an expansion region?
27701095a5dSDimitry Andric       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
27801095a5dSDimitry Andric         Kind = CounterMappingRegion::ExpansionRegion;
27901095a5dSDimitry Andric         ExpandedFileID = EncodedCounterAndRegion >>
28001095a5dSDimitry Andric                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
28101095a5dSDimitry Andric         if (ExpandedFileID >= NumFileIDs)
282b1c73532SDimitry Andric           return make_error<CoverageMapError>(coveragemap_error::malformed,
283b1c73532SDimitry Andric                                               "ExpandedFileID is invalid");
28401095a5dSDimitry Andric       } else {
28501095a5dSDimitry Andric         switch (EncodedCounterAndRegion >>
28601095a5dSDimitry Andric                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
28701095a5dSDimitry Andric         case CounterMappingRegion::CodeRegion:
28801095a5dSDimitry Andric           // Don't do anything when we have a code region with a zero counter.
28901095a5dSDimitry Andric           break;
29001095a5dSDimitry Andric         case CounterMappingRegion::SkippedRegion:
29101095a5dSDimitry Andric           Kind = CounterMappingRegion::SkippedRegion;
29201095a5dSDimitry Andric           break;
293b60736ecSDimitry Andric         case CounterMappingRegion::BranchRegion:
294b60736ecSDimitry Andric           // For a Branch Region, read two successive counters.
295b60736ecSDimitry Andric           Kind = CounterMappingRegion::BranchRegion;
296b60736ecSDimitry Andric           if (auto Err = readCounter(C))
297b60736ecSDimitry Andric             return Err;
298b60736ecSDimitry Andric           if (auto Err = readCounter(C2))
299b60736ecSDimitry Andric             return Err;
300b60736ecSDimitry Andric           break;
301312c0ed1SDimitry Andric         case CounterMappingRegion::MCDCBranchRegion:
302312c0ed1SDimitry Andric           // For a MCDC Branch Region, read two successive counters and 3 IDs.
303312c0ed1SDimitry Andric           Kind = CounterMappingRegion::MCDCBranchRegion;
304312c0ed1SDimitry Andric           if (auto Err = readCounter(C))
305312c0ed1SDimitry Andric             return Err;
306312c0ed1SDimitry Andric           if (auto Err = readCounter(C2))
307312c0ed1SDimitry Andric             return Err;
308ac9a064cSDimitry Andric           if (auto Err = readIntMax(ID1, std::numeric_limits<int16_t>::max()))
309312c0ed1SDimitry Andric             return Err;
310ac9a064cSDimitry Andric           if (auto Err = readIntMax(TID1, std::numeric_limits<int16_t>::max()))
311312c0ed1SDimitry Andric             return Err;
312ac9a064cSDimitry Andric           if (auto Err = readIntMax(FID1, std::numeric_limits<int16_t>::max()))
313312c0ed1SDimitry Andric             return Err;
314ac9a064cSDimitry Andric           if (ID1 == 0)
315ac9a064cSDimitry Andric             return make_error<CoverageMapError>(
316ac9a064cSDimitry Andric                 coveragemap_error::malformed,
317ac9a064cSDimitry Andric                 "MCDCConditionID shouldn't be zero");
318ac9a064cSDimitry Andric           Params = mcdc::BranchParameters{
319ac9a064cSDimitry Andric               static_cast<int16_t>(static_cast<int16_t>(ID1) - 1),
320ac9a064cSDimitry Andric               {static_cast<int16_t>(static_cast<int16_t>(FID1) - 1),
321ac9a064cSDimitry Andric                static_cast<int16_t>(static_cast<int16_t>(TID1) - 1)}};
322312c0ed1SDimitry Andric           break;
323312c0ed1SDimitry Andric         case CounterMappingRegion::MCDCDecisionRegion:
324312c0ed1SDimitry Andric           Kind = CounterMappingRegion::MCDCDecisionRegion;
325312c0ed1SDimitry Andric           if (auto Err = readIntMax(BIDX, std::numeric_limits<unsigned>::max()))
326312c0ed1SDimitry Andric             return Err;
327ac9a064cSDimitry Andric           if (auto Err = readIntMax(NC, std::numeric_limits<int16_t>::max()))
328312c0ed1SDimitry Andric             return Err;
329ac9a064cSDimitry Andric           Params = mcdc::DecisionParameters{static_cast<unsigned>(BIDX),
330ac9a064cSDimitry Andric                                             static_cast<uint16_t>(NC)};
331312c0ed1SDimitry Andric           break;
33201095a5dSDimitry Andric         default:
333b1c73532SDimitry Andric           return make_error<CoverageMapError>(coveragemap_error::malformed,
334b1c73532SDimitry Andric                                               "region kind is incorrect");
33501095a5dSDimitry Andric         }
33601095a5dSDimitry Andric       }
33701095a5dSDimitry Andric     }
33801095a5dSDimitry Andric 
33901095a5dSDimitry Andric     // Read the source range.
34001095a5dSDimitry Andric     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
34101095a5dSDimitry Andric     if (auto Err =
34201095a5dSDimitry Andric             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
34301095a5dSDimitry Andric       return Err;
34401095a5dSDimitry Andric     if (auto Err = readULEB128(ColumnStart))
34501095a5dSDimitry Andric       return Err;
34601095a5dSDimitry Andric     if (ColumnStart > std::numeric_limits<unsigned>::max())
347b1c73532SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed,
348b1c73532SDimitry Andric                                           "start column is too big");
34901095a5dSDimitry Andric     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
35001095a5dSDimitry Andric       return Err;
35101095a5dSDimitry Andric     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
35201095a5dSDimitry Andric       return Err;
35301095a5dSDimitry Andric     LineStart += LineStartDelta;
354044eb2f6SDimitry Andric 
355044eb2f6SDimitry Andric     // If the high bit of ColumnEnd is set, this is a gap region.
356044eb2f6SDimitry Andric     if (ColumnEnd & (1U << 31)) {
357044eb2f6SDimitry Andric       Kind = CounterMappingRegion::GapRegion;
358044eb2f6SDimitry Andric       ColumnEnd &= ~(1U << 31);
359044eb2f6SDimitry Andric     }
360044eb2f6SDimitry Andric 
36101095a5dSDimitry Andric     // Adjust the column locations for the empty regions that are supposed to
36201095a5dSDimitry Andric     // cover whole lines. Those regions should be encoded with the
36301095a5dSDimitry Andric     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
36401095a5dSDimitry Andric     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
36501095a5dSDimitry Andric     // we set the column range to (0 -> 0) to ensure that the column start and
36601095a5dSDimitry Andric     // column end take up one byte each.
36701095a5dSDimitry Andric     // The std::numeric_limits<unsigned>::max() is used to represent a column
36801095a5dSDimitry Andric     // position at the end of the line without knowing the length of that line.
36901095a5dSDimitry Andric     if (ColumnStart == 0 && ColumnEnd == 0) {
37001095a5dSDimitry Andric       ColumnStart = 1;
37101095a5dSDimitry Andric       ColumnEnd = std::numeric_limits<unsigned>::max();
37201095a5dSDimitry Andric     }
37301095a5dSDimitry Andric 
374eb11fae6SDimitry Andric     LLVM_DEBUG({
37501095a5dSDimitry Andric       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
37601095a5dSDimitry Andric              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
37701095a5dSDimitry Andric              << ColumnEnd << ", ";
37801095a5dSDimitry Andric       if (Kind == CounterMappingRegion::ExpansionRegion)
37901095a5dSDimitry Andric         dbgs() << "Expands to file " << ExpandedFileID;
38001095a5dSDimitry Andric       else
38101095a5dSDimitry Andric         CounterMappingContext(Expressions).dump(C, dbgs());
38201095a5dSDimitry Andric       dbgs() << "\n";
38301095a5dSDimitry Andric     });
38401095a5dSDimitry Andric 
385312c0ed1SDimitry Andric     auto CMR = CounterMappingRegion(
386ac9a064cSDimitry Andric         C, C2, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
387ac9a064cSDimitry Andric         LineStart + NumLines, ColumnEnd, Kind, Params);
388044eb2f6SDimitry Andric     if (CMR.startLoc() > CMR.endLoc())
389b1c73532SDimitry Andric       return make_error<CoverageMapError>(
390b1c73532SDimitry Andric           coveragemap_error::malformed,
391b1c73532SDimitry Andric           "counter mapping region locations are incorrect");
392044eb2f6SDimitry Andric     MappingRegions.push_back(CMR);
39301095a5dSDimitry Andric   }
39401095a5dSDimitry Andric   return Error::success();
39501095a5dSDimitry Andric }
39601095a5dSDimitry Andric 
read()39701095a5dSDimitry Andric Error RawCoverageMappingReader::read() {
39801095a5dSDimitry Andric   // Read the virtual file mapping.
39971d5a254SDimitry Andric   SmallVector<unsigned, 8> VirtualFileMapping;
40001095a5dSDimitry Andric   uint64_t NumFileMappings;
40101095a5dSDimitry Andric   if (auto Err = readSize(NumFileMappings))
40201095a5dSDimitry Andric     return Err;
40301095a5dSDimitry Andric   for (size_t I = 0; I < NumFileMappings; ++I) {
40401095a5dSDimitry Andric     uint64_t FilenameIndex;
40501095a5dSDimitry Andric     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
40601095a5dSDimitry Andric       return Err;
40701095a5dSDimitry Andric     VirtualFileMapping.push_back(FilenameIndex);
40801095a5dSDimitry Andric   }
40901095a5dSDimitry Andric 
41001095a5dSDimitry Andric   // Construct the files using unique filenames and virtual file mapping.
41101095a5dSDimitry Andric   for (auto I : VirtualFileMapping) {
41201095a5dSDimitry Andric     Filenames.push_back(TranslationUnitFilenames[I]);
41301095a5dSDimitry Andric   }
41401095a5dSDimitry Andric 
41501095a5dSDimitry Andric   // Read the expressions.
41601095a5dSDimitry Andric   uint64_t NumExpressions;
41701095a5dSDimitry Andric   if (auto Err = readSize(NumExpressions))
41801095a5dSDimitry Andric     return Err;
41901095a5dSDimitry Andric   // Create an array of dummy expressions that get the proper counters
42001095a5dSDimitry Andric   // when the expressions are read, and the proper kinds when the counters
42101095a5dSDimitry Andric   // are decoded.
42201095a5dSDimitry Andric   Expressions.resize(
42301095a5dSDimitry Andric       NumExpressions,
42401095a5dSDimitry Andric       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
42501095a5dSDimitry Andric   for (size_t I = 0; I < NumExpressions; ++I) {
42601095a5dSDimitry Andric     if (auto Err = readCounter(Expressions[I].LHS))
42701095a5dSDimitry Andric       return Err;
42801095a5dSDimitry Andric     if (auto Err = readCounter(Expressions[I].RHS))
42901095a5dSDimitry Andric       return Err;
43001095a5dSDimitry Andric   }
43101095a5dSDimitry Andric 
43201095a5dSDimitry Andric   // Read the mapping regions sub-arrays.
43301095a5dSDimitry Andric   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
43401095a5dSDimitry Andric        InferredFileID < S; ++InferredFileID) {
43501095a5dSDimitry Andric     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
43601095a5dSDimitry Andric                                               VirtualFileMapping.size()))
43701095a5dSDimitry Andric       return Err;
43801095a5dSDimitry Andric   }
43901095a5dSDimitry Andric 
44001095a5dSDimitry Andric   // Set the counters for the expansion regions.
44101095a5dSDimitry Andric   // i.e. Counter of expansion region = counter of the first region
44201095a5dSDimitry Andric   // from the expanded file.
44301095a5dSDimitry Andric   // Perform multiple passes to correctly propagate the counters through
44401095a5dSDimitry Andric   // all the nested expansion regions.
44501095a5dSDimitry Andric   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
44601095a5dSDimitry Andric   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
44701095a5dSDimitry Andric   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
44801095a5dSDimitry Andric     for (auto &R : MappingRegions) {
44901095a5dSDimitry Andric       if (R.Kind != CounterMappingRegion::ExpansionRegion)
45001095a5dSDimitry Andric         continue;
45101095a5dSDimitry Andric       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
45201095a5dSDimitry Andric       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
45301095a5dSDimitry Andric     }
45401095a5dSDimitry Andric     for (auto &R : MappingRegions) {
45501095a5dSDimitry Andric       if (FileIDExpansionRegionMapping[R.FileID]) {
45601095a5dSDimitry Andric         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
45701095a5dSDimitry Andric         FileIDExpansionRegionMapping[R.FileID] = nullptr;
45801095a5dSDimitry Andric       }
45901095a5dSDimitry Andric     }
46001095a5dSDimitry Andric   }
46101095a5dSDimitry Andric 
46201095a5dSDimitry Andric   return Error::success();
46301095a5dSDimitry Andric }
46401095a5dSDimitry Andric 
isDummy()46501095a5dSDimitry Andric Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
46601095a5dSDimitry Andric   // A dummy coverage mapping data consists of just one region with zero count.
46701095a5dSDimitry Andric   uint64_t NumFileMappings;
46801095a5dSDimitry Andric   if (Error Err = readSize(NumFileMappings))
46901095a5dSDimitry Andric     return std::move(Err);
47001095a5dSDimitry Andric   if (NumFileMappings != 1)
47101095a5dSDimitry Andric     return false;
47201095a5dSDimitry Andric   // We don't expect any specific value for the filename index, just skip it.
47301095a5dSDimitry Andric   uint64_t FilenameIndex;
47401095a5dSDimitry Andric   if (Error Err =
47501095a5dSDimitry Andric           readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
47601095a5dSDimitry Andric     return std::move(Err);
47701095a5dSDimitry Andric   uint64_t NumExpressions;
47801095a5dSDimitry Andric   if (Error Err = readSize(NumExpressions))
47901095a5dSDimitry Andric     return std::move(Err);
48001095a5dSDimitry Andric   if (NumExpressions != 0)
48101095a5dSDimitry Andric     return false;
48201095a5dSDimitry Andric   uint64_t NumRegions;
48301095a5dSDimitry Andric   if (Error Err = readSize(NumRegions))
48401095a5dSDimitry Andric     return std::move(Err);
48501095a5dSDimitry Andric   if (NumRegions != 1)
48601095a5dSDimitry Andric     return false;
48701095a5dSDimitry Andric   uint64_t EncodedCounterAndRegion;
48801095a5dSDimitry Andric   if (Error Err = readIntMax(EncodedCounterAndRegion,
48901095a5dSDimitry Andric                              std::numeric_limits<unsigned>::max()))
49001095a5dSDimitry Andric     return std::move(Err);
49101095a5dSDimitry Andric   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
49201095a5dSDimitry Andric   return Tag == Counter::Zero;
49301095a5dSDimitry Andric }
49401095a5dSDimitry Andric 
create(SectionRef & Section)49501095a5dSDimitry Andric Error InstrProfSymtab::create(SectionRef &Section) {
496e6d15924SDimitry Andric   Expected<StringRef> DataOrErr = Section.getContents();
497e6d15924SDimitry Andric   if (!DataOrErr)
498e6d15924SDimitry Andric     return DataOrErr.takeError();
499e6d15924SDimitry Andric   Data = *DataOrErr;
50001095a5dSDimitry Andric   Address = Section.getAddress();
501e6d15924SDimitry Andric 
502e6d15924SDimitry Andric   // If this is a linked PE/COFF file, then we have to skip over the null byte
503e6d15924SDimitry Andric   // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
504312c0ed1SDimitry Andric   // If the name section is .lprfcovnames, it doesn't have the null byte at the
505312c0ed1SDimitry Andric   // beginning.
506e6d15924SDimitry Andric   const ObjectFile *Obj = Section.getObject();
507e6d15924SDimitry Andric   if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
508312c0ed1SDimitry Andric     if (Expected<StringRef> NameOrErr = Section.getName())
509312c0ed1SDimitry Andric       if (*NameOrErr != getInstrProfSectionName(IPSK_covname, Triple::COFF))
510e6d15924SDimitry Andric         Data = Data.drop_front(1);
511e6d15924SDimitry Andric 
51201095a5dSDimitry Andric   return Error::success();
51301095a5dSDimitry Andric }
51401095a5dSDimitry Andric 
getFuncName(uint64_t Pointer,size_t Size)51501095a5dSDimitry Andric StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
51601095a5dSDimitry Andric   if (Pointer < Address)
51701095a5dSDimitry Andric     return StringRef();
51801095a5dSDimitry Andric   auto Offset = Pointer - Address;
51901095a5dSDimitry Andric   if (Offset + Size > Data.size())
52001095a5dSDimitry Andric     return StringRef();
52101095a5dSDimitry Andric   return Data.substr(Pointer - Address, Size);
52201095a5dSDimitry Andric }
52301095a5dSDimitry Andric 
52401095a5dSDimitry Andric // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
isCoverageMappingDummy(uint64_t Hash,StringRef Mapping)52501095a5dSDimitry Andric static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
52601095a5dSDimitry Andric   // The hash value of dummy mapping records is always zero.
52701095a5dSDimitry Andric   if (Hash)
52801095a5dSDimitry Andric     return false;
52901095a5dSDimitry Andric   return RawCoverageMappingDummyChecker(Mapping).isDummy();
53001095a5dSDimitry Andric }
53101095a5dSDimitry Andric 
532cfca06d7SDimitry Andric /// A range of filename indices. Used to specify the location of a batch of
533cfca06d7SDimitry Andric /// filenames in a vector-like container.
534cfca06d7SDimitry Andric struct FilenameRange {
535cfca06d7SDimitry Andric   unsigned StartingIndex;
536cfca06d7SDimitry Andric   unsigned Length;
537cfca06d7SDimitry Andric 
FilenameRangeFilenameRange538cfca06d7SDimitry Andric   FilenameRange(unsigned StartingIndex, unsigned Length)
539cfca06d7SDimitry Andric       : StartingIndex(StartingIndex), Length(Length) {}
540cfca06d7SDimitry Andric 
markInvalidFilenameRange541cfca06d7SDimitry Andric   void markInvalid() { Length = 0; }
isInvalidFilenameRange542cfca06d7SDimitry Andric   bool isInvalid() const { return Length == 0; }
543cfca06d7SDimitry Andric };
544cfca06d7SDimitry Andric 
54501095a5dSDimitry Andric namespace {
54671d5a254SDimitry Andric 
547cfca06d7SDimitry Andric /// The interface to read coverage mapping function records for a module.
54801095a5dSDimitry Andric struct CovMapFuncRecordReader {
54971d5a254SDimitry Andric   virtual ~CovMapFuncRecordReader() = default;
55071d5a254SDimitry Andric 
551cfca06d7SDimitry Andric   // Read a coverage header.
55201095a5dSDimitry Andric   //
553cfca06d7SDimitry Andric   // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
55401095a5dSDimitry Andric   // mapping data associated with the module.
55501095a5dSDimitry Andric   //
556cfca06d7SDimitry Andric   // Returns a pointer to the next \c CovHeader if it exists, or to an address
557cfca06d7SDimitry Andric   // greater than \p CovEnd if not.
558344a3780SDimitry Andric   virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
559344a3780SDimitry Andric                                                     const char *CovBufEnd) = 0;
560cfca06d7SDimitry Andric 
561cfca06d7SDimitry Andric   // Read function records.
562cfca06d7SDimitry Andric   //
563cfca06d7SDimitry Andric   // \p FuncRecBuf points to the buffer containing a batch of function records.
564cfca06d7SDimitry Andric   // \p FuncRecBufEnd points past the end of the batch of records.
565cfca06d7SDimitry Andric   //
566cfca06d7SDimitry Andric   // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
567cfca06d7SDimitry Andric   // associated with the function records. It is unused in Version4.
568cfca06d7SDimitry Andric   //
569cfca06d7SDimitry Andric   // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
570cfca06d7SDimitry Andric   // mappings associated with the function records. It is unused in Version4.
571e3b55780SDimitry Andric   virtual Error
572e3b55780SDimitry Andric   readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
573e3b55780SDimitry Andric                       std::optional<FilenameRange> OutOfLineFileRange,
574cfca06d7SDimitry Andric                       const char *OutOfLineMappingBuf,
575cfca06d7SDimitry Andric                       const char *OutOfLineMappingBufEnd) = 0;
57671d5a254SDimitry Andric 
577b1c73532SDimitry Andric   template <class IntPtrT, llvm::endianness Endian>
57801095a5dSDimitry Andric   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
57971d5a254SDimitry Andric   get(CovMapVersion Version, InstrProfSymtab &P,
580344a3780SDimitry Andric       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
581344a3780SDimitry Andric       std::vector<std::string> &F);
58201095a5dSDimitry Andric };
58301095a5dSDimitry Andric 
58401095a5dSDimitry Andric // A class for reading coverage mapping function records for a module.
585b1c73532SDimitry Andric template <CovMapVersion Version, class IntPtrT, llvm::endianness Endian>
58601095a5dSDimitry Andric class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
58708bbd35aSDimitry Andric   using FuncRecordType =
58808bbd35aSDimitry Andric       typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
58908bbd35aSDimitry Andric   using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
59001095a5dSDimitry Andric 
59101095a5dSDimitry Andric   // Maps function's name references to the indexes of their records
59201095a5dSDimitry Andric   // in \c Records.
59371d5a254SDimitry Andric   DenseMap<NameRefType, size_t> FunctionRecords;
59401095a5dSDimitry Andric   InstrProfSymtab &ProfileNames;
595344a3780SDimitry Andric   StringRef CompilationDir;
596344a3780SDimitry Andric   std::vector<std::string> &Filenames;
59701095a5dSDimitry Andric   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
59801095a5dSDimitry Andric 
599cfca06d7SDimitry Andric   // Maps a hash of the filenames in a TU to a \c FileRange. The range
600cfca06d7SDimitry Andric   // specifies the location of the hashed filenames in \c Filenames.
601cfca06d7SDimitry Andric   DenseMap<uint64_t, FilenameRange> FileRangeMap;
602cfca06d7SDimitry Andric 
60301095a5dSDimitry Andric   // Add the record to the collection if we don't already have a record that
60401095a5dSDimitry Andric   // points to the same function name. This is useful to ignore the redundant
60501095a5dSDimitry Andric   // records for the functions with ODR linkage.
60601095a5dSDimitry Andric   // In addition, prefer records with real coverage mapping data to dummy
60701095a5dSDimitry Andric   // records, which were emitted for inline functions which were seen but
60801095a5dSDimitry Andric   // not used in the corresponding translation unit.
insertFunctionRecordIfNeeded(const FuncRecordType * CFR,StringRef Mapping,FilenameRange FileRange)60901095a5dSDimitry Andric   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
610cfca06d7SDimitry Andric                                      StringRef Mapping,
611cfca06d7SDimitry Andric                                      FilenameRange FileRange) {
612cfca06d7SDimitry Andric     ++CovMapNumRecords;
61301095a5dSDimitry Andric     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
61401095a5dSDimitry Andric     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
61501095a5dSDimitry Andric     auto InsertResult =
61601095a5dSDimitry Andric         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
61701095a5dSDimitry Andric     if (InsertResult.second) {
61801095a5dSDimitry Andric       StringRef FuncName;
61901095a5dSDimitry Andric       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
62001095a5dSDimitry Andric         return Err;
62108bbd35aSDimitry Andric       if (FuncName.empty())
622c0981da4SDimitry Andric         return make_error<InstrProfError>(instrprof_error::malformed,
623c0981da4SDimitry Andric                                           "function name is empty");
624cfca06d7SDimitry Andric       ++CovMapNumUsedRecords;
625cfca06d7SDimitry Andric       Records.emplace_back(Version, FuncName, FuncHash, Mapping,
626cfca06d7SDimitry Andric                            FileRange.StartingIndex, FileRange.Length);
62701095a5dSDimitry Andric       return Error::success();
62801095a5dSDimitry Andric     }
62901095a5dSDimitry Andric     // Update the existing record if it's a dummy and the new record is real.
63001095a5dSDimitry Andric     size_t OldRecordIndex = InsertResult.first->second;
63101095a5dSDimitry Andric     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
63201095a5dSDimitry Andric         Records[OldRecordIndex];
63301095a5dSDimitry Andric     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
63401095a5dSDimitry Andric         OldRecord.FunctionHash, OldRecord.CoverageMapping);
63501095a5dSDimitry Andric     if (Error Err = OldIsDummyExpected.takeError())
63601095a5dSDimitry Andric       return Err;
63701095a5dSDimitry Andric     if (!*OldIsDummyExpected)
63801095a5dSDimitry Andric       return Error::success();
63901095a5dSDimitry Andric     Expected<bool> NewIsDummyExpected =
64001095a5dSDimitry Andric         isCoverageMappingDummy(FuncHash, Mapping);
64101095a5dSDimitry Andric     if (Error Err = NewIsDummyExpected.takeError())
64201095a5dSDimitry Andric       return Err;
64301095a5dSDimitry Andric     if (*NewIsDummyExpected)
64401095a5dSDimitry Andric       return Error::success();
645cfca06d7SDimitry Andric     ++CovMapNumUsedRecords;
64601095a5dSDimitry Andric     OldRecord.FunctionHash = FuncHash;
64701095a5dSDimitry Andric     OldRecord.CoverageMapping = Mapping;
648cfca06d7SDimitry Andric     OldRecord.FilenamesBegin = FileRange.StartingIndex;
649cfca06d7SDimitry Andric     OldRecord.FilenamesSize = FileRange.Length;
65001095a5dSDimitry Andric     return Error::success();
65101095a5dSDimitry Andric   }
65201095a5dSDimitry Andric 
65301095a5dSDimitry Andric public:
VersionedCovMapFuncRecordReader(InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,StringRef D,std::vector<std::string> & F)65401095a5dSDimitry Andric   VersionedCovMapFuncRecordReader(
65501095a5dSDimitry Andric       InstrProfSymtab &P,
656344a3780SDimitry Andric       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
657344a3780SDimitry Andric       std::vector<std::string> &F)
658344a3780SDimitry Andric       : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
65971d5a254SDimitry Andric 
66071d5a254SDimitry Andric   ~VersionedCovMapFuncRecordReader() override = default;
66101095a5dSDimitry Andric 
readCoverageHeader(const char * CovBuf,const char * CovBufEnd)662344a3780SDimitry Andric   Expected<const char *> readCoverageHeader(const char *CovBuf,
663344a3780SDimitry Andric                                             const char *CovBufEnd) override {
66401095a5dSDimitry Andric     using namespace support;
66571d5a254SDimitry Andric 
666cfca06d7SDimitry Andric     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
667b1c73532SDimitry Andric       return make_error<CoverageMapError>(
668b1c73532SDimitry Andric           coveragemap_error::malformed,
669b1c73532SDimitry Andric           "coverage mapping header section is larger than buffer size");
670cfca06d7SDimitry Andric     auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
67101095a5dSDimitry Andric     uint32_t NRecords = CovHeader->getNRecords<Endian>();
67201095a5dSDimitry Andric     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
67301095a5dSDimitry Andric     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
67401095a5dSDimitry Andric     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
675cfca06d7SDimitry Andric     CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
67601095a5dSDimitry Andric 
67701095a5dSDimitry Andric     // Skip past the function records, saving the start and end for later.
678cfca06d7SDimitry Andric     // This is a no-op in Version4 (function records are read after all headers
679cfca06d7SDimitry Andric     // are read).
680cfca06d7SDimitry Andric     const char *FuncRecBuf = nullptr;
681cfca06d7SDimitry Andric     const char *FuncRecBufEnd = nullptr;
682cfca06d7SDimitry Andric     if (Version < CovMapVersion::Version4)
683cfca06d7SDimitry Andric       FuncRecBuf = CovBuf;
684cfca06d7SDimitry Andric     CovBuf += NRecords * sizeof(FuncRecordType);
685cfca06d7SDimitry Andric     if (Version < CovMapVersion::Version4)
686cfca06d7SDimitry Andric       FuncRecBufEnd = CovBuf;
68701095a5dSDimitry Andric 
68801095a5dSDimitry Andric     // Get the filenames.
689cfca06d7SDimitry Andric     if (CovBuf + FilenamesSize > CovBufEnd)
690b1c73532SDimitry Andric       return make_error<CoverageMapError>(
691b1c73532SDimitry Andric           coveragemap_error::malformed,
692b1c73532SDimitry Andric           "filenames section is larger than buffer size");
69301095a5dSDimitry Andric     size_t FilenamesBegin = Filenames.size();
694cfca06d7SDimitry Andric     StringRef FilenameRegion(CovBuf, FilenamesSize);
695344a3780SDimitry Andric     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
696344a3780SDimitry Andric                                       CompilationDir);
697344a3780SDimitry Andric     if (auto Err = Reader.read(Version))
69801095a5dSDimitry Andric       return std::move(Err);
699cfca06d7SDimitry Andric     CovBuf += FilenamesSize;
700cfca06d7SDimitry Andric     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
701cfca06d7SDimitry Andric 
702b60736ecSDimitry Andric     if (Version >= CovMapVersion::Version4) {
703cfca06d7SDimitry Andric       // Map a hash of the filenames region to the filename range associated
704cfca06d7SDimitry Andric       // with this coverage header.
705cfca06d7SDimitry Andric       int64_t FilenamesRef =
706cfca06d7SDimitry Andric           llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
707cfca06d7SDimitry Andric       auto Insert =
708cfca06d7SDimitry Andric           FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
709cfca06d7SDimitry Andric       if (!Insert.second) {
710cfca06d7SDimitry Andric         // The same filenames ref was encountered twice. It's possible that
711cfca06d7SDimitry Andric         // the associated filenames are the same.
712cfca06d7SDimitry Andric         auto It = Filenames.begin();
713cfca06d7SDimitry Andric         FilenameRange &OrigRange = Insert.first->getSecond();
714cfca06d7SDimitry Andric         if (std::equal(It + OrigRange.StartingIndex,
715cfca06d7SDimitry Andric                        It + OrigRange.StartingIndex + OrigRange.Length,
716cfca06d7SDimitry Andric                        It + FileRange.StartingIndex,
717cfca06d7SDimitry Andric                        It + FileRange.StartingIndex + FileRange.Length))
718cfca06d7SDimitry Andric           // Map the new range to the original one.
719cfca06d7SDimitry Andric           FileRange = OrigRange;
720cfca06d7SDimitry Andric         else
721cfca06d7SDimitry Andric           // This is a hash collision. Mark the filenames ref invalid.
722cfca06d7SDimitry Andric           OrigRange.markInvalid();
723cfca06d7SDimitry Andric       }
724cfca06d7SDimitry Andric     }
72501095a5dSDimitry Andric 
72601095a5dSDimitry Andric     // We'll read the coverage mapping records in the loop below.
727cfca06d7SDimitry Andric     // This is a no-op in Version4 (coverage mappings are not affixed to the
728cfca06d7SDimitry Andric     // coverage header).
729cfca06d7SDimitry Andric     const char *MappingBuf = CovBuf;
730b60736ecSDimitry Andric     if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
731b1c73532SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed,
732b1c73532SDimitry Andric                                           "coverage mapping size is not zero");
733cfca06d7SDimitry Andric     CovBuf += CoverageSize;
734cfca06d7SDimitry Andric     const char *MappingEnd = CovBuf;
735cfca06d7SDimitry Andric 
736cfca06d7SDimitry Andric     if (CovBuf > CovBufEnd)
737b1c73532SDimitry Andric       return make_error<CoverageMapError>(
738b1c73532SDimitry Andric           coveragemap_error::malformed,
739b1c73532SDimitry Andric           "function records section is larger than buffer size");
740cfca06d7SDimitry Andric 
741cfca06d7SDimitry Andric     if (Version < CovMapVersion::Version4) {
742cfca06d7SDimitry Andric       // Read each function record.
743cfca06d7SDimitry Andric       if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
744cfca06d7SDimitry Andric                                         MappingBuf, MappingEnd))
745cfca06d7SDimitry Andric         return std::move(E);
746cfca06d7SDimitry Andric     }
747cfca06d7SDimitry Andric 
74801095a5dSDimitry Andric     // Each coverage map has an alignment of 8, so we need to adjust alignment
74901095a5dSDimitry Andric     // before reading the next map.
750cfca06d7SDimitry Andric     CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
75101095a5dSDimitry Andric 
752cfca06d7SDimitry Andric     return CovBuf;
75301095a5dSDimitry Andric   }
754cfca06d7SDimitry Andric 
readFunctionRecords(const char * FuncRecBuf,const char * FuncRecBufEnd,std::optional<FilenameRange> OutOfLineFileRange,const char * OutOfLineMappingBuf,const char * OutOfLineMappingBufEnd)755cfca06d7SDimitry Andric   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
756e3b55780SDimitry Andric                             std::optional<FilenameRange> OutOfLineFileRange,
757cfca06d7SDimitry Andric                             const char *OutOfLineMappingBuf,
758cfca06d7SDimitry Andric                             const char *OutOfLineMappingBufEnd) override {
759cfca06d7SDimitry Andric     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
760cfca06d7SDimitry Andric     while ((const char *)CFR < FuncRecBufEnd) {
761cfca06d7SDimitry Andric       // Validate the length of the coverage mapping for this function.
762cfca06d7SDimitry Andric       const char *NextMappingBuf;
763cfca06d7SDimitry Andric       const FuncRecordType *NextCFR;
764cfca06d7SDimitry Andric       std::tie(NextMappingBuf, NextCFR) =
765cfca06d7SDimitry Andric           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
766cfca06d7SDimitry Andric       if (Version < CovMapVersion::Version4)
767cfca06d7SDimitry Andric         if (NextMappingBuf > OutOfLineMappingBufEnd)
768b1c73532SDimitry Andric           return make_error<CoverageMapError>(
769b1c73532SDimitry Andric               coveragemap_error::malformed,
770b1c73532SDimitry Andric               "next mapping buffer is larger than buffer size");
771cfca06d7SDimitry Andric 
772cfca06d7SDimitry Andric       // Look up the set of filenames associated with this function record.
773e3b55780SDimitry Andric       std::optional<FilenameRange> FileRange;
774cfca06d7SDimitry Andric       if (Version < CovMapVersion::Version4) {
775cfca06d7SDimitry Andric         FileRange = OutOfLineFileRange;
776cfca06d7SDimitry Andric       } else {
777cfca06d7SDimitry Andric         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
778cfca06d7SDimitry Andric         auto It = FileRangeMap.find(FilenamesRef);
779cfca06d7SDimitry Andric         if (It == FileRangeMap.end())
780b1c73532SDimitry Andric           return make_error<CoverageMapError>(
781b1c73532SDimitry Andric               coveragemap_error::malformed,
782b1c73532SDimitry Andric               "no filename found for function with hash=0x" +
783b1c73532SDimitry Andric                   Twine::utohexstr(FilenamesRef));
784cfca06d7SDimitry Andric         else
785cfca06d7SDimitry Andric           FileRange = It->getSecond();
786cfca06d7SDimitry Andric       }
787cfca06d7SDimitry Andric 
788cfca06d7SDimitry Andric       // Now, read the coverage data.
789cfca06d7SDimitry Andric       if (FileRange && !FileRange->isInvalid()) {
790cfca06d7SDimitry Andric         StringRef Mapping =
791cfca06d7SDimitry Andric             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
792b60736ecSDimitry Andric         if (Version >= CovMapVersion::Version4 &&
793cfca06d7SDimitry Andric             Mapping.data() + Mapping.size() > FuncRecBufEnd)
794b1c73532SDimitry Andric           return make_error<CoverageMapError>(
795b1c73532SDimitry Andric               coveragemap_error::malformed,
796b1c73532SDimitry Andric               "coverage mapping data is larger than buffer size");
797cfca06d7SDimitry Andric         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
798cfca06d7SDimitry Andric           return Err;
799cfca06d7SDimitry Andric       }
800cfca06d7SDimitry Andric 
801cfca06d7SDimitry Andric       std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
802cfca06d7SDimitry Andric     }
803cfca06d7SDimitry Andric     return Error::success();
80401095a5dSDimitry Andric   }
80501095a5dSDimitry Andric };
80671d5a254SDimitry Andric 
80701095a5dSDimitry Andric } // end anonymous namespace
80801095a5dSDimitry Andric 
809b1c73532SDimitry Andric template <class IntPtrT, llvm::endianness Endian>
get(CovMapVersion Version,InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,StringRef D,std::vector<std::string> & F)81001095a5dSDimitry Andric Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
81171d5a254SDimitry Andric     CovMapVersion Version, InstrProfSymtab &P,
812344a3780SDimitry Andric     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
813344a3780SDimitry Andric     std::vector<std::string> &F) {
81401095a5dSDimitry Andric   using namespace coverage;
81571d5a254SDimitry Andric 
81601095a5dSDimitry Andric   switch (Version) {
81701095a5dSDimitry Andric   case CovMapVersion::Version1:
8181d5ae102SDimitry Andric     return std::make_unique<VersionedCovMapFuncRecordReader<
819344a3780SDimitry Andric         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
82001095a5dSDimitry Andric   case CovMapVersion::Version2:
821044eb2f6SDimitry Andric   case CovMapVersion::Version3:
822cfca06d7SDimitry Andric   case CovMapVersion::Version4:
823b60736ecSDimitry Andric   case CovMapVersion::Version5:
824344a3780SDimitry Andric   case CovMapVersion::Version6:
825b1c73532SDimitry Andric   case CovMapVersion::Version7:
82601095a5dSDimitry Andric     // Decompress the name data.
82701095a5dSDimitry Andric     if (Error E = P.create(P.getNameData()))
82801095a5dSDimitry Andric       return std::move(E);
829044eb2f6SDimitry Andric     if (Version == CovMapVersion::Version2)
8301d5ae102SDimitry Andric       return std::make_unique<VersionedCovMapFuncRecordReader<
831344a3780SDimitry Andric           CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
832cfca06d7SDimitry Andric     else if (Version == CovMapVersion::Version3)
8331d5ae102SDimitry Andric       return std::make_unique<VersionedCovMapFuncRecordReader<
834344a3780SDimitry Andric           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
835cfca06d7SDimitry Andric     else if (Version == CovMapVersion::Version4)
836cfca06d7SDimitry Andric       return std::make_unique<VersionedCovMapFuncRecordReader<
837344a3780SDimitry Andric           CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
838b60736ecSDimitry Andric     else if (Version == CovMapVersion::Version5)
839b60736ecSDimitry Andric       return std::make_unique<VersionedCovMapFuncRecordReader<
840344a3780SDimitry Andric           CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
841344a3780SDimitry Andric     else if (Version == CovMapVersion::Version6)
842344a3780SDimitry Andric       return std::make_unique<VersionedCovMapFuncRecordReader<
843344a3780SDimitry Andric           CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
844b1c73532SDimitry Andric     else if (Version == CovMapVersion::Version7)
845b1c73532SDimitry Andric       return std::make_unique<VersionedCovMapFuncRecordReader<
846b1c73532SDimitry Andric           CovMapVersion::Version7, IntPtrT, Endian>>(P, R, D, F);
84701095a5dSDimitry Andric   }
84801095a5dSDimitry Andric   llvm_unreachable("Unsupported version");
84901095a5dSDimitry Andric }
85001095a5dSDimitry Andric 
851b1c73532SDimitry Andric template <typename T, llvm::endianness Endian>
readCoverageMappingData(InstrProfSymtab & ProfileNames,StringRef CovMap,StringRef FuncRecords,std::vector<BinaryCoverageReader::ProfileMappingRecord> & Records,StringRef CompilationDir,std::vector<std::string> & Filenames)85201095a5dSDimitry Andric static Error readCoverageMappingData(
853cfca06d7SDimitry Andric     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
85401095a5dSDimitry Andric     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
855344a3780SDimitry Andric     StringRef CompilationDir, std::vector<std::string> &Filenames) {
85601095a5dSDimitry Andric   using namespace coverage;
85771d5a254SDimitry Andric 
85801095a5dSDimitry Andric   // Read the records in the coverage data section.
85901095a5dSDimitry Andric   auto CovHeader =
860cfca06d7SDimitry Andric       reinterpret_cast<const CovMapHeader *>(CovMap.data());
86101095a5dSDimitry Andric   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
86271d5a254SDimitry Andric   if (Version > CovMapVersion::CurrentVersion)
86301095a5dSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
86401095a5dSDimitry Andric   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
86501095a5dSDimitry Andric       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
866344a3780SDimitry Andric                                              CompilationDir, Filenames);
86701095a5dSDimitry Andric   if (Error E = ReaderExpected.takeError())
86801095a5dSDimitry Andric     return E;
86901095a5dSDimitry Andric   auto Reader = std::move(ReaderExpected.get());
870cfca06d7SDimitry Andric   const char *CovBuf = CovMap.data();
871cfca06d7SDimitry Andric   const char *CovBufEnd = CovBuf + CovMap.size();
872cfca06d7SDimitry Andric   const char *FuncRecBuf = FuncRecords.data();
873cfca06d7SDimitry Andric   const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
874cfca06d7SDimitry Andric   while (CovBuf < CovBufEnd) {
875cfca06d7SDimitry Andric     // Read the current coverage header & filename data.
876cfca06d7SDimitry Andric     //
877cfca06d7SDimitry Andric     // Prior to Version4, this also reads all function records affixed to the
878cfca06d7SDimitry Andric     // header.
879cfca06d7SDimitry Andric     //
880cfca06d7SDimitry Andric     // Return a pointer to the next coverage header.
881344a3780SDimitry Andric     auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
882cfca06d7SDimitry Andric     if (auto E = NextOrErr.takeError())
88301095a5dSDimitry Andric       return E;
884cfca06d7SDimitry Andric     CovBuf = NextOrErr.get();
88501095a5dSDimitry Andric   }
886cfca06d7SDimitry Andric   // In Version4, function records are not affixed to coverage headers. Read
887cfca06d7SDimitry Andric   // the records from their dedicated section.
888b60736ecSDimitry Andric   if (Version >= CovMapVersion::Version4)
889e3b55780SDimitry Andric     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
890e3b55780SDimitry Andric                                        nullptr, nullptr);
89101095a5dSDimitry Andric   return Error::success();
89201095a5dSDimitry Andric }
89371d5a254SDimitry Andric 
894e6d15924SDimitry Andric Expected<std::unique_ptr<BinaryCoverageReader>>
createCoverageReaderFromBuffer(StringRef Coverage,FuncRecordsStorage && FuncRecords,std::unique_ptr<InstrProfSymtab> ProfileNamesPtr,uint8_t BytesInAddress,llvm::endianness Endian,StringRef CompilationDir)895e6d15924SDimitry Andric BinaryCoverageReader::createCoverageReaderFromBuffer(
896344a3780SDimitry Andric     StringRef Coverage, FuncRecordsStorage &&FuncRecords,
897ac9a064cSDimitry Andric     std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
898b1c73532SDimitry Andric     llvm::endianness Endian, StringRef CompilationDir) {
899ac9a064cSDimitry Andric   if (ProfileNamesPtr == nullptr)
900ac9a064cSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
901ac9a064cSDimitry Andric                                         "Caller must provide ProfileNames");
902ac9a064cSDimitry Andric   std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader(
903ac9a064cSDimitry Andric       std::move(ProfileNamesPtr), std::move(FuncRecords)));
904ac9a064cSDimitry Andric   InstrProfSymtab &ProfileNames = *Reader->ProfileNames;
905344a3780SDimitry Andric   StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
906b1c73532SDimitry Andric   if (BytesInAddress == 4 && Endian == llvm::endianness::little) {
907b1c73532SDimitry Andric     if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>(
908ac9a064cSDimitry Andric             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
909ac9a064cSDimitry Andric             CompilationDir, Reader->Filenames))
910e6d15924SDimitry Andric       return std::move(E);
911b1c73532SDimitry Andric   } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) {
912b1c73532SDimitry Andric     if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>(
913ac9a064cSDimitry Andric             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
914ac9a064cSDimitry Andric             CompilationDir, Reader->Filenames))
915e6d15924SDimitry Andric       return std::move(E);
916b1c73532SDimitry Andric   } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) {
917b1c73532SDimitry Andric     if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>(
918ac9a064cSDimitry Andric             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
919ac9a064cSDimitry Andric             CompilationDir, Reader->Filenames))
920e6d15924SDimitry Andric       return std::move(E);
921b1c73532SDimitry Andric   } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) {
922b1c73532SDimitry Andric     if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>(
923ac9a064cSDimitry Andric             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
924ac9a064cSDimitry Andric             CompilationDir, Reader->Filenames))
925e6d15924SDimitry Andric       return std::move(E);
926e6d15924SDimitry Andric   } else
927b1c73532SDimitry Andric     return make_error<CoverageMapError>(
928b1c73532SDimitry Andric         coveragemap_error::malformed,
929b1c73532SDimitry Andric         "not supported endianness or bytes in address");
930e6d15924SDimitry Andric   return std::move(Reader);
931e6d15924SDimitry Andric }
932e6d15924SDimitry Andric 
933e6d15924SDimitry Andric static Expected<std::unique_ptr<BinaryCoverageReader>>
loadTestingFormat(StringRef Data,StringRef CompilationDir)934344a3780SDimitry Andric loadTestingFormat(StringRef Data, StringRef CompilationDir) {
935e6d15924SDimitry Andric   uint8_t BytesInAddress = 8;
936b1c73532SDimitry Andric   llvm::endianness Endian = llvm::endianness::little;
93701095a5dSDimitry Andric 
938b1c73532SDimitry Andric   // Read the magic and version.
939b1c73532SDimitry Andric   Data = Data.substr(sizeof(TestingFormatMagic));
940b1c73532SDimitry Andric   if (Data.size() < sizeof(uint64_t))
941b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
942b1c73532SDimitry Andric                                         "the size of data is too small");
943b1c73532SDimitry Andric   auto TestingVersion =
944b1c73532SDimitry Andric       support::endian::byte_swap<uint64_t, llvm::endianness::little>(
945b1c73532SDimitry Andric           *reinterpret_cast<const uint64_t *>(Data.data()));
946b1c73532SDimitry Andric   Data = Data.substr(sizeof(uint64_t));
947b1c73532SDimitry Andric 
948b1c73532SDimitry Andric   // Read the ProfileNames data.
94908bbd35aSDimitry Andric   if (Data.empty())
95001095a5dSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
95101095a5dSDimitry Andric   unsigned N = 0;
952e6d15924SDimitry Andric   uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
95301095a5dSDimitry Andric   if (N > Data.size())
954b1c73532SDimitry Andric     return make_error<CoverageMapError>(
955b1c73532SDimitry Andric         coveragemap_error::malformed,
956b1c73532SDimitry Andric         "the size of TestingFormatMagic is too big");
95701095a5dSDimitry Andric   Data = Data.substr(N);
95808bbd35aSDimitry Andric   if (Data.empty())
95901095a5dSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
96001095a5dSDimitry Andric   N = 0;
961e6d15924SDimitry Andric   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
96201095a5dSDimitry Andric   if (N > Data.size())
963b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
964b1c73532SDimitry Andric                                         "the size of ULEB128 is too big");
96501095a5dSDimitry Andric   Data = Data.substr(N);
96601095a5dSDimitry Andric   if (Data.size() < ProfileNamesSize)
967b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
968b1c73532SDimitry Andric                                         "the size of ProfileNames is too big");
969ac9a064cSDimitry Andric   auto ProfileNames = std::make_unique<InstrProfSymtab>();
970ac9a064cSDimitry Andric   if (Error E = ProfileNames->create(Data.substr(0, ProfileNamesSize), Address))
971e6d15924SDimitry Andric     return std::move(E);
972344a3780SDimitry Andric   Data = Data.substr(ProfileNamesSize);
973b1c73532SDimitry Andric 
974b1c73532SDimitry Andric   // In Version2, the size of CoverageMapping is stored directly.
975b1c73532SDimitry Andric   uint64_t CoverageMappingSize;
976b1c73532SDimitry Andric   if (TestingVersion == uint64_t(TestingFormatVersion::Version2)) {
977b1c73532SDimitry Andric     N = 0;
978b1c73532SDimitry Andric     CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N);
979b1c73532SDimitry Andric     if (N > Data.size())
980b1c73532SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed,
981b1c73532SDimitry Andric                                           "the size of ULEB128 is too big");
982b1c73532SDimitry Andric     Data = Data.substr(N);
983b1c73532SDimitry Andric     if (CoverageMappingSize < sizeof(CovMapHeader))
984b1c73532SDimitry Andric       return make_error<CoverageMapError>(
985b1c73532SDimitry Andric           coveragemap_error::malformed,
986b1c73532SDimitry Andric           "the size of CoverageMapping is teoo small");
987b1c73532SDimitry Andric   } else if (TestingVersion != uint64_t(TestingFormatVersion::Version1)) {
988b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
989b1c73532SDimitry Andric   }
990b1c73532SDimitry Andric 
99101095a5dSDimitry Andric   // Skip the padding bytes because coverage map data has an alignment of 8.
992b1c73532SDimitry Andric   auto Pad = offsetToAlignedAddr(Data.data(), Align(8));
993344a3780SDimitry Andric   if (Data.size() < Pad)
994b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
995b1c73532SDimitry Andric                                         "insufficient padding");
996344a3780SDimitry Andric   Data = Data.substr(Pad);
997344a3780SDimitry Andric   if (Data.size() < sizeof(CovMapHeader))
998b1c73532SDimitry Andric     return make_error<CoverageMapError>(
999b1c73532SDimitry Andric         coveragemap_error::malformed,
1000b1c73532SDimitry Andric         "coverage mapping header section is larger than data size");
1001344a3780SDimitry Andric   auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
1002344a3780SDimitry Andric       Data.substr(0, sizeof(CovMapHeader)).data());
1003b1c73532SDimitry Andric   auto Version =
1004b1c73532SDimitry Andric       CovMapVersion(CovHeader->getVersion<llvm::endianness::little>());
1005b1c73532SDimitry Andric 
1006b1c73532SDimitry Andric   // In Version1, the size of CoverageMapping is calculated.
1007b1c73532SDimitry Andric   if (TestingVersion == uint64_t(TestingFormatVersion::Version1)) {
1008344a3780SDimitry Andric     if (Version < CovMapVersion::Version4) {
1009b1c73532SDimitry Andric       CoverageMappingSize = Data.size();
1010344a3780SDimitry Andric     } else {
1011b1c73532SDimitry Andric       auto FilenamesSize =
1012b1c73532SDimitry Andric           CovHeader->getFilenamesSize<llvm::endianness::little>();
1013b1c73532SDimitry Andric       CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
1014b1c73532SDimitry Andric     }
1015b1c73532SDimitry Andric   }
1016b1c73532SDimitry Andric 
1017b1c73532SDimitry Andric   auto CoverageMapping = Data.substr(0, CoverageMappingSize);
1018344a3780SDimitry Andric   Data = Data.substr(CoverageMappingSize);
1019b1c73532SDimitry Andric 
1020b1c73532SDimitry Andric   // Read the CoverageRecords data.
1021b1c73532SDimitry Andric   if (Version < CovMapVersion::Version4) {
1022b1c73532SDimitry Andric     if (!Data.empty())
1023b1c73532SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed,
1024b1c73532SDimitry Andric                                           "data is not empty");
1025b1c73532SDimitry Andric   } else {
1026344a3780SDimitry Andric     // Skip the padding bytes because coverage records data has an alignment
1027344a3780SDimitry Andric     // of 8.
1028344a3780SDimitry Andric     Pad = offsetToAlignedAddr(Data.data(), Align(8));
1029344a3780SDimitry Andric     if (Data.size() < Pad)
1030b1c73532SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed,
1031b1c73532SDimitry Andric                                           "insufficient padding");
1032b1c73532SDimitry Andric     Data = Data.substr(Pad);
1033344a3780SDimitry Andric   }
1034b1c73532SDimitry Andric   BinaryCoverageReader::FuncRecordsStorage CoverageRecords =
1035b1c73532SDimitry Andric       MemoryBuffer::getMemBuffer(Data);
1036b1c73532SDimitry Andric 
1037e6d15924SDimitry Andric   return BinaryCoverageReader::createCoverageReaderFromBuffer(
1038344a3780SDimitry Andric       CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames),
1039344a3780SDimitry Andric       BytesInAddress, Endian, CompilationDir);
104001095a5dSDimitry Andric }
104101095a5dSDimitry Andric 
1042312c0ed1SDimitry Andric /// Find all sections that match \p IPSK name. There may be more than one if
1043312c0ed1SDimitry Andric /// comdats are in use, e.g. for the __llvm_covfun section on ELF.
1044312c0ed1SDimitry Andric static Expected<std::vector<SectionRef>>
lookupSections(ObjectFile & OF,InstrProfSectKind IPSK)1045312c0ed1SDimitry Andric lookupSections(ObjectFile &OF, InstrProfSectKind IPSK) {
1046312c0ed1SDimitry Andric   auto ObjFormat = OF.getTripleObjectFormat();
1047312c0ed1SDimitry Andric   auto Name =
1048312c0ed1SDimitry Andric       getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false);
1049e6d15924SDimitry Andric   // On COFF, the object file section name may end in "$M". This tells the
1050e6d15924SDimitry Andric   // linker to sort these sections between "$A" and "$Z". The linker removes the
1051e6d15924SDimitry Andric   // dollar and everything after it in the final binary. Do the same to match.
1052e6d15924SDimitry Andric   bool IsCOFF = isa<COFFObjectFile>(OF);
1053e6d15924SDimitry Andric   auto stripSuffix = [IsCOFF](StringRef N) {
1054e6d15924SDimitry Andric     return IsCOFF ? N.split('$').first : N;
1055e6d15924SDimitry Andric   };
1056e6d15924SDimitry Andric   Name = stripSuffix(Name);
1057e6d15924SDimitry Andric 
1058cfca06d7SDimitry Andric   std::vector<SectionRef> Sections;
105901095a5dSDimitry Andric   for (const auto &Section : OF.sections()) {
10601d5ae102SDimitry Andric     Expected<StringRef> NameOrErr = Section.getName();
10611d5ae102SDimitry Andric     if (!NameOrErr)
10621d5ae102SDimitry Andric       return NameOrErr.takeError();
1063312c0ed1SDimitry Andric     if (stripSuffix(*NameOrErr) == Name) {
1064312c0ed1SDimitry Andric       // COFF profile name section contains two null bytes indicating the
1065312c0ed1SDimitry Andric       // start/end of the section. If its size is 2 bytes, it's empty.
1066312c0ed1SDimitry Andric       if (IsCOFF && IPSK == IPSK_name && Section.getSize() == 2)
1067312c0ed1SDimitry Andric         continue;
1068cfca06d7SDimitry Andric       Sections.push_back(Section);
106901095a5dSDimitry Andric     }
1070312c0ed1SDimitry Andric   }
1071cfca06d7SDimitry Andric   if (Sections.empty())
107201095a5dSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
1073cfca06d7SDimitry Andric   return Sections;
107401095a5dSDimitry Andric }
107501095a5dSDimitry Andric 
1076e6d15924SDimitry Andric static Expected<std::unique_ptr<BinaryCoverageReader>>
loadBinaryFormat(std::unique_ptr<Binary> Bin,StringRef Arch,StringRef CompilationDir="",object::BuildIDRef * BinaryID=nullptr)1077344a3780SDimitry Andric loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
10787fa27ce4SDimitry Andric                  StringRef CompilationDir = "",
10797fa27ce4SDimitry Andric                  object::BuildIDRef *BinaryID = nullptr) {
108001095a5dSDimitry Andric   std::unique_ptr<ObjectFile> OF;
108171d5a254SDimitry Andric   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
108201095a5dSDimitry Andric     // If we have a universal binary, try to look up the object for the
108301095a5dSDimitry Andric     // appropriate architecture.
10841d5ae102SDimitry Andric     auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
108501095a5dSDimitry Andric     if (!ObjectFileOrErr)
108601095a5dSDimitry Andric       return ObjectFileOrErr.takeError();
108701095a5dSDimitry Andric     OF = std::move(ObjectFileOrErr.get());
108871d5a254SDimitry Andric   } else if (isa<ObjectFile>(Bin.get())) {
108901095a5dSDimitry Andric     // For any other object file, upcast and take ownership.
109071d5a254SDimitry Andric     OF.reset(cast<ObjectFile>(Bin.release()));
109101095a5dSDimitry Andric     // If we've asked for a particular arch, make sure they match.
109201095a5dSDimitry Andric     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
109301095a5dSDimitry Andric       return errorCodeToError(object_error::arch_not_found);
109401095a5dSDimitry Andric   } else
109501095a5dSDimitry Andric     // We can only handle object files.
1096b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
1097b1c73532SDimitry Andric                                         "binary is not an object file");
109801095a5dSDimitry Andric 
109901095a5dSDimitry Andric   // The coverage uses native pointer sizes for the object it's written in.
1100e6d15924SDimitry Andric   uint8_t BytesInAddress = OF->getBytesInAddress();
1101b1c73532SDimitry Andric   llvm::endianness Endian =
1102b1c73532SDimitry Andric       OF->isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;
110301095a5dSDimitry Andric 
110401095a5dSDimitry Andric   // Look for the sections that we are interested in.
1105ac9a064cSDimitry Andric   auto ProfileNames = std::make_unique<InstrProfSymtab>();
1106312c0ed1SDimitry Andric   std::vector<SectionRef> NamesSectionRefs;
1107312c0ed1SDimitry Andric   // If IPSK_name is not found, fallback to search for IPK_covname, which is
1108312c0ed1SDimitry Andric   // used when binary correlation is enabled.
1109312c0ed1SDimitry Andric   auto NamesSection = lookupSections(*OF, IPSK_name);
1110312c0ed1SDimitry Andric   if (auto E = NamesSection.takeError()) {
1111312c0ed1SDimitry Andric     consumeError(std::move(E));
1112312c0ed1SDimitry Andric     NamesSection = lookupSections(*OF, IPSK_covname);
111301095a5dSDimitry Andric     if (auto E = NamesSection.takeError())
1114e6d15924SDimitry Andric       return std::move(E);
1115312c0ed1SDimitry Andric   }
1116312c0ed1SDimitry Andric   NamesSectionRefs = *NamesSection;
1117312c0ed1SDimitry Andric 
1118312c0ed1SDimitry Andric   if (NamesSectionRefs.size() != 1)
1119312c0ed1SDimitry Andric     return make_error<CoverageMapError>(
1120312c0ed1SDimitry Andric         coveragemap_error::malformed,
1121312c0ed1SDimitry Andric         "the size of coverage mapping section is not one");
1122ac9a064cSDimitry Andric   if (Error E = ProfileNames->create(NamesSectionRefs.back()))
1123312c0ed1SDimitry Andric     return std::move(E);
1124312c0ed1SDimitry Andric 
1125312c0ed1SDimitry Andric   auto CoverageSection = lookupSections(*OF, IPSK_covmap);
112601095a5dSDimitry Andric   if (auto E = CoverageSection.takeError())
1127e6d15924SDimitry Andric     return std::move(E);
1128cfca06d7SDimitry Andric   std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
1129cfca06d7SDimitry Andric   if (CoverageSectionRefs.size() != 1)
1130b1c73532SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed,
1131b1c73532SDimitry Andric                                         "the size of name section is not one");
1132cfca06d7SDimitry Andric   auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
1133e6d15924SDimitry Andric   if (!CoverageMappingOrErr)
1134e6d15924SDimitry Andric     return CoverageMappingOrErr.takeError();
1135cfca06d7SDimitry Andric   StringRef CoverageMapping = CoverageMappingOrErr.get();
113601095a5dSDimitry Andric 
1137cfca06d7SDimitry Andric   // Look for the coverage records section (Version4 only).
1138312c0ed1SDimitry Andric   auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun);
1139344a3780SDimitry Andric 
1140344a3780SDimitry Andric   BinaryCoverageReader::FuncRecordsStorage FuncRecords;
1141344a3780SDimitry Andric   if (auto E = CoverageRecordsSections.takeError()) {
1142cfca06d7SDimitry Andric     consumeError(std::move(E));
1143344a3780SDimitry Andric     FuncRecords = MemoryBuffer::getMemBuffer("");
1144344a3780SDimitry Andric   } else {
1145344a3780SDimitry Andric     // Compute the FuncRecordsBuffer of the buffer, taking into account the
1146344a3780SDimitry Andric     // padding between each record, and making sure the first block is aligned
1147344a3780SDimitry Andric     // in memory to maintain consistency between buffer address and size
1148344a3780SDimitry Andric     // alignment.
1149344a3780SDimitry Andric     const Align RecordAlignment(8);
1150344a3780SDimitry Andric     uint64_t FuncRecordsSize = 0;
1151cfca06d7SDimitry Andric     for (SectionRef Section : *CoverageRecordsSections) {
1152cfca06d7SDimitry Andric       auto CoverageRecordsOrErr = Section.getContents();
1153cfca06d7SDimitry Andric       if (!CoverageRecordsOrErr)
1154cfca06d7SDimitry Andric         return CoverageRecordsOrErr.takeError();
1155344a3780SDimitry Andric       FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
1156cfca06d7SDimitry Andric     }
1157344a3780SDimitry Andric     auto WritableBuffer =
1158344a3780SDimitry Andric         WritableMemoryBuffer::getNewUninitMemBuffer(FuncRecordsSize);
1159344a3780SDimitry Andric     char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
1160344a3780SDimitry Andric     assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) &&
1161344a3780SDimitry Andric            "Allocated memory is correctly aligned");
1162344a3780SDimitry Andric 
1163344a3780SDimitry Andric     for (SectionRef Section : *CoverageRecordsSections) {
1164344a3780SDimitry Andric       auto CoverageRecordsOrErr = Section.getContents();
1165344a3780SDimitry Andric       if (!CoverageRecordsOrErr)
1166344a3780SDimitry Andric         return CoverageRecordsOrErr.takeError();
1167344a3780SDimitry Andric       const auto &CoverageRecords = CoverageRecordsOrErr.get();
1168344a3780SDimitry Andric       FuncRecordsBuffer = std::copy(CoverageRecords.begin(),
1169344a3780SDimitry Andric                                     CoverageRecords.end(), FuncRecordsBuffer);
1170344a3780SDimitry Andric       FuncRecordsBuffer =
1171344a3780SDimitry Andric           std::fill_n(FuncRecordsBuffer,
1172344a3780SDimitry Andric                       alignAddr(FuncRecordsBuffer, RecordAlignment) -
1173344a3780SDimitry Andric                           (uintptr_t)FuncRecordsBuffer,
1174344a3780SDimitry Andric                       '\0');
1175344a3780SDimitry Andric     }
1176344a3780SDimitry Andric     assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
1177344a3780SDimitry Andric            "consistent init");
1178344a3780SDimitry Andric     FuncRecords = std::move(WritableBuffer);
1179cfca06d7SDimitry Andric   }
1180cfca06d7SDimitry Andric 
11817fa27ce4SDimitry Andric   if (BinaryID)
11827fa27ce4SDimitry Andric     *BinaryID = getBuildID(OF.get());
11837fa27ce4SDimitry Andric 
1184e6d15924SDimitry Andric   return BinaryCoverageReader::createCoverageReaderFromBuffer(
1185cfca06d7SDimitry Andric       CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
1186344a3780SDimitry Andric       BytesInAddress, Endian, CompilationDir);
118701095a5dSDimitry Andric }
118801095a5dSDimitry Andric 
1189b60736ecSDimitry Andric /// Determine whether \p Arch is invalid or empty, given \p Bin.
isArchSpecifierInvalidOrMissing(Binary * Bin,StringRef Arch)1190b60736ecSDimitry Andric static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
1191b60736ecSDimitry Andric   // If we have a universal binary and Arch doesn't identify any of its slices,
1192b60736ecSDimitry Andric   // it's user error.
1193b60736ecSDimitry Andric   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
1194b60736ecSDimitry Andric     for (auto &ObjForArch : Universal->objects())
1195b60736ecSDimitry Andric       if (Arch == ObjForArch.getArchFlagName())
1196b60736ecSDimitry Andric         return false;
1197b60736ecSDimitry Andric     return true;
1198b60736ecSDimitry Andric   }
1199b60736ecSDimitry Andric   return false;
1200b60736ecSDimitry Andric }
1201b60736ecSDimitry Andric 
1202e6d15924SDimitry Andric Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
create(MemoryBufferRef ObjectBuffer,StringRef Arch,SmallVectorImpl<std::unique_ptr<MemoryBuffer>> & ObjectFileBuffers,StringRef CompilationDir,SmallVectorImpl<object::BuildIDRef> * BinaryIDs)1203e6d15924SDimitry Andric BinaryCoverageReader::create(
1204e6d15924SDimitry Andric     MemoryBufferRef ObjectBuffer, StringRef Arch,
1205344a3780SDimitry Andric     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
12067fa27ce4SDimitry Andric     StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {
1207e6d15924SDimitry Andric   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
120801095a5dSDimitry Andric 
1209b1c73532SDimitry Andric   if (ObjectBuffer.getBuffer().size() > sizeof(TestingFormatMagic)) {
1210b1c73532SDimitry Andric     uint64_t Magic =
1211b1c73532SDimitry Andric         support::endian::byte_swap<uint64_t, llvm::endianness::little>(
1212b1c73532SDimitry Andric             *reinterpret_cast<const uint64_t *>(ObjectBuffer.getBufferStart()));
1213b1c73532SDimitry Andric     if (Magic == TestingFormatMagic) {
121401095a5dSDimitry Andric       // This is a special format used for testing.
1215344a3780SDimitry Andric       auto ReaderOrErr =
1216344a3780SDimitry Andric           loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
1217e6d15924SDimitry Andric       if (!ReaderOrErr)
1218e6d15924SDimitry Andric         return ReaderOrErr.takeError();
1219e6d15924SDimitry Andric       Readers.push_back(std::move(ReaderOrErr.get()));
1220e6d15924SDimitry Andric       return std::move(Readers);
1221e6d15924SDimitry Andric     }
1222b1c73532SDimitry Andric   }
122301095a5dSDimitry Andric 
1224e6d15924SDimitry Andric   auto BinOrErr = createBinary(ObjectBuffer);
1225e6d15924SDimitry Andric   if (!BinOrErr)
1226e6d15924SDimitry Andric     return BinOrErr.takeError();
1227e6d15924SDimitry Andric   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
1228e6d15924SDimitry Andric 
1229b60736ecSDimitry Andric   if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
1230b60736ecSDimitry Andric     return make_error<CoverageMapError>(
1231b60736ecSDimitry Andric         coveragemap_error::invalid_or_missing_arch_specifier);
1232b60736ecSDimitry Andric 
1233e6d15924SDimitry Andric   // MachO universal binaries which contain archives need to be treated as
1234e6d15924SDimitry Andric   // archives, not as regular binaries.
1235e6d15924SDimitry Andric   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
1236e6d15924SDimitry Andric     for (auto &ObjForArch : Universal->objects()) {
1237e6d15924SDimitry Andric       // Skip slices within the universal binary which target the wrong arch.
1238e6d15924SDimitry Andric       std::string ObjArch = ObjForArch.getArchFlagName();
1239e6d15924SDimitry Andric       if (Arch != ObjArch)
1240e6d15924SDimitry Andric         continue;
1241e6d15924SDimitry Andric 
1242e6d15924SDimitry Andric       auto ArchiveOrErr = ObjForArch.getAsArchive();
1243e6d15924SDimitry Andric       if (!ArchiveOrErr) {
1244e6d15924SDimitry Andric         // If this is not an archive, try treating it as a regular object.
1245e6d15924SDimitry Andric         consumeError(ArchiveOrErr.takeError());
1246e6d15924SDimitry Andric         break;
1247e6d15924SDimitry Andric       }
1248e6d15924SDimitry Andric 
1249e6d15924SDimitry Andric       return BinaryCoverageReader::create(
1250344a3780SDimitry Andric           ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
12517fa27ce4SDimitry Andric           CompilationDir, BinaryIDs);
1252e6d15924SDimitry Andric     }
1253e6d15924SDimitry Andric   }
1254e6d15924SDimitry Andric 
1255e6d15924SDimitry Andric   // Load coverage out of archive members.
1256e6d15924SDimitry Andric   if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
1257e6d15924SDimitry Andric     Error Err = Error::success();
1258e6d15924SDimitry Andric     for (auto &Child : Ar->children(Err)) {
1259e6d15924SDimitry Andric       Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
1260e6d15924SDimitry Andric       if (!ChildBufOrErr)
1261e6d15924SDimitry Andric         return ChildBufOrErr.takeError();
1262e6d15924SDimitry Andric 
1263e6d15924SDimitry Andric       auto ChildReadersOrErr = BinaryCoverageReader::create(
12647fa27ce4SDimitry Andric           ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,
12657fa27ce4SDimitry Andric           BinaryIDs);
1266e6d15924SDimitry Andric       if (!ChildReadersOrErr)
1267e6d15924SDimitry Andric         return ChildReadersOrErr.takeError();
1268e6d15924SDimitry Andric       for (auto &Reader : ChildReadersOrErr.get())
1269e6d15924SDimitry Andric         Readers.push_back(std::move(Reader));
1270e6d15924SDimitry Andric     }
1271e6d15924SDimitry Andric     if (Err)
1272e6d15924SDimitry Andric       return std::move(Err);
1273e6d15924SDimitry Andric 
1274e6d15924SDimitry Andric     // Thin archives reference object files outside of the archive file, i.e.
1275e6d15924SDimitry Andric     // files which reside in memory not owned by the caller. Transfer ownership
1276e6d15924SDimitry Andric     // to the caller.
1277e6d15924SDimitry Andric     if (Ar->isThin())
1278e6d15924SDimitry Andric       for (auto &Buffer : Ar->takeThinBuffers())
1279e6d15924SDimitry Andric         ObjectFileBuffers.push_back(std::move(Buffer));
1280e6d15924SDimitry Andric 
1281e6d15924SDimitry Andric     return std::move(Readers);
1282e6d15924SDimitry Andric   }
1283e6d15924SDimitry Andric 
12847fa27ce4SDimitry Andric   object::BuildIDRef BinaryID;
12857fa27ce4SDimitry Andric   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,
12867fa27ce4SDimitry Andric                                       BinaryIDs ? &BinaryID : nullptr);
1287e6d15924SDimitry Andric   if (!ReaderOrErr)
1288e6d15924SDimitry Andric     return ReaderOrErr.takeError();
1289e6d15924SDimitry Andric   Readers.push_back(std::move(ReaderOrErr.get()));
12907fa27ce4SDimitry Andric   if (!BinaryID.empty())
12917fa27ce4SDimitry Andric     BinaryIDs->push_back(BinaryID);
1292e6d15924SDimitry Andric   return std::move(Readers);
129301095a5dSDimitry Andric }
129401095a5dSDimitry Andric 
readNextRecord(CoverageMappingRecord & Record)129501095a5dSDimitry Andric Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
129601095a5dSDimitry Andric   if (CurrentRecord >= MappingRecords.size())
129701095a5dSDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::eof);
129801095a5dSDimitry Andric 
129901095a5dSDimitry Andric   FunctionsFilenames.clear();
130001095a5dSDimitry Andric   Expressions.clear();
130101095a5dSDimitry Andric   MappingRegions.clear();
130201095a5dSDimitry Andric   auto &R = MappingRecords[CurrentRecord];
1303e3b55780SDimitry Andric   auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
1304344a3780SDimitry Andric   RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
1305344a3780SDimitry Andric                                   Expressions, MappingRegions);
130601095a5dSDimitry Andric   if (auto Err = Reader.read())
130701095a5dSDimitry Andric     return Err;
130801095a5dSDimitry Andric 
130901095a5dSDimitry Andric   Record.FunctionName = R.FunctionName;
131001095a5dSDimitry Andric   Record.FunctionHash = R.FunctionHash;
131101095a5dSDimitry Andric   Record.Filenames = FunctionsFilenames;
131201095a5dSDimitry Andric   Record.Expressions = Expressions;
131301095a5dSDimitry Andric   Record.MappingRegions = MappingRegions;
131401095a5dSDimitry Andric 
131501095a5dSDimitry Andric   ++CurrentRecord;
131601095a5dSDimitry Andric   return Error::success();
131701095a5dSDimitry Andric }
1318