xref: /openbsd-src/gnu/llvm/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file contains support for reading coverage mapping data for
1009467b48Spatrick // instrumentation based coverage.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
1509467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1609467b48Spatrick #include "llvm/ADT/DenseMap.h"
1709467b48Spatrick #include "llvm/ADT/STLExtras.h"
1809467b48Spatrick #include "llvm/ADT/SmallVector.h"
19097a140dSpatrick #include "llvm/ADT/Statistic.h"
2009467b48Spatrick #include "llvm/ADT/StringRef.h"
2109467b48Spatrick #include "llvm/ADT/Triple.h"
22*d415bd75Srobert #include "llvm/Object/Archive.h"
2309467b48Spatrick #include "llvm/Object/Binary.h"
2473471bf0Spatrick #include "llvm/Object/COFF.h"
2509467b48Spatrick #include "llvm/Object/Error.h"
2609467b48Spatrick #include "llvm/Object/MachOUniversal.h"
2709467b48Spatrick #include "llvm/Object/ObjectFile.h"
2809467b48Spatrick #include "llvm/ProfileData/InstrProf.h"
2909467b48Spatrick #include "llvm/Support/Casting.h"
30097a140dSpatrick #include "llvm/Support/Compression.h"
3109467b48Spatrick #include "llvm/Support/Debug.h"
3209467b48Spatrick #include "llvm/Support/Endian.h"
3309467b48Spatrick #include "llvm/Support/Error.h"
3409467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3509467b48Spatrick #include "llvm/Support/LEB128.h"
3609467b48Spatrick #include "llvm/Support/MathExtras.h"
3773471bf0Spatrick #include "llvm/Support/Path.h"
3809467b48Spatrick #include "llvm/Support/raw_ostream.h"
3909467b48Spatrick #include <vector>
4009467b48Spatrick 
4109467b48Spatrick using namespace llvm;
4209467b48Spatrick using namespace coverage;
4309467b48Spatrick using namespace object;
4409467b48Spatrick 
4509467b48Spatrick #define DEBUG_TYPE "coverage-mapping"
4609467b48Spatrick 
47097a140dSpatrick STATISTIC(CovMapNumRecords, "The # of coverage function records");
48097a140dSpatrick STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");
49097a140dSpatrick 
increment()5009467b48Spatrick void CoverageMappingIterator::increment() {
5109467b48Spatrick   if (ReadErr != coveragemap_error::success)
5209467b48Spatrick     return;
5309467b48Spatrick 
5409467b48Spatrick   // Check if all the records were read or if an error occurred while reading
5509467b48Spatrick   // the next record.
5609467b48Spatrick   if (auto E = Reader->readNextRecord(Record))
5709467b48Spatrick     handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
5809467b48Spatrick       if (CME.get() == coveragemap_error::eof)
5909467b48Spatrick         *this = CoverageMappingIterator();
6009467b48Spatrick       else
6109467b48Spatrick         ReadErr = CME.get();
6209467b48Spatrick     });
6309467b48Spatrick }
6409467b48Spatrick 
readULEB128(uint64_t & Result)6509467b48Spatrick Error RawCoverageReader::readULEB128(uint64_t &Result) {
6609467b48Spatrick   if (Data.empty())
6709467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::truncated);
6809467b48Spatrick   unsigned N = 0;
6909467b48Spatrick   Result = decodeULEB128(Data.bytes_begin(), &N);
7009467b48Spatrick   if (N > Data.size())
7109467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
7209467b48Spatrick   Data = Data.substr(N);
7309467b48Spatrick   return Error::success();
7409467b48Spatrick }
7509467b48Spatrick 
readIntMax(uint64_t & Result,uint64_t MaxPlus1)7609467b48Spatrick Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
7709467b48Spatrick   if (auto Err = readULEB128(Result))
7809467b48Spatrick     return Err;
7909467b48Spatrick   if (Result >= MaxPlus1)
8009467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
8109467b48Spatrick   return Error::success();
8209467b48Spatrick }
8309467b48Spatrick 
readSize(uint64_t & Result)8409467b48Spatrick Error RawCoverageReader::readSize(uint64_t &Result) {
8509467b48Spatrick   if (auto Err = readULEB128(Result))
8609467b48Spatrick     return Err;
8709467b48Spatrick   if (Result > Data.size())
8809467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
8909467b48Spatrick   return Error::success();
9009467b48Spatrick }
9109467b48Spatrick 
readString(StringRef & Result)9209467b48Spatrick Error RawCoverageReader::readString(StringRef &Result) {
9309467b48Spatrick   uint64_t Length;
9409467b48Spatrick   if (auto Err = readSize(Length))
9509467b48Spatrick     return Err;
9609467b48Spatrick   Result = Data.substr(0, Length);
9709467b48Spatrick   Data = Data.substr(Length);
9809467b48Spatrick   return Error::success();
9909467b48Spatrick }
10009467b48Spatrick 
read(CovMapVersion Version)10173471bf0Spatrick Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
10209467b48Spatrick   uint64_t NumFilenames;
10309467b48Spatrick   if (auto Err = readSize(NumFilenames))
10409467b48Spatrick     return Err;
105097a140dSpatrick   if (!NumFilenames)
106097a140dSpatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
107097a140dSpatrick 
108097a140dSpatrick   if (Version < CovMapVersion::Version4)
10973471bf0Spatrick     return readUncompressed(Version, NumFilenames);
110097a140dSpatrick 
111097a140dSpatrick   // The uncompressed length may exceed the size of the encoded filenames.
112097a140dSpatrick   // Skip size validation.
113097a140dSpatrick   uint64_t UncompressedLen;
114097a140dSpatrick   if (auto Err = readULEB128(UncompressedLen))
115097a140dSpatrick     return Err;
116097a140dSpatrick 
117097a140dSpatrick   uint64_t CompressedLen;
118097a140dSpatrick   if (auto Err = readSize(CompressedLen))
119097a140dSpatrick     return Err;
120097a140dSpatrick 
121097a140dSpatrick   if (CompressedLen > 0) {
122*d415bd75Srobert     if (!compression::zlib::isAvailable())
123097a140dSpatrick       return make_error<CoverageMapError>(
124097a140dSpatrick           coveragemap_error::decompression_failed);
125097a140dSpatrick 
12673471bf0Spatrick     // Allocate memory for the decompressed filenames.
127*d415bd75Srobert     SmallVector<uint8_t, 0> StorageBuf;
128097a140dSpatrick 
129097a140dSpatrick     // Read compressed filenames.
130097a140dSpatrick     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
131097a140dSpatrick     Data = Data.substr(CompressedLen);
132*d415bd75Srobert     auto Err = compression::zlib::decompress(
133*d415bd75Srobert         arrayRefFromStringRef(CompressedFilenames), StorageBuf,
134*d415bd75Srobert         UncompressedLen);
135097a140dSpatrick     if (Err) {
136097a140dSpatrick       consumeError(std::move(Err));
137097a140dSpatrick       return make_error<CoverageMapError>(
138097a140dSpatrick           coveragemap_error::decompression_failed);
139097a140dSpatrick     }
140097a140dSpatrick 
141*d415bd75Srobert     RawCoverageFilenamesReader Delegate(toStringRef(StorageBuf), Filenames,
14273471bf0Spatrick                                         CompilationDir);
14373471bf0Spatrick     return Delegate.readUncompressed(Version, NumFilenames);
144097a140dSpatrick   }
145097a140dSpatrick 
14673471bf0Spatrick   return readUncompressed(Version, NumFilenames);
147097a140dSpatrick }
148097a140dSpatrick 
readUncompressed(CovMapVersion Version,uint64_t NumFilenames)14973471bf0Spatrick Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
15073471bf0Spatrick                                                    uint64_t NumFilenames) {
151097a140dSpatrick   // Read uncompressed filenames.
15273471bf0Spatrick   if (Version < CovMapVersion::Version6) {
15309467b48Spatrick     for (size_t I = 0; I < NumFilenames; ++I) {
15409467b48Spatrick       StringRef Filename;
15509467b48Spatrick       if (auto Err = readString(Filename))
15609467b48Spatrick         return Err;
15773471bf0Spatrick       Filenames.push_back(Filename.str());
15873471bf0Spatrick     }
15973471bf0Spatrick   } else {
16073471bf0Spatrick     StringRef CWD;
16173471bf0Spatrick     if (auto Err = readString(CWD))
16273471bf0Spatrick       return Err;
16373471bf0Spatrick     Filenames.push_back(CWD.str());
16473471bf0Spatrick 
16573471bf0Spatrick     for (size_t I = 1; I < NumFilenames; ++I) {
16673471bf0Spatrick       StringRef Filename;
16773471bf0Spatrick       if (auto Err = readString(Filename))
16873471bf0Spatrick         return Err;
16973471bf0Spatrick       if (sys::path::is_absolute(Filename)) {
17073471bf0Spatrick         Filenames.push_back(Filename.str());
17173471bf0Spatrick       } else {
17273471bf0Spatrick         SmallString<256> P;
17373471bf0Spatrick         if (!CompilationDir.empty())
17473471bf0Spatrick           P.assign(CompilationDir);
17573471bf0Spatrick         else
17673471bf0Spatrick           P.assign(CWD);
17773471bf0Spatrick         llvm::sys::path::append(P, Filename);
178*d415bd75Srobert         sys::path::remove_dots(P, /*remove_dot_dot=*/true);
179*d415bd75Srobert         Filenames.push_back(static_cast<std::string>(P.str()));
18073471bf0Spatrick       }
18173471bf0Spatrick     }
18209467b48Spatrick   }
18309467b48Spatrick   return Error::success();
18409467b48Spatrick }
18509467b48Spatrick 
decodeCounter(unsigned Value,Counter & C)18609467b48Spatrick Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
18709467b48Spatrick   auto Tag = Value & Counter::EncodingTagMask;
18809467b48Spatrick   switch (Tag) {
18909467b48Spatrick   case Counter::Zero:
19009467b48Spatrick     C = Counter::getZero();
19109467b48Spatrick     return Error::success();
19209467b48Spatrick   case Counter::CounterValueReference:
19309467b48Spatrick     C = Counter::getCounter(Value >> Counter::EncodingTagBits);
19409467b48Spatrick     return Error::success();
19509467b48Spatrick   default:
19609467b48Spatrick     break;
19709467b48Spatrick   }
19809467b48Spatrick   Tag -= Counter::Expression;
19909467b48Spatrick   switch (Tag) {
20009467b48Spatrick   case CounterExpression::Subtract:
20109467b48Spatrick   case CounterExpression::Add: {
20209467b48Spatrick     auto ID = Value >> Counter::EncodingTagBits;
20309467b48Spatrick     if (ID >= Expressions.size())
20409467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
20509467b48Spatrick     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
20609467b48Spatrick     C = Counter::getExpression(ID);
20709467b48Spatrick     break;
20809467b48Spatrick   }
20909467b48Spatrick   default:
21009467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
21109467b48Spatrick   }
21209467b48Spatrick   return Error::success();
21309467b48Spatrick }
21409467b48Spatrick 
readCounter(Counter & C)21509467b48Spatrick Error RawCoverageMappingReader::readCounter(Counter &C) {
21609467b48Spatrick   uint64_t EncodedCounter;
21709467b48Spatrick   if (auto Err =
21809467b48Spatrick           readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
21909467b48Spatrick     return Err;
22009467b48Spatrick   if (auto Err = decodeCounter(EncodedCounter, C))
22109467b48Spatrick     return Err;
22209467b48Spatrick   return Error::success();
22309467b48Spatrick }
22409467b48Spatrick 
22509467b48Spatrick static const unsigned EncodingExpansionRegionBit = 1
22609467b48Spatrick                                                    << Counter::EncodingTagBits;
22709467b48Spatrick 
22809467b48Spatrick /// Read the sub-array of regions for the given inferred file id.
22909467b48Spatrick /// \param NumFileIDs the number of file ids that are defined for this
23009467b48Spatrick /// function.
readMappingRegionsSubArray(std::vector<CounterMappingRegion> & MappingRegions,unsigned InferredFileID,size_t NumFileIDs)23109467b48Spatrick Error RawCoverageMappingReader::readMappingRegionsSubArray(
23209467b48Spatrick     std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
23309467b48Spatrick     size_t NumFileIDs) {
23409467b48Spatrick   uint64_t NumRegions;
23509467b48Spatrick   if (auto Err = readSize(NumRegions))
23609467b48Spatrick     return Err;
23709467b48Spatrick   unsigned LineStart = 0;
23809467b48Spatrick   for (size_t I = 0; I < NumRegions; ++I) {
23973471bf0Spatrick     Counter C, C2;
24009467b48Spatrick     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
24109467b48Spatrick 
24209467b48Spatrick     // Read the combined counter + region kind.
24309467b48Spatrick     uint64_t EncodedCounterAndRegion;
24409467b48Spatrick     if (auto Err = readIntMax(EncodedCounterAndRegion,
24509467b48Spatrick                               std::numeric_limits<unsigned>::max()))
24609467b48Spatrick       return Err;
24709467b48Spatrick     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
24809467b48Spatrick     uint64_t ExpandedFileID = 0;
24973471bf0Spatrick 
25073471bf0Spatrick     // If Tag does not represent a ZeroCounter, then it is understood to refer
25173471bf0Spatrick     // to a counter or counter expression with region kind assumed to be
25273471bf0Spatrick     // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
25373471bf0Spatrick     // referenced counter or counter expression (and nothing else).
25473471bf0Spatrick     //
25573471bf0Spatrick     // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
25673471bf0Spatrick     // then EncodedCounterAndRegion is interpreted to represent an
25773471bf0Spatrick     // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
25873471bf0Spatrick     // interpreted to refer to a specific region kind, after which additional
25973471bf0Spatrick     // fields may be read (e.g. BranchRegions have two encoded counters that
26073471bf0Spatrick     // follow an encoded region kind value).
26109467b48Spatrick     if (Tag != Counter::Zero) {
26209467b48Spatrick       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
26309467b48Spatrick         return Err;
26409467b48Spatrick     } else {
26509467b48Spatrick       // Is it an expansion region?
26609467b48Spatrick       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
26709467b48Spatrick         Kind = CounterMappingRegion::ExpansionRegion;
26809467b48Spatrick         ExpandedFileID = EncodedCounterAndRegion >>
26909467b48Spatrick                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
27009467b48Spatrick         if (ExpandedFileID >= NumFileIDs)
27109467b48Spatrick           return make_error<CoverageMapError>(coveragemap_error::malformed);
27209467b48Spatrick       } else {
27309467b48Spatrick         switch (EncodedCounterAndRegion >>
27409467b48Spatrick                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
27509467b48Spatrick         case CounterMappingRegion::CodeRegion:
27609467b48Spatrick           // Don't do anything when we have a code region with a zero counter.
27709467b48Spatrick           break;
27809467b48Spatrick         case CounterMappingRegion::SkippedRegion:
27909467b48Spatrick           Kind = CounterMappingRegion::SkippedRegion;
28009467b48Spatrick           break;
28173471bf0Spatrick         case CounterMappingRegion::BranchRegion:
28273471bf0Spatrick           // For a Branch Region, read two successive counters.
28373471bf0Spatrick           Kind = CounterMappingRegion::BranchRegion;
28473471bf0Spatrick           if (auto Err = readCounter(C))
28573471bf0Spatrick             return Err;
28673471bf0Spatrick           if (auto Err = readCounter(C2))
28773471bf0Spatrick             return Err;
28873471bf0Spatrick           break;
28909467b48Spatrick         default:
29009467b48Spatrick           return make_error<CoverageMapError>(coveragemap_error::malformed);
29109467b48Spatrick         }
29209467b48Spatrick       }
29309467b48Spatrick     }
29409467b48Spatrick 
29509467b48Spatrick     // Read the source range.
29609467b48Spatrick     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
29709467b48Spatrick     if (auto Err =
29809467b48Spatrick             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
29909467b48Spatrick       return Err;
30009467b48Spatrick     if (auto Err = readULEB128(ColumnStart))
30109467b48Spatrick       return Err;
30209467b48Spatrick     if (ColumnStart > std::numeric_limits<unsigned>::max())
30309467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
30409467b48Spatrick     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
30509467b48Spatrick       return Err;
30609467b48Spatrick     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
30709467b48Spatrick       return Err;
30809467b48Spatrick     LineStart += LineStartDelta;
30909467b48Spatrick 
31009467b48Spatrick     // If the high bit of ColumnEnd is set, this is a gap region.
31109467b48Spatrick     if (ColumnEnd & (1U << 31)) {
31209467b48Spatrick       Kind = CounterMappingRegion::GapRegion;
31309467b48Spatrick       ColumnEnd &= ~(1U << 31);
31409467b48Spatrick     }
31509467b48Spatrick 
31609467b48Spatrick     // Adjust the column locations for the empty regions that are supposed to
31709467b48Spatrick     // cover whole lines. Those regions should be encoded with the
31809467b48Spatrick     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
31909467b48Spatrick     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
32009467b48Spatrick     // we set the column range to (0 -> 0) to ensure that the column start and
32109467b48Spatrick     // column end take up one byte each.
32209467b48Spatrick     // The std::numeric_limits<unsigned>::max() is used to represent a column
32309467b48Spatrick     // position at the end of the line without knowing the length of that line.
32409467b48Spatrick     if (ColumnStart == 0 && ColumnEnd == 0) {
32509467b48Spatrick       ColumnStart = 1;
32609467b48Spatrick       ColumnEnd = std::numeric_limits<unsigned>::max();
32709467b48Spatrick     }
32809467b48Spatrick 
32909467b48Spatrick     LLVM_DEBUG({
33009467b48Spatrick       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
33109467b48Spatrick              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
33209467b48Spatrick              << ColumnEnd << ", ";
33309467b48Spatrick       if (Kind == CounterMappingRegion::ExpansionRegion)
33409467b48Spatrick         dbgs() << "Expands to file " << ExpandedFileID;
33509467b48Spatrick       else
33609467b48Spatrick         CounterMappingContext(Expressions).dump(C, dbgs());
33709467b48Spatrick       dbgs() << "\n";
33809467b48Spatrick     });
33909467b48Spatrick 
34073471bf0Spatrick     auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID,
34109467b48Spatrick                                     LineStart, ColumnStart,
34209467b48Spatrick                                     LineStart + NumLines, ColumnEnd, Kind);
34309467b48Spatrick     if (CMR.startLoc() > CMR.endLoc())
34409467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
34509467b48Spatrick     MappingRegions.push_back(CMR);
34609467b48Spatrick   }
34709467b48Spatrick   return Error::success();
34809467b48Spatrick }
34909467b48Spatrick 
read()35009467b48Spatrick Error RawCoverageMappingReader::read() {
35109467b48Spatrick   // Read the virtual file mapping.
35209467b48Spatrick   SmallVector<unsigned, 8> VirtualFileMapping;
35309467b48Spatrick   uint64_t NumFileMappings;
35409467b48Spatrick   if (auto Err = readSize(NumFileMappings))
35509467b48Spatrick     return Err;
35609467b48Spatrick   for (size_t I = 0; I < NumFileMappings; ++I) {
35709467b48Spatrick     uint64_t FilenameIndex;
35809467b48Spatrick     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
35909467b48Spatrick       return Err;
36009467b48Spatrick     VirtualFileMapping.push_back(FilenameIndex);
36109467b48Spatrick   }
36209467b48Spatrick 
36309467b48Spatrick   // Construct the files using unique filenames and virtual file mapping.
36409467b48Spatrick   for (auto I : VirtualFileMapping) {
36509467b48Spatrick     Filenames.push_back(TranslationUnitFilenames[I]);
36609467b48Spatrick   }
36709467b48Spatrick 
36809467b48Spatrick   // Read the expressions.
36909467b48Spatrick   uint64_t NumExpressions;
37009467b48Spatrick   if (auto Err = readSize(NumExpressions))
37109467b48Spatrick     return Err;
37209467b48Spatrick   // Create an array of dummy expressions that get the proper counters
37309467b48Spatrick   // when the expressions are read, and the proper kinds when the counters
37409467b48Spatrick   // are decoded.
37509467b48Spatrick   Expressions.resize(
37609467b48Spatrick       NumExpressions,
37709467b48Spatrick       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
37809467b48Spatrick   for (size_t I = 0; I < NumExpressions; ++I) {
37909467b48Spatrick     if (auto Err = readCounter(Expressions[I].LHS))
38009467b48Spatrick       return Err;
38109467b48Spatrick     if (auto Err = readCounter(Expressions[I].RHS))
38209467b48Spatrick       return Err;
38309467b48Spatrick   }
38409467b48Spatrick 
38509467b48Spatrick   // Read the mapping regions sub-arrays.
38609467b48Spatrick   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
38709467b48Spatrick        InferredFileID < S; ++InferredFileID) {
38809467b48Spatrick     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
38909467b48Spatrick                                               VirtualFileMapping.size()))
39009467b48Spatrick       return Err;
39109467b48Spatrick   }
39209467b48Spatrick 
39309467b48Spatrick   // Set the counters for the expansion regions.
39409467b48Spatrick   // i.e. Counter of expansion region = counter of the first region
39509467b48Spatrick   // from the expanded file.
39609467b48Spatrick   // Perform multiple passes to correctly propagate the counters through
39709467b48Spatrick   // all the nested expansion regions.
39809467b48Spatrick   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
39909467b48Spatrick   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
40009467b48Spatrick   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
40109467b48Spatrick     for (auto &R : MappingRegions) {
40209467b48Spatrick       if (R.Kind != CounterMappingRegion::ExpansionRegion)
40309467b48Spatrick         continue;
40409467b48Spatrick       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
40509467b48Spatrick       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
40609467b48Spatrick     }
40709467b48Spatrick     for (auto &R : MappingRegions) {
40809467b48Spatrick       if (FileIDExpansionRegionMapping[R.FileID]) {
40909467b48Spatrick         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
41009467b48Spatrick         FileIDExpansionRegionMapping[R.FileID] = nullptr;
41109467b48Spatrick       }
41209467b48Spatrick     }
41309467b48Spatrick   }
41409467b48Spatrick 
41509467b48Spatrick   return Error::success();
41609467b48Spatrick }
41709467b48Spatrick 
isDummy()41809467b48Spatrick Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
41909467b48Spatrick   // A dummy coverage mapping data consists of just one region with zero count.
42009467b48Spatrick   uint64_t NumFileMappings;
42109467b48Spatrick   if (Error Err = readSize(NumFileMappings))
42209467b48Spatrick     return std::move(Err);
42309467b48Spatrick   if (NumFileMappings != 1)
42409467b48Spatrick     return false;
42509467b48Spatrick   // We don't expect any specific value for the filename index, just skip it.
42609467b48Spatrick   uint64_t FilenameIndex;
42709467b48Spatrick   if (Error Err =
42809467b48Spatrick           readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
42909467b48Spatrick     return std::move(Err);
43009467b48Spatrick   uint64_t NumExpressions;
43109467b48Spatrick   if (Error Err = readSize(NumExpressions))
43209467b48Spatrick     return std::move(Err);
43309467b48Spatrick   if (NumExpressions != 0)
43409467b48Spatrick     return false;
43509467b48Spatrick   uint64_t NumRegions;
43609467b48Spatrick   if (Error Err = readSize(NumRegions))
43709467b48Spatrick     return std::move(Err);
43809467b48Spatrick   if (NumRegions != 1)
43909467b48Spatrick     return false;
44009467b48Spatrick   uint64_t EncodedCounterAndRegion;
44109467b48Spatrick   if (Error Err = readIntMax(EncodedCounterAndRegion,
44209467b48Spatrick                              std::numeric_limits<unsigned>::max()))
44309467b48Spatrick     return std::move(Err);
44409467b48Spatrick   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
44509467b48Spatrick   return Tag == Counter::Zero;
44609467b48Spatrick }
44709467b48Spatrick 
create(SectionRef & Section)44809467b48Spatrick Error InstrProfSymtab::create(SectionRef &Section) {
44909467b48Spatrick   Expected<StringRef> DataOrErr = Section.getContents();
45009467b48Spatrick   if (!DataOrErr)
45109467b48Spatrick     return DataOrErr.takeError();
45209467b48Spatrick   Data = *DataOrErr;
45309467b48Spatrick   Address = Section.getAddress();
45409467b48Spatrick 
45509467b48Spatrick   // If this is a linked PE/COFF file, then we have to skip over the null byte
45609467b48Spatrick   // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
45709467b48Spatrick   const ObjectFile *Obj = Section.getObject();
45809467b48Spatrick   if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
45909467b48Spatrick     Data = Data.drop_front(1);
46009467b48Spatrick 
46109467b48Spatrick   return Error::success();
46209467b48Spatrick }
46309467b48Spatrick 
getFuncName(uint64_t Pointer,size_t Size)46409467b48Spatrick StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
46509467b48Spatrick   if (Pointer < Address)
46609467b48Spatrick     return StringRef();
46709467b48Spatrick   auto Offset = Pointer - Address;
46809467b48Spatrick   if (Offset + Size > Data.size())
46909467b48Spatrick     return StringRef();
47009467b48Spatrick   return Data.substr(Pointer - Address, Size);
47109467b48Spatrick }
47209467b48Spatrick 
47309467b48Spatrick // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
isCoverageMappingDummy(uint64_t Hash,StringRef Mapping)47409467b48Spatrick static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
47509467b48Spatrick   // The hash value of dummy mapping records is always zero.
47609467b48Spatrick   if (Hash)
47709467b48Spatrick     return false;
47809467b48Spatrick   return RawCoverageMappingDummyChecker(Mapping).isDummy();
47909467b48Spatrick }
48009467b48Spatrick 
481097a140dSpatrick /// A range of filename indices. Used to specify the location of a batch of
482097a140dSpatrick /// filenames in a vector-like container.
483097a140dSpatrick struct FilenameRange {
484097a140dSpatrick   unsigned StartingIndex;
485097a140dSpatrick   unsigned Length;
486097a140dSpatrick 
FilenameRangeFilenameRange487097a140dSpatrick   FilenameRange(unsigned StartingIndex, unsigned Length)
488097a140dSpatrick       : StartingIndex(StartingIndex), Length(Length) {}
489097a140dSpatrick 
markInvalidFilenameRange490097a140dSpatrick   void markInvalid() { Length = 0; }
isInvalidFilenameRange491097a140dSpatrick   bool isInvalid() const { return Length == 0; }
492097a140dSpatrick };
493097a140dSpatrick 
49409467b48Spatrick namespace {
49509467b48Spatrick 
496097a140dSpatrick /// The interface to read coverage mapping function records for a module.
49709467b48Spatrick struct CovMapFuncRecordReader {
49809467b48Spatrick   virtual ~CovMapFuncRecordReader() = default;
49909467b48Spatrick 
500097a140dSpatrick   // Read a coverage header.
50109467b48Spatrick   //
502097a140dSpatrick   // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
50309467b48Spatrick   // mapping data associated with the module.
50409467b48Spatrick   //
505097a140dSpatrick   // Returns a pointer to the next \c CovHeader if it exists, or to an address
506097a140dSpatrick   // greater than \p CovEnd if not.
50773471bf0Spatrick   virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
50873471bf0Spatrick                                                     const char *CovBufEnd) = 0;
509097a140dSpatrick 
510097a140dSpatrick   // Read function records.
511097a140dSpatrick   //
512097a140dSpatrick   // \p FuncRecBuf points to the buffer containing a batch of function records.
513097a140dSpatrick   // \p FuncRecBufEnd points past the end of the batch of records.
514097a140dSpatrick   //
515097a140dSpatrick   // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
516097a140dSpatrick   // associated with the function records. It is unused in Version4.
517097a140dSpatrick   //
518097a140dSpatrick   // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
519097a140dSpatrick   // mappings associated with the function records. It is unused in Version4.
520*d415bd75Srobert   virtual Error
521*d415bd75Srobert   readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
522*d415bd75Srobert                       std::optional<FilenameRange> OutOfLineFileRange,
523097a140dSpatrick                       const char *OutOfLineMappingBuf,
524097a140dSpatrick                       const char *OutOfLineMappingBufEnd) = 0;
52509467b48Spatrick 
52609467b48Spatrick   template <class IntPtrT, support::endianness Endian>
52709467b48Spatrick   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
52809467b48Spatrick   get(CovMapVersion Version, InstrProfSymtab &P,
52973471bf0Spatrick       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
53073471bf0Spatrick       std::vector<std::string> &F);
53109467b48Spatrick };
53209467b48Spatrick 
53309467b48Spatrick // A class for reading coverage mapping function records for a module.
53409467b48Spatrick template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
53509467b48Spatrick class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
53609467b48Spatrick   using FuncRecordType =
53709467b48Spatrick       typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
53809467b48Spatrick   using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
53909467b48Spatrick 
54009467b48Spatrick   // Maps function's name references to the indexes of their records
54109467b48Spatrick   // in \c Records.
54209467b48Spatrick   DenseMap<NameRefType, size_t> FunctionRecords;
54309467b48Spatrick   InstrProfSymtab &ProfileNames;
54473471bf0Spatrick   StringRef CompilationDir;
54573471bf0Spatrick   std::vector<std::string> &Filenames;
54609467b48Spatrick   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
54709467b48Spatrick 
548097a140dSpatrick   // Maps a hash of the filenames in a TU to a \c FileRange. The range
549097a140dSpatrick   // specifies the location of the hashed filenames in \c Filenames.
550097a140dSpatrick   DenseMap<uint64_t, FilenameRange> FileRangeMap;
551097a140dSpatrick 
55209467b48Spatrick   // Add the record to the collection if we don't already have a record that
55309467b48Spatrick   // points to the same function name. This is useful to ignore the redundant
55409467b48Spatrick   // records for the functions with ODR linkage.
55509467b48Spatrick   // In addition, prefer records with real coverage mapping data to dummy
55609467b48Spatrick   // records, which were emitted for inline functions which were seen but
55709467b48Spatrick   // not used in the corresponding translation unit.
insertFunctionRecordIfNeeded(const FuncRecordType * CFR,StringRef Mapping,FilenameRange FileRange)55809467b48Spatrick   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
559097a140dSpatrick                                      StringRef Mapping,
560097a140dSpatrick                                      FilenameRange FileRange) {
561097a140dSpatrick     ++CovMapNumRecords;
56209467b48Spatrick     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
56309467b48Spatrick     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
56409467b48Spatrick     auto InsertResult =
56509467b48Spatrick         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
56609467b48Spatrick     if (InsertResult.second) {
56709467b48Spatrick       StringRef FuncName;
56809467b48Spatrick       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
56909467b48Spatrick         return Err;
57009467b48Spatrick       if (FuncName.empty())
571*d415bd75Srobert         return make_error<InstrProfError>(instrprof_error::malformed,
572*d415bd75Srobert                                           "function name is empty");
573097a140dSpatrick       ++CovMapNumUsedRecords;
574097a140dSpatrick       Records.emplace_back(Version, FuncName, FuncHash, Mapping,
575097a140dSpatrick                            FileRange.StartingIndex, FileRange.Length);
57609467b48Spatrick       return Error::success();
57709467b48Spatrick     }
57809467b48Spatrick     // Update the existing record if it's a dummy and the new record is real.
57909467b48Spatrick     size_t OldRecordIndex = InsertResult.first->second;
58009467b48Spatrick     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
58109467b48Spatrick         Records[OldRecordIndex];
58209467b48Spatrick     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
58309467b48Spatrick         OldRecord.FunctionHash, OldRecord.CoverageMapping);
58409467b48Spatrick     if (Error Err = OldIsDummyExpected.takeError())
58509467b48Spatrick       return Err;
58609467b48Spatrick     if (!*OldIsDummyExpected)
58709467b48Spatrick       return Error::success();
58809467b48Spatrick     Expected<bool> NewIsDummyExpected =
58909467b48Spatrick         isCoverageMappingDummy(FuncHash, Mapping);
59009467b48Spatrick     if (Error Err = NewIsDummyExpected.takeError())
59109467b48Spatrick       return Err;
59209467b48Spatrick     if (*NewIsDummyExpected)
59309467b48Spatrick       return Error::success();
594097a140dSpatrick     ++CovMapNumUsedRecords;
59509467b48Spatrick     OldRecord.FunctionHash = FuncHash;
59609467b48Spatrick     OldRecord.CoverageMapping = Mapping;
597097a140dSpatrick     OldRecord.FilenamesBegin = FileRange.StartingIndex;
598097a140dSpatrick     OldRecord.FilenamesSize = FileRange.Length;
59909467b48Spatrick     return Error::success();
60009467b48Spatrick   }
60109467b48Spatrick 
60209467b48Spatrick public:
VersionedCovMapFuncRecordReader(InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,StringRef D,std::vector<std::string> & F)60309467b48Spatrick   VersionedCovMapFuncRecordReader(
60409467b48Spatrick       InstrProfSymtab &P,
60573471bf0Spatrick       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
60673471bf0Spatrick       std::vector<std::string> &F)
60773471bf0Spatrick       : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}
60809467b48Spatrick 
60909467b48Spatrick   ~VersionedCovMapFuncRecordReader() override = default;
61009467b48Spatrick 
readCoverageHeader(const char * CovBuf,const char * CovBufEnd)61173471bf0Spatrick   Expected<const char *> readCoverageHeader(const char *CovBuf,
61273471bf0Spatrick                                             const char *CovBufEnd) override {
61309467b48Spatrick     using namespace support;
61409467b48Spatrick 
615097a140dSpatrick     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
61609467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
617097a140dSpatrick     auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
61809467b48Spatrick     uint32_t NRecords = CovHeader->getNRecords<Endian>();
61909467b48Spatrick     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
62009467b48Spatrick     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
62109467b48Spatrick     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
622097a140dSpatrick     CovBuf = reinterpret_cast<const char *>(CovHeader + 1);
62309467b48Spatrick 
62409467b48Spatrick     // Skip past the function records, saving the start and end for later.
625097a140dSpatrick     // This is a no-op in Version4 (function records are read after all headers
626097a140dSpatrick     // are read).
627097a140dSpatrick     const char *FuncRecBuf = nullptr;
628097a140dSpatrick     const char *FuncRecBufEnd = nullptr;
629097a140dSpatrick     if (Version < CovMapVersion::Version4)
630097a140dSpatrick       FuncRecBuf = CovBuf;
631097a140dSpatrick     CovBuf += NRecords * sizeof(FuncRecordType);
632097a140dSpatrick     if (Version < CovMapVersion::Version4)
633097a140dSpatrick       FuncRecBufEnd = CovBuf;
63409467b48Spatrick 
63509467b48Spatrick     // Get the filenames.
636097a140dSpatrick     if (CovBuf + FilenamesSize > CovBufEnd)
63709467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
63809467b48Spatrick     size_t FilenamesBegin = Filenames.size();
639097a140dSpatrick     StringRef FilenameRegion(CovBuf, FilenamesSize);
64073471bf0Spatrick     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
64173471bf0Spatrick                                       CompilationDir);
64273471bf0Spatrick     if (auto Err = Reader.read(Version))
64309467b48Spatrick       return std::move(Err);
644097a140dSpatrick     CovBuf += FilenamesSize;
645097a140dSpatrick     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
646097a140dSpatrick 
64773471bf0Spatrick     if (Version >= CovMapVersion::Version4) {
648097a140dSpatrick       // Map a hash of the filenames region to the filename range associated
649097a140dSpatrick       // with this coverage header.
650097a140dSpatrick       int64_t FilenamesRef =
651097a140dSpatrick           llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
652097a140dSpatrick       auto Insert =
653097a140dSpatrick           FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
654097a140dSpatrick       if (!Insert.second) {
655097a140dSpatrick         // The same filenames ref was encountered twice. It's possible that
656097a140dSpatrick         // the associated filenames are the same.
657097a140dSpatrick         auto It = Filenames.begin();
658097a140dSpatrick         FilenameRange &OrigRange = Insert.first->getSecond();
659097a140dSpatrick         if (std::equal(It + OrigRange.StartingIndex,
660097a140dSpatrick                        It + OrigRange.StartingIndex + OrigRange.Length,
661097a140dSpatrick                        It + FileRange.StartingIndex,
662097a140dSpatrick                        It + FileRange.StartingIndex + FileRange.Length))
663097a140dSpatrick           // Map the new range to the original one.
664097a140dSpatrick           FileRange = OrigRange;
665097a140dSpatrick         else
666097a140dSpatrick           // This is a hash collision. Mark the filenames ref invalid.
667097a140dSpatrick           OrigRange.markInvalid();
668097a140dSpatrick       }
669097a140dSpatrick     }
67009467b48Spatrick 
67109467b48Spatrick     // We'll read the coverage mapping records in the loop below.
672097a140dSpatrick     // This is a no-op in Version4 (coverage mappings are not affixed to the
673097a140dSpatrick     // coverage header).
674097a140dSpatrick     const char *MappingBuf = CovBuf;
67573471bf0Spatrick     if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
67609467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
677097a140dSpatrick     CovBuf += CoverageSize;
678097a140dSpatrick     const char *MappingEnd = CovBuf;
679097a140dSpatrick 
680097a140dSpatrick     if (CovBuf > CovBufEnd)
681097a140dSpatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
682097a140dSpatrick 
683097a140dSpatrick     if (Version < CovMapVersion::Version4) {
684097a140dSpatrick       // Read each function record.
685097a140dSpatrick       if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
686097a140dSpatrick                                         MappingBuf, MappingEnd))
687097a140dSpatrick         return std::move(E);
688097a140dSpatrick     }
689097a140dSpatrick 
69009467b48Spatrick     // Each coverage map has an alignment of 8, so we need to adjust alignment
69109467b48Spatrick     // before reading the next map.
692097a140dSpatrick     CovBuf += offsetToAlignedAddr(CovBuf, Align(8));
69309467b48Spatrick 
694097a140dSpatrick     return CovBuf;
69509467b48Spatrick   }
696097a140dSpatrick 
readFunctionRecords(const char * FuncRecBuf,const char * FuncRecBufEnd,std::optional<FilenameRange> OutOfLineFileRange,const char * OutOfLineMappingBuf,const char * OutOfLineMappingBufEnd)697097a140dSpatrick   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
698*d415bd75Srobert                             std::optional<FilenameRange> OutOfLineFileRange,
699097a140dSpatrick                             const char *OutOfLineMappingBuf,
700097a140dSpatrick                             const char *OutOfLineMappingBufEnd) override {
701097a140dSpatrick     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
702097a140dSpatrick     while ((const char *)CFR < FuncRecBufEnd) {
703097a140dSpatrick       // Validate the length of the coverage mapping for this function.
704097a140dSpatrick       const char *NextMappingBuf;
705097a140dSpatrick       const FuncRecordType *NextCFR;
706097a140dSpatrick       std::tie(NextMappingBuf, NextCFR) =
707097a140dSpatrick           CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
708097a140dSpatrick       if (Version < CovMapVersion::Version4)
709097a140dSpatrick         if (NextMappingBuf > OutOfLineMappingBufEnd)
710097a140dSpatrick           return make_error<CoverageMapError>(coveragemap_error::malformed);
711097a140dSpatrick 
712097a140dSpatrick       // Look up the set of filenames associated with this function record.
713*d415bd75Srobert       std::optional<FilenameRange> FileRange;
714097a140dSpatrick       if (Version < CovMapVersion::Version4) {
715097a140dSpatrick         FileRange = OutOfLineFileRange;
716097a140dSpatrick       } else {
717097a140dSpatrick         uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
718097a140dSpatrick         auto It = FileRangeMap.find(FilenamesRef);
719097a140dSpatrick         if (It == FileRangeMap.end())
720097a140dSpatrick           return make_error<CoverageMapError>(coveragemap_error::malformed);
721097a140dSpatrick         else
722097a140dSpatrick           FileRange = It->getSecond();
723097a140dSpatrick       }
724097a140dSpatrick 
725097a140dSpatrick       // Now, read the coverage data.
726097a140dSpatrick       if (FileRange && !FileRange->isInvalid()) {
727097a140dSpatrick         StringRef Mapping =
728097a140dSpatrick             CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
72973471bf0Spatrick         if (Version >= CovMapVersion::Version4 &&
730097a140dSpatrick             Mapping.data() + Mapping.size() > FuncRecBufEnd)
731097a140dSpatrick           return make_error<CoverageMapError>(coveragemap_error::malformed);
732097a140dSpatrick         if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
733097a140dSpatrick           return Err;
734097a140dSpatrick       }
735097a140dSpatrick 
736097a140dSpatrick       std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
737097a140dSpatrick     }
738097a140dSpatrick     return Error::success();
73909467b48Spatrick   }
74009467b48Spatrick };
74109467b48Spatrick 
74209467b48Spatrick } // end anonymous namespace
74309467b48Spatrick 
74409467b48Spatrick template <class IntPtrT, support::endianness Endian>
get(CovMapVersion Version,InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,StringRef D,std::vector<std::string> & F)74509467b48Spatrick Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
74609467b48Spatrick     CovMapVersion Version, InstrProfSymtab &P,
74773471bf0Spatrick     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
74873471bf0Spatrick     std::vector<std::string> &F) {
74909467b48Spatrick   using namespace coverage;
75009467b48Spatrick 
75109467b48Spatrick   switch (Version) {
75209467b48Spatrick   case CovMapVersion::Version1:
75309467b48Spatrick     return std::make_unique<VersionedCovMapFuncRecordReader<
75473471bf0Spatrick         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
75509467b48Spatrick   case CovMapVersion::Version2:
75609467b48Spatrick   case CovMapVersion::Version3:
757097a140dSpatrick   case CovMapVersion::Version4:
75873471bf0Spatrick   case CovMapVersion::Version5:
75973471bf0Spatrick   case CovMapVersion::Version6:
76009467b48Spatrick     // Decompress the name data.
76109467b48Spatrick     if (Error E = P.create(P.getNameData()))
76209467b48Spatrick       return std::move(E);
76309467b48Spatrick     if (Version == CovMapVersion::Version2)
76409467b48Spatrick       return std::make_unique<VersionedCovMapFuncRecordReader<
76573471bf0Spatrick           CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
766097a140dSpatrick     else if (Version == CovMapVersion::Version3)
76709467b48Spatrick       return std::make_unique<VersionedCovMapFuncRecordReader<
76873471bf0Spatrick           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
769097a140dSpatrick     else if (Version == CovMapVersion::Version4)
770097a140dSpatrick       return std::make_unique<VersionedCovMapFuncRecordReader<
77173471bf0Spatrick           CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
77273471bf0Spatrick     else if (Version == CovMapVersion::Version5)
77373471bf0Spatrick       return std::make_unique<VersionedCovMapFuncRecordReader<
77473471bf0Spatrick           CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
77573471bf0Spatrick     else if (Version == CovMapVersion::Version6)
77673471bf0Spatrick       return std::make_unique<VersionedCovMapFuncRecordReader<
77773471bf0Spatrick           CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
77809467b48Spatrick   }
77909467b48Spatrick   llvm_unreachable("Unsupported version");
78009467b48Spatrick }
78109467b48Spatrick 
78209467b48Spatrick template <typename T, support::endianness Endian>
readCoverageMappingData(InstrProfSymtab & ProfileNames,StringRef CovMap,StringRef FuncRecords,std::vector<BinaryCoverageReader::ProfileMappingRecord> & Records,StringRef CompilationDir,std::vector<std::string> & Filenames)78309467b48Spatrick static Error readCoverageMappingData(
784097a140dSpatrick     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
78509467b48Spatrick     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
78673471bf0Spatrick     StringRef CompilationDir, std::vector<std::string> &Filenames) {
78709467b48Spatrick   using namespace coverage;
78809467b48Spatrick 
78909467b48Spatrick   // Read the records in the coverage data section.
79009467b48Spatrick   auto CovHeader =
791097a140dSpatrick       reinterpret_cast<const CovMapHeader *>(CovMap.data());
79209467b48Spatrick   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
79309467b48Spatrick   if (Version > CovMapVersion::CurrentVersion)
79409467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
79509467b48Spatrick   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
79609467b48Spatrick       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
79773471bf0Spatrick                                              CompilationDir, Filenames);
79809467b48Spatrick   if (Error E = ReaderExpected.takeError())
79909467b48Spatrick     return E;
80009467b48Spatrick   auto Reader = std::move(ReaderExpected.get());
801097a140dSpatrick   const char *CovBuf = CovMap.data();
802097a140dSpatrick   const char *CovBufEnd = CovBuf + CovMap.size();
803097a140dSpatrick   const char *FuncRecBuf = FuncRecords.data();
804097a140dSpatrick   const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
805097a140dSpatrick   while (CovBuf < CovBufEnd) {
806097a140dSpatrick     // Read the current coverage header & filename data.
807097a140dSpatrick     //
808097a140dSpatrick     // Prior to Version4, this also reads all function records affixed to the
809097a140dSpatrick     // header.
810097a140dSpatrick     //
811097a140dSpatrick     // Return a pointer to the next coverage header.
81273471bf0Spatrick     auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
813097a140dSpatrick     if (auto E = NextOrErr.takeError())
81409467b48Spatrick       return E;
815097a140dSpatrick     CovBuf = NextOrErr.get();
81609467b48Spatrick   }
817097a140dSpatrick   // In Version4, function records are not affixed to coverage headers. Read
818097a140dSpatrick   // the records from their dedicated section.
81973471bf0Spatrick   if (Version >= CovMapVersion::Version4)
820*d415bd75Srobert     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
821*d415bd75Srobert                                        nullptr, nullptr);
82209467b48Spatrick   return Error::success();
82309467b48Spatrick }
82409467b48Spatrick 
82509467b48Spatrick static const char *TestingFormatMagic = "llvmcovmtestdata";
82609467b48Spatrick 
82709467b48Spatrick Expected<std::unique_ptr<BinaryCoverageReader>>
createCoverageReaderFromBuffer(StringRef Coverage,FuncRecordsStorage && FuncRecords,InstrProfSymtab && ProfileNames,uint8_t BytesInAddress,support::endianness Endian,StringRef CompilationDir)82809467b48Spatrick BinaryCoverageReader::createCoverageReaderFromBuffer(
82973471bf0Spatrick     StringRef Coverage, FuncRecordsStorage &&FuncRecords,
83073471bf0Spatrick     InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
83173471bf0Spatrick     support::endianness Endian, StringRef CompilationDir) {
832097a140dSpatrick   std::unique_ptr<BinaryCoverageReader> Reader(
833097a140dSpatrick       new BinaryCoverageReader(std::move(FuncRecords)));
83409467b48Spatrick   Reader->ProfileNames = std::move(ProfileNames);
83573471bf0Spatrick   StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
83609467b48Spatrick   if (BytesInAddress == 4 && Endian == support::endianness::little) {
83709467b48Spatrick     if (Error E =
83809467b48Spatrick             readCoverageMappingData<uint32_t, support::endianness::little>(
839097a140dSpatrick                 Reader->ProfileNames, Coverage, FuncRecordsRef,
84073471bf0Spatrick                 Reader->MappingRecords, CompilationDir, Reader->Filenames))
84109467b48Spatrick       return std::move(E);
84209467b48Spatrick   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
84309467b48Spatrick     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
844097a140dSpatrick             Reader->ProfileNames, Coverage, FuncRecordsRef,
84573471bf0Spatrick             Reader->MappingRecords, CompilationDir, Reader->Filenames))
84609467b48Spatrick       return std::move(E);
84709467b48Spatrick   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
84809467b48Spatrick     if (Error E =
84909467b48Spatrick             readCoverageMappingData<uint64_t, support::endianness::little>(
850097a140dSpatrick                 Reader->ProfileNames, Coverage, FuncRecordsRef,
85173471bf0Spatrick                 Reader->MappingRecords, CompilationDir, Reader->Filenames))
85209467b48Spatrick       return std::move(E);
85309467b48Spatrick   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
85409467b48Spatrick     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
855097a140dSpatrick             Reader->ProfileNames, Coverage, FuncRecordsRef,
85673471bf0Spatrick             Reader->MappingRecords, CompilationDir, Reader->Filenames))
85709467b48Spatrick       return std::move(E);
85809467b48Spatrick   } else
85909467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
86009467b48Spatrick   return std::move(Reader);
86109467b48Spatrick }
86209467b48Spatrick 
86309467b48Spatrick static Expected<std::unique_ptr<BinaryCoverageReader>>
loadTestingFormat(StringRef Data,StringRef CompilationDir)86473471bf0Spatrick loadTestingFormat(StringRef Data, StringRef CompilationDir) {
86509467b48Spatrick   uint8_t BytesInAddress = 8;
86609467b48Spatrick   support::endianness Endian = support::endianness::little;
86709467b48Spatrick 
86809467b48Spatrick   Data = Data.substr(StringRef(TestingFormatMagic).size());
86909467b48Spatrick   if (Data.empty())
87009467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::truncated);
87109467b48Spatrick   unsigned N = 0;
87209467b48Spatrick   uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
87309467b48Spatrick   if (N > Data.size())
87409467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
87509467b48Spatrick   Data = Data.substr(N);
87609467b48Spatrick   if (Data.empty())
87709467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::truncated);
87809467b48Spatrick   N = 0;
87909467b48Spatrick   uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
88009467b48Spatrick   if (N > Data.size())
88109467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
88209467b48Spatrick   Data = Data.substr(N);
88309467b48Spatrick   if (Data.size() < ProfileNamesSize)
88409467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
88509467b48Spatrick   InstrProfSymtab ProfileNames;
88609467b48Spatrick   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
88709467b48Spatrick     return std::move(E);
88873471bf0Spatrick   Data = Data.substr(ProfileNamesSize);
88909467b48Spatrick   // Skip the padding bytes because coverage map data has an alignment of 8.
89073471bf0Spatrick   size_t Pad = offsetToAlignedAddr(Data.data(), Align(8));
89173471bf0Spatrick   if (Data.size() < Pad)
89273471bf0Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
89373471bf0Spatrick   Data = Data.substr(Pad);
89473471bf0Spatrick   if (Data.size() < sizeof(CovMapHeader))
89573471bf0Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
89673471bf0Spatrick   auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
89773471bf0Spatrick       Data.substr(0, sizeof(CovMapHeader)).data());
89873471bf0Spatrick   CovMapVersion Version =
89973471bf0Spatrick       (CovMapVersion)CovHeader->getVersion<support::endianness::little>();
90073471bf0Spatrick   StringRef CoverageMapping;
90173471bf0Spatrick   BinaryCoverageReader::FuncRecordsStorage CoverageRecords;
90273471bf0Spatrick   if (Version < CovMapVersion::Version4) {
90373471bf0Spatrick     CoverageMapping = Data;
90409467b48Spatrick     if (CoverageMapping.empty())
90509467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::truncated);
90673471bf0Spatrick     CoverageRecords = MemoryBuffer::getMemBuffer("");
90773471bf0Spatrick   } else {
90873471bf0Spatrick     uint32_t FilenamesSize =
90973471bf0Spatrick         CovHeader->getFilenamesSize<support::endianness::little>();
91073471bf0Spatrick     uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
91173471bf0Spatrick     CoverageMapping = Data.substr(0, CoverageMappingSize);
91273471bf0Spatrick     if (CoverageMapping.empty())
91373471bf0Spatrick       return make_error<CoverageMapError>(coveragemap_error::truncated);
91473471bf0Spatrick     Data = Data.substr(CoverageMappingSize);
91573471bf0Spatrick     // Skip the padding bytes because coverage records data has an alignment
91673471bf0Spatrick     // of 8.
91773471bf0Spatrick     Pad = offsetToAlignedAddr(Data.data(), Align(8));
91873471bf0Spatrick     if (Data.size() < Pad)
91909467b48Spatrick       return make_error<CoverageMapError>(coveragemap_error::malformed);
92073471bf0Spatrick     CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad));
92173471bf0Spatrick     if (CoverageRecords->getBufferSize() == 0)
92273471bf0Spatrick       return make_error<CoverageMapError>(coveragemap_error::truncated);
92373471bf0Spatrick   }
92409467b48Spatrick   return BinaryCoverageReader::createCoverageReaderFromBuffer(
92573471bf0Spatrick       CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames),
92673471bf0Spatrick       BytesInAddress, Endian, CompilationDir);
92709467b48Spatrick }
92809467b48Spatrick 
929097a140dSpatrick /// Find all sections that match \p Name. There may be more than one if comdats
930097a140dSpatrick /// are in use, e.g. for the __llvm_covfun section on ELF.
lookupSections(ObjectFile & OF,StringRef Name)931097a140dSpatrick static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
932097a140dSpatrick                                                         StringRef Name) {
93309467b48Spatrick   // On COFF, the object file section name may end in "$M". This tells the
93409467b48Spatrick   // linker to sort these sections between "$A" and "$Z". The linker removes the
93509467b48Spatrick   // dollar and everything after it in the final binary. Do the same to match.
93609467b48Spatrick   bool IsCOFF = isa<COFFObjectFile>(OF);
93709467b48Spatrick   auto stripSuffix = [IsCOFF](StringRef N) {
93809467b48Spatrick     return IsCOFF ? N.split('$').first : N;
93909467b48Spatrick   };
94009467b48Spatrick   Name = stripSuffix(Name);
94109467b48Spatrick 
942097a140dSpatrick   std::vector<SectionRef> Sections;
94309467b48Spatrick   for (const auto &Section : OF.sections()) {
94409467b48Spatrick     Expected<StringRef> NameOrErr = Section.getName();
94509467b48Spatrick     if (!NameOrErr)
94609467b48Spatrick       return NameOrErr.takeError();
94709467b48Spatrick     if (stripSuffix(*NameOrErr) == Name)
948097a140dSpatrick       Sections.push_back(Section);
94909467b48Spatrick   }
950097a140dSpatrick   if (Sections.empty())
95109467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::no_data_found);
952097a140dSpatrick   return Sections;
95309467b48Spatrick }
95409467b48Spatrick 
95509467b48Spatrick static Expected<std::unique_ptr<BinaryCoverageReader>>
loadBinaryFormat(std::unique_ptr<Binary> Bin,StringRef Arch,StringRef CompilationDir="",std::optional<object::BuildIDRef> * BinaryID=nullptr)95673471bf0Spatrick loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
957*d415bd75Srobert                  StringRef CompilationDir = "",
958*d415bd75Srobert                  std::optional<object::BuildIDRef> *BinaryID = nullptr) {
95909467b48Spatrick   std::unique_ptr<ObjectFile> OF;
96009467b48Spatrick   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
96109467b48Spatrick     // If we have a universal binary, try to look up the object for the
96209467b48Spatrick     // appropriate architecture.
96309467b48Spatrick     auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
96409467b48Spatrick     if (!ObjectFileOrErr)
96509467b48Spatrick       return ObjectFileOrErr.takeError();
96609467b48Spatrick     OF = std::move(ObjectFileOrErr.get());
96709467b48Spatrick   } else if (isa<ObjectFile>(Bin.get())) {
96809467b48Spatrick     // For any other object file, upcast and take ownership.
96909467b48Spatrick     OF.reset(cast<ObjectFile>(Bin.release()));
97009467b48Spatrick     // If we've asked for a particular arch, make sure they match.
97109467b48Spatrick     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
97209467b48Spatrick       return errorCodeToError(object_error::arch_not_found);
97309467b48Spatrick   } else
97409467b48Spatrick     // We can only handle object files.
97509467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
97609467b48Spatrick 
97709467b48Spatrick   // The coverage uses native pointer sizes for the object it's written in.
97809467b48Spatrick   uint8_t BytesInAddress = OF->getBytesInAddress();
97909467b48Spatrick   support::endianness Endian = OF->isLittleEndian()
98009467b48Spatrick                                    ? support::endianness::little
98109467b48Spatrick                                    : support::endianness::big;
98209467b48Spatrick 
98309467b48Spatrick   // Look for the sections that we are interested in.
98409467b48Spatrick   auto ObjFormat = OF->getTripleObjectFormat();
98509467b48Spatrick   auto NamesSection =
986097a140dSpatrick       lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
98709467b48Spatrick                                                  /*AddSegmentInfo=*/false));
98809467b48Spatrick   if (auto E = NamesSection.takeError())
98909467b48Spatrick     return std::move(E);
99009467b48Spatrick   auto CoverageSection =
991097a140dSpatrick       lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
99209467b48Spatrick                                                   /*AddSegmentInfo=*/false));
99309467b48Spatrick   if (auto E = CoverageSection.takeError())
99409467b48Spatrick     return std::move(E);
995097a140dSpatrick   std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
996097a140dSpatrick   if (CoverageSectionRefs.size() != 1)
997097a140dSpatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
998097a140dSpatrick   auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
99909467b48Spatrick   if (!CoverageMappingOrErr)
100009467b48Spatrick     return CoverageMappingOrErr.takeError();
1001097a140dSpatrick   StringRef CoverageMapping = CoverageMappingOrErr.get();
100209467b48Spatrick 
100309467b48Spatrick   InstrProfSymtab ProfileNames;
1004097a140dSpatrick   std::vector<SectionRef> NamesSectionRefs = *NamesSection;
1005097a140dSpatrick   if (NamesSectionRefs.size() != 1)
1006097a140dSpatrick     return make_error<CoverageMapError>(coveragemap_error::malformed);
1007097a140dSpatrick   if (Error E = ProfileNames.create(NamesSectionRefs.back()))
100809467b48Spatrick     return std::move(E);
100909467b48Spatrick 
1010097a140dSpatrick   // Look for the coverage records section (Version4 only).
1011097a140dSpatrick   auto CoverageRecordsSections =
1012097a140dSpatrick       lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
1013097a140dSpatrick                                                   /*AddSegmentInfo=*/false));
101473471bf0Spatrick 
101573471bf0Spatrick   BinaryCoverageReader::FuncRecordsStorage FuncRecords;
101673471bf0Spatrick   if (auto E = CoverageRecordsSections.takeError()) {
1017097a140dSpatrick     consumeError(std::move(E));
101873471bf0Spatrick     FuncRecords = MemoryBuffer::getMemBuffer("");
101973471bf0Spatrick   } else {
102073471bf0Spatrick     // Compute the FuncRecordsBuffer of the buffer, taking into account the
102173471bf0Spatrick     // padding between each record, and making sure the first block is aligned
102273471bf0Spatrick     // in memory to maintain consistency between buffer address and size
102373471bf0Spatrick     // alignment.
102473471bf0Spatrick     const Align RecordAlignment(8);
102573471bf0Spatrick     uint64_t FuncRecordsSize = 0;
1026097a140dSpatrick     for (SectionRef Section : *CoverageRecordsSections) {
1027097a140dSpatrick       auto CoverageRecordsOrErr = Section.getContents();
1028097a140dSpatrick       if (!CoverageRecordsOrErr)
1029097a140dSpatrick         return CoverageRecordsOrErr.takeError();
103073471bf0Spatrick       FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
1031097a140dSpatrick     }
103273471bf0Spatrick     auto WritableBuffer =
103373471bf0Spatrick         WritableMemoryBuffer::getNewUninitMemBuffer(FuncRecordsSize);
103473471bf0Spatrick     char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
103573471bf0Spatrick     assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) &&
103673471bf0Spatrick            "Allocated memory is correctly aligned");
103773471bf0Spatrick 
103873471bf0Spatrick     for (SectionRef Section : *CoverageRecordsSections) {
103973471bf0Spatrick       auto CoverageRecordsOrErr = Section.getContents();
104073471bf0Spatrick       if (!CoverageRecordsOrErr)
104173471bf0Spatrick         return CoverageRecordsOrErr.takeError();
104273471bf0Spatrick       const auto &CoverageRecords = CoverageRecordsOrErr.get();
104373471bf0Spatrick       FuncRecordsBuffer = std::copy(CoverageRecords.begin(),
104473471bf0Spatrick                                     CoverageRecords.end(), FuncRecordsBuffer);
104573471bf0Spatrick       FuncRecordsBuffer =
104673471bf0Spatrick           std::fill_n(FuncRecordsBuffer,
104773471bf0Spatrick                       alignAddr(FuncRecordsBuffer, RecordAlignment) -
104873471bf0Spatrick                           (uintptr_t)FuncRecordsBuffer,
104973471bf0Spatrick                       '\0');
105073471bf0Spatrick     }
105173471bf0Spatrick     assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
105273471bf0Spatrick            "consistent init");
105373471bf0Spatrick     FuncRecords = std::move(WritableBuffer);
1054097a140dSpatrick   }
1055097a140dSpatrick 
1056*d415bd75Srobert   if (BinaryID)
1057*d415bd75Srobert     *BinaryID = getBuildID(OF.get());
1058*d415bd75Srobert 
105909467b48Spatrick   return BinaryCoverageReader::createCoverageReaderFromBuffer(
1060097a140dSpatrick       CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
106173471bf0Spatrick       BytesInAddress, Endian, CompilationDir);
106273471bf0Spatrick }
106373471bf0Spatrick 
106473471bf0Spatrick /// Determine whether \p Arch is invalid or empty, given \p Bin.
isArchSpecifierInvalidOrMissing(Binary * Bin,StringRef Arch)106573471bf0Spatrick static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
106673471bf0Spatrick   // If we have a universal binary and Arch doesn't identify any of its slices,
106773471bf0Spatrick   // it's user error.
106873471bf0Spatrick   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
106973471bf0Spatrick     for (auto &ObjForArch : Universal->objects())
107073471bf0Spatrick       if (Arch == ObjForArch.getArchFlagName())
107173471bf0Spatrick         return false;
107273471bf0Spatrick     return true;
107373471bf0Spatrick   }
107473471bf0Spatrick   return false;
107509467b48Spatrick }
107609467b48Spatrick 
107709467b48Spatrick Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
create(MemoryBufferRef ObjectBuffer,StringRef Arch,SmallVectorImpl<std::unique_ptr<MemoryBuffer>> & ObjectFileBuffers,StringRef CompilationDir,SmallVectorImpl<object::BuildIDRef> * BinaryIDs)107809467b48Spatrick BinaryCoverageReader::create(
107909467b48Spatrick     MemoryBufferRef ObjectBuffer, StringRef Arch,
108073471bf0Spatrick     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
1081*d415bd75Srobert     StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {
108209467b48Spatrick   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
108309467b48Spatrick 
108409467b48Spatrick   if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
108509467b48Spatrick     // This is a special format used for testing.
108673471bf0Spatrick     auto ReaderOrErr =
108773471bf0Spatrick         loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
108809467b48Spatrick     if (!ReaderOrErr)
108909467b48Spatrick       return ReaderOrErr.takeError();
109009467b48Spatrick     Readers.push_back(std::move(ReaderOrErr.get()));
109109467b48Spatrick     return std::move(Readers);
109209467b48Spatrick   }
109309467b48Spatrick 
109409467b48Spatrick   auto BinOrErr = createBinary(ObjectBuffer);
109509467b48Spatrick   if (!BinOrErr)
109609467b48Spatrick     return BinOrErr.takeError();
109709467b48Spatrick   std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
109809467b48Spatrick 
109973471bf0Spatrick   if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
110073471bf0Spatrick     return make_error<CoverageMapError>(
110173471bf0Spatrick         coveragemap_error::invalid_or_missing_arch_specifier);
110273471bf0Spatrick 
110309467b48Spatrick   // MachO universal binaries which contain archives need to be treated as
110409467b48Spatrick   // archives, not as regular binaries.
110509467b48Spatrick   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
110609467b48Spatrick     for (auto &ObjForArch : Universal->objects()) {
110709467b48Spatrick       // Skip slices within the universal binary which target the wrong arch.
110809467b48Spatrick       std::string ObjArch = ObjForArch.getArchFlagName();
110909467b48Spatrick       if (Arch != ObjArch)
111009467b48Spatrick         continue;
111109467b48Spatrick 
111209467b48Spatrick       auto ArchiveOrErr = ObjForArch.getAsArchive();
111309467b48Spatrick       if (!ArchiveOrErr) {
111409467b48Spatrick         // If this is not an archive, try treating it as a regular object.
111509467b48Spatrick         consumeError(ArchiveOrErr.takeError());
111609467b48Spatrick         break;
111709467b48Spatrick       }
111809467b48Spatrick 
111909467b48Spatrick       return BinaryCoverageReader::create(
112073471bf0Spatrick           ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
1121*d415bd75Srobert           CompilationDir, BinaryIDs);
112209467b48Spatrick     }
112309467b48Spatrick   }
112409467b48Spatrick 
112509467b48Spatrick   // Load coverage out of archive members.
112609467b48Spatrick   if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
112709467b48Spatrick     Error Err = Error::success();
112809467b48Spatrick     for (auto &Child : Ar->children(Err)) {
112909467b48Spatrick       Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
113009467b48Spatrick       if (!ChildBufOrErr)
113109467b48Spatrick         return ChildBufOrErr.takeError();
113209467b48Spatrick 
113309467b48Spatrick       auto ChildReadersOrErr = BinaryCoverageReader::create(
1134*d415bd75Srobert           ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,
1135*d415bd75Srobert           BinaryIDs);
113609467b48Spatrick       if (!ChildReadersOrErr)
113709467b48Spatrick         return ChildReadersOrErr.takeError();
113809467b48Spatrick       for (auto &Reader : ChildReadersOrErr.get())
113909467b48Spatrick         Readers.push_back(std::move(Reader));
114009467b48Spatrick     }
114109467b48Spatrick     if (Err)
114209467b48Spatrick       return std::move(Err);
114309467b48Spatrick 
114409467b48Spatrick     // Thin archives reference object files outside of the archive file, i.e.
114509467b48Spatrick     // files which reside in memory not owned by the caller. Transfer ownership
114609467b48Spatrick     // to the caller.
114709467b48Spatrick     if (Ar->isThin())
114809467b48Spatrick       for (auto &Buffer : Ar->takeThinBuffers())
114909467b48Spatrick         ObjectFileBuffers.push_back(std::move(Buffer));
115009467b48Spatrick 
115109467b48Spatrick     return std::move(Readers);
115209467b48Spatrick   }
115309467b48Spatrick 
1154*d415bd75Srobert   std::optional<object::BuildIDRef> BinaryID;
1155*d415bd75Srobert   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,
1156*d415bd75Srobert                                       BinaryIDs ? &BinaryID : nullptr);
115709467b48Spatrick   if (!ReaderOrErr)
115809467b48Spatrick     return ReaderOrErr.takeError();
115909467b48Spatrick   Readers.push_back(std::move(ReaderOrErr.get()));
1160*d415bd75Srobert   if (BinaryID)
1161*d415bd75Srobert     BinaryIDs->push_back(*BinaryID);
116209467b48Spatrick   return std::move(Readers);
116309467b48Spatrick }
116409467b48Spatrick 
readNextRecord(CoverageMappingRecord & Record)116509467b48Spatrick Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
116609467b48Spatrick   if (CurrentRecord >= MappingRecords.size())
116709467b48Spatrick     return make_error<CoverageMapError>(coveragemap_error::eof);
116809467b48Spatrick 
116909467b48Spatrick   FunctionsFilenames.clear();
117009467b48Spatrick   Expressions.clear();
117109467b48Spatrick   MappingRegions.clear();
117209467b48Spatrick   auto &R = MappingRecords[CurrentRecord];
1173*d415bd75Srobert   auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
117473471bf0Spatrick   RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
117573471bf0Spatrick                                   Expressions, MappingRegions);
117609467b48Spatrick   if (auto Err = Reader.read())
117709467b48Spatrick     return Err;
117809467b48Spatrick 
117909467b48Spatrick   Record.FunctionName = R.FunctionName;
118009467b48Spatrick   Record.FunctionHash = R.FunctionHash;
118109467b48Spatrick   Record.Filenames = FunctionsFilenames;
118209467b48Spatrick   Record.Expressions = Expressions;
118309467b48Spatrick   Record.MappingRegions = MappingRegions;
118409467b48Spatrick 
118509467b48Spatrick   ++CurrentRecord;
118609467b48Spatrick   return Error::success();
118709467b48Spatrick }
1188