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