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