blob: 515f19a3b4067b67f543dc62a820036c0406a6d6 [file] [log] [blame]
Eugene Zelenkoe78d1312017-03-03 01:07:34 +00001//===- CoverageMappingReader.cpp - Code coverage mapping reader -*- C++ -*-===//
Alex Lorenza20a5d52014-07-24 23:57:54 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains support for reading coverage mapping data for
11// instrumentation based coverage.
12//
13//===----------------------------------------------------------------------===//
14
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000015#include "llvm/ADT/ArrayRef.h"
Igor Kudrinac40e812016-05-20 09:14:24 +000016#include "llvm/ADT/DenseMap.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000017#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Triple.h"
21#include "llvm/Object/Binary.h"
22#include "llvm/Object/Error.h"
Justin Bogner43795352015-03-11 02:30:51 +000023#include "llvm/Object/MachOUniversal.h"
Alex Lorenza20a5d52014-07-24 23:57:54 +000024#include "llvm/Object/ObjectFile.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000025#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
26#include "llvm/ProfileData/InstrProf.h"
27#include "llvm/Support/Casting.h"
Justin Bognerf5846492014-09-20 15:31:51 +000028#include "llvm/Support/Debug.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000029#include "llvm/Support/Error.h"
30#include "llvm/Support/ErrorHandling.h"
Justin Bogner7b33cc92015-03-16 06:55:45 +000031#include "llvm/Support/Endian.h"
Alex Lorenza20a5d52014-07-24 23:57:54 +000032#include "llvm/Support/LEB128.h"
Justin Bognerd49d8ee2015-06-05 01:23:42 +000033#include "llvm/Support/MathExtras.h"
Benjamin Kramer799003b2015-03-23 19:32:43 +000034#include "llvm/Support/raw_ostream.h"
Eugene Zelenkoe78d1312017-03-03 01:07:34 +000035#include <algorithm>
36#include <cassert>
37#include <cstddef>
38#include <cstdint>
39#include <limits>
40#include <memory>
41#include <utility>
42#include <vector>
Alex Lorenza20a5d52014-07-24 23:57:54 +000043
44using namespace llvm;
45using namespace coverage;
46using namespace object;
47
Justin Bognerf5846492014-09-20 15:31:51 +000048#define DEBUG_TYPE "coverage-mapping"
49
Alex Lorenza20a5d52014-07-24 23:57:54 +000050void CoverageMappingIterator::increment() {
51 // Check if all the records were read or if an error occurred while reading
52 // the next record.
Vedant Kumar9152fd12016-05-19 03:54:45 +000053 if (auto E = Reader->readNextRecord(Record)) {
54 handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
55 if (CME.get() == coveragemap_error::eof)
56 *this = CoverageMappingIterator();
57 else
58 llvm_unreachable("Unexpected error in coverage mapping iterator");
59 });
60 }
Alex Lorenza20a5d52014-07-24 23:57:54 +000061}
62
Vedant Kumar9152fd12016-05-19 03:54:45 +000063Error RawCoverageReader::readULEB128(uint64_t &Result) {
Alex Lorenza20a5d52014-07-24 23:57:54 +000064 if (Data.size() < 1)
Vedant Kumar9152fd12016-05-19 03:54:45 +000065 return make_error<CoverageMapError>(coveragemap_error::truncated);
Alex Lorenza20a5d52014-07-24 23:57:54 +000066 unsigned N = 0;
67 Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
68 if (N > Data.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +000069 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +000070 Data = Data.substr(N);
Vedant Kumar9152fd12016-05-19 03:54:45 +000071 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +000072}
73
Vedant Kumar9152fd12016-05-19 03:54:45 +000074Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
Alex Lorenza20a5d52014-07-24 23:57:54 +000075 if (auto Err = readULEB128(Result))
76 return Err;
77 if (Result >= MaxPlus1)
Vedant Kumar9152fd12016-05-19 03:54:45 +000078 return make_error<CoverageMapError>(coveragemap_error::malformed);
79 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +000080}
81
Vedant Kumar9152fd12016-05-19 03:54:45 +000082Error RawCoverageReader::readSize(uint64_t &Result) {
Alex Lorenza20a5d52014-07-24 23:57:54 +000083 if (auto Err = readULEB128(Result))
84 return Err;
85 // Sanity check the number.
86 if (Result > Data.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +000087 return make_error<CoverageMapError>(coveragemap_error::malformed);
88 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +000089}
90
Vedant Kumar9152fd12016-05-19 03:54:45 +000091Error RawCoverageReader::readString(StringRef &Result) {
Alex Lorenza20a5d52014-07-24 23:57:54 +000092 uint64_t Length;
93 if (auto Err = readSize(Length))
94 return Err;
95 Result = Data.substr(0, Length);
96 Data = Data.substr(Length);
Vedant Kumar9152fd12016-05-19 03:54:45 +000097 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +000098}
99
Vedant Kumar9152fd12016-05-19 03:54:45 +0000100Error RawCoverageFilenamesReader::read() {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000101 uint64_t NumFilenames;
102 if (auto Err = readSize(NumFilenames))
103 return Err;
104 for (size_t I = 0; I < NumFilenames; ++I) {
105 StringRef Filename;
106 if (auto Err = readString(Filename))
107 return Err;
108 Filenames.push_back(Filename);
109 }
Vedant Kumar9152fd12016-05-19 03:54:45 +0000110 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000111}
112
Vedant Kumar9152fd12016-05-19 03:54:45 +0000113Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000114 auto Tag = Value & Counter::EncodingTagMask;
115 switch (Tag) {
116 case Counter::Zero:
117 C = Counter::getZero();
Vedant Kumar9152fd12016-05-19 03:54:45 +0000118 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000119 case Counter::CounterValueReference:
120 C = Counter::getCounter(Value >> Counter::EncodingTagBits);
Vedant Kumar9152fd12016-05-19 03:54:45 +0000121 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000122 default:
123 break;
124 }
125 Tag -= Counter::Expression;
126 switch (Tag) {
127 case CounterExpression::Subtract:
128 case CounterExpression::Add: {
129 auto ID = Value >> Counter::EncodingTagBits;
130 if (ID >= Expressions.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000131 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000132 Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
133 C = Counter::getExpression(ID);
134 break;
135 }
136 default:
Vedant Kumar9152fd12016-05-19 03:54:45 +0000137 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000138 }
Vedant Kumar9152fd12016-05-19 03:54:45 +0000139 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000140}
141
Vedant Kumar9152fd12016-05-19 03:54:45 +0000142Error RawCoverageMappingReader::readCounter(Counter &C) {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000143 uint64_t EncodedCounter;
144 if (auto Err =
145 readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
146 return Err;
147 if (auto Err = decodeCounter(EncodedCounter, C))
148 return Err;
Vedant Kumar9152fd12016-05-19 03:54:45 +0000149 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000150}
151
152static const unsigned EncodingExpansionRegionBit = 1
153 << Counter::EncodingTagBits;
154
155/// \brief Read the sub-array of regions for the given inferred file id.
Ehsan Akhgari29b61ce2014-07-25 02:51:57 +0000156/// \param NumFileIDs the number of file ids that are defined for this
Alex Lorenza20a5d52014-07-24 23:57:54 +0000157/// function.
Vedant Kumar9152fd12016-05-19 03:54:45 +0000158Error RawCoverageMappingReader::readMappingRegionsSubArray(
Alex Lorenza20a5d52014-07-24 23:57:54 +0000159 std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
160 size_t NumFileIDs) {
161 uint64_t NumRegions;
162 if (auto Err = readSize(NumRegions))
163 return Err;
164 unsigned LineStart = 0;
165 for (size_t I = 0; I < NumRegions; ++I) {
166 Counter C;
167 CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
168
169 // Read the combined counter + region kind.
170 uint64_t EncodedCounterAndRegion;
171 if (auto Err = readIntMax(EncodedCounterAndRegion,
172 std::numeric_limits<unsigned>::max()))
173 return Err;
174 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
175 uint64_t ExpandedFileID = 0;
176 if (Tag != Counter::Zero) {
177 if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
178 return Err;
179 } else {
180 // Is it an expansion region?
181 if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
182 Kind = CounterMappingRegion::ExpansionRegion;
183 ExpandedFileID = EncodedCounterAndRegion >>
184 Counter::EncodingCounterTagAndExpansionRegionTagBits;
185 if (ExpandedFileID >= NumFileIDs)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000186 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000187 } else {
188 switch (EncodedCounterAndRegion >>
189 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
190 case CounterMappingRegion::CodeRegion:
191 // Don't do anything when we have a code region with a zero counter.
192 break;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000193 case CounterMappingRegion::SkippedRegion:
194 Kind = CounterMappingRegion::SkippedRegion;
195 break;
196 default:
Vedant Kumar9152fd12016-05-19 03:54:45 +0000197 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000198 }
199 }
200 }
201
202 // Read the source range.
Justin Bognerde158172015-02-03 21:35:36 +0000203 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000204 if (auto Err =
205 readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
206 return Err;
Justin Bognerde158172015-02-03 21:35:36 +0000207 if (auto Err = readULEB128(ColumnStart))
Alex Lorenza20a5d52014-07-24 23:57:54 +0000208 return Err;
Alex Lorenz1193b5e2014-08-04 18:00:51 +0000209 if (ColumnStart > std::numeric_limits<unsigned>::max())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000210 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000211 if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
212 return Err;
213 if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
214 return Err;
215 LineStart += LineStartDelta;
216 // Adjust the column locations for the empty regions that are supposed to
217 // cover whole lines. Those regions should be encoded with the
218 // column range (1 -> std::numeric_limits<unsigned>::max()), but because
219 // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
220 // we set the column range to (0 -> 0) to ensure that the column start and
221 // column end take up one byte each.
222 // The std::numeric_limits<unsigned>::max() is used to represent a column
223 // position at the end of the line without knowing the length of that line.
224 if (ColumnStart == 0 && ColumnEnd == 0) {
225 ColumnStart = 1;
226 ColumnEnd = std::numeric_limits<unsigned>::max();
227 }
Justin Bognerf5846492014-09-20 15:31:51 +0000228
229 DEBUG({
230 dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
231 << ColumnStart << " -> " << (LineStart + NumLines) << ":"
232 << ColumnEnd << ", ";
233 if (Kind == CounterMappingRegion::ExpansionRegion)
234 dbgs() << "Expands to file " << ExpandedFileID;
235 else
236 CounterMappingContext(Expressions).dump(C, dbgs());
237 dbgs() << "\n";
238 });
239
Justin Bogner26b31422015-02-03 23:59:33 +0000240 MappingRegions.push_back(CounterMappingRegion(
241 C, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
242 LineStart + NumLines, ColumnEnd, Kind));
Alex Lorenza20a5d52014-07-24 23:57:54 +0000243 }
Vedant Kumar9152fd12016-05-19 03:54:45 +0000244 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000245}
246
Vedant Kumar9152fd12016-05-19 03:54:45 +0000247Error RawCoverageMappingReader::read() {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000248 // Read the virtual file mapping.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000249 SmallVector<unsigned, 8> VirtualFileMapping;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000250 uint64_t NumFileMappings;
251 if (auto Err = readSize(NumFileMappings))
252 return Err;
253 for (size_t I = 0; I < NumFileMappings; ++I) {
254 uint64_t FilenameIndex;
255 if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
256 return Err;
257 VirtualFileMapping.push_back(FilenameIndex);
258 }
259
260 // Construct the files using unique filenames and virtual file mapping.
261 for (auto I : VirtualFileMapping) {
262 Filenames.push_back(TranslationUnitFilenames[I]);
263 }
264
265 // Read the expressions.
266 uint64_t NumExpressions;
267 if (auto Err = readSize(NumExpressions))
268 return Err;
269 // Create an array of dummy expressions that get the proper counters
270 // when the expressions are read, and the proper kinds when the counters
271 // are decoded.
272 Expressions.resize(
273 NumExpressions,
274 CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
275 for (size_t I = 0; I < NumExpressions; ++I) {
276 if (auto Err = readCounter(Expressions[I].LHS))
277 return Err;
278 if (auto Err = readCounter(Expressions[I].RHS))
279 return Err;
280 }
281
282 // Read the mapping regions sub-arrays.
283 for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
284 InferredFileID < S; ++InferredFileID) {
285 if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
286 VirtualFileMapping.size()))
287 return Err;
288 }
289
290 // Set the counters for the expansion regions.
291 // i.e. Counter of expansion region = counter of the first region
292 // from the expanded file.
293 // Perform multiple passes to correctly propagate the counters through
294 // all the nested expansion regions.
Alex Lorenz251b3e32014-07-29 21:42:24 +0000295 SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
296 FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000297 for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
Alex Lorenz251b3e32014-07-29 21:42:24 +0000298 for (auto &R : MappingRegions) {
299 if (R.Kind != CounterMappingRegion::ExpansionRegion)
300 continue;
301 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
302 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
303 }
304 for (auto &R : MappingRegions) {
305 if (FileIDExpansionRegionMapping[R.FileID]) {
306 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
307 FileIDExpansionRegionMapping[R.FileID] = nullptr;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000308 }
309 }
310 }
311
Vedant Kumar9152fd12016-05-19 03:54:45 +0000312 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000313}
314
Igor Kudrinac40e812016-05-20 09:14:24 +0000315Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
316 // A dummy coverage mapping data consists of just one region with zero count.
317 uint64_t NumFileMappings;
318 if (Error Err = readSize(NumFileMappings))
319 return std::move(Err);
320 if (NumFileMappings != 1)
321 return false;
322 // We don't expect any specific value for the filename index, just skip it.
323 uint64_t FilenameIndex;
324 if (Error Err =
325 readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
326 return std::move(Err);
327 uint64_t NumExpressions;
328 if (Error Err = readSize(NumExpressions))
329 return std::move(Err);
330 if (NumExpressions != 0)
331 return false;
332 uint64_t NumRegions;
333 if (Error Err = readSize(NumRegions))
334 return std::move(Err);
335 if (NumRegions != 1)
336 return false;
337 uint64_t EncodedCounterAndRegion;
338 if (Error Err = readIntMax(EncodedCounterAndRegion,
339 std::numeric_limits<unsigned>::max()))
340 return std::move(Err);
341 unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
342 return Tag == Counter::Zero;
343}
344
Vedant Kumar9152fd12016-05-19 03:54:45 +0000345Error InstrProfSymtab::create(SectionRef &Section) {
346 if (auto EC = Section.getContents(Data))
347 return errorCodeToError(EC);
Xinliang David Li50de45d2015-12-17 00:53:37 +0000348 Address = Section.getAddress();
Vedant Kumar9152fd12016-05-19 03:54:45 +0000349 return Error::success();
Xinliang David Li50de45d2015-12-17 00:53:37 +0000350}
Alex Lorenza20a5d52014-07-24 23:57:54 +0000351
Xinliang David Li50de45d2015-12-17 00:53:37 +0000352StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
353 if (Pointer < Address)
354 return StringRef();
355 auto Offset = Pointer - Address;
356 if (Offset + Size > Data.size())
357 return StringRef();
358 return Data.substr(Pointer - Address, Size);
Alexander Kornienkof00654e2015-06-23 09:49:53 +0000359}
Alex Lorenza20a5d52014-07-24 23:57:54 +0000360
Igor Kudrinac40e812016-05-20 09:14:24 +0000361// Check if the mapping data is a dummy, i.e. is emitted for an unused function.
362static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
363 // The hash value of dummy mapping records is always zero.
364 if (Hash)
365 return false;
366 return RawCoverageMappingDummyChecker(Mapping).isDummy();
367}
368
Benjamin Kramer85c824f2016-02-05 13:50:53 +0000369namespace {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000370
Xinliang David Lia9d78462016-01-13 23:29:33 +0000371struct CovMapFuncRecordReader {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000372 virtual ~CovMapFuncRecordReader() = default;
373
Vedant Kumar3739b952016-06-17 21:31:03 +0000374 // The interface to read coverage mapping function records for a module.
375 //
376 // \p Buf points to the buffer containing the \c CovHeader of the coverage
377 // mapping data associated with the module.
378 //
379 // Returns a pointer to the next \c CovHeader if it exists, or a pointer
380 // greater than \p End if not.
381 virtual Expected<const char *> readFunctionRecords(const char *Buf,
382 const char *End) = 0;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000383
Xinliang David Lia9d78462016-01-13 23:29:33 +0000384 template <class IntPtrT, support::endianness Endian>
Vedant Kumar9152fd12016-05-19 03:54:45 +0000385 static Expected<std::unique_ptr<CovMapFuncRecordReader>>
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000386 get(CovMapVersion Version, InstrProfSymtab &P,
Xinliang David Lia9d78462016-01-13 23:29:33 +0000387 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
388 std::vector<StringRef> &F);
389};
Alex Lorenza20a5d52014-07-24 23:57:54 +0000390
Xinliang David Lia9d78462016-01-13 23:29:33 +0000391// A class for reading coverage mapping function records for a module.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000392template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
Xinliang David Lia9d78462016-01-13 23:29:33 +0000393class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000394 typedef typename CovMapTraits<
Xinliang David Li84a2df32016-01-14 06:38:52 +0000395 Version, IntPtrT>::CovMapFuncRecordType FuncRecordType;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000396 typedef typename CovMapTraits<Version, IntPtrT>::NameRefType NameRefType;
Xinliang David Lia9d78462016-01-13 23:29:33 +0000397
Igor Kudrinac40e812016-05-20 09:14:24 +0000398 // Maps function's name references to the indexes of their records
399 // in \c Records.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000400 DenseMap<NameRefType, size_t> FunctionRecords;
Xinliang David Lia9d78462016-01-13 23:29:33 +0000401 InstrProfSymtab &ProfileNames;
402 std::vector<StringRef> &Filenames;
403 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
404
Igor Kudrinac40e812016-05-20 09:14:24 +0000405 // Add the record to the collection if we don't already have a record that
406 // points to the same function name. This is useful to ignore the redundant
407 // records for the functions with ODR linkage.
408 // In addition, prefer records with real coverage mapping data to dummy
409 // records, which were emitted for inline functions which were seen but
410 // not used in the corresponding translation unit.
411 Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
412 StringRef Mapping, size_t FilenamesBegin) {
413 uint64_t FuncHash = CFR->template getFuncHash<Endian>();
414 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
415 auto InsertResult =
416 FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
417 if (InsertResult.second) {
418 StringRef FuncName;
419 if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
420 return Err;
421 Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin,
422 Filenames.size() - FilenamesBegin);
423 return Error::success();
424 }
425 // Update the existing record if it's a dummy and the new record is real.
426 size_t OldRecordIndex = InsertResult.first->second;
427 BinaryCoverageReader::ProfileMappingRecord &OldRecord =
428 Records[OldRecordIndex];
429 Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
430 OldRecord.FunctionHash, OldRecord.CoverageMapping);
431 if (Error Err = OldIsDummyExpected.takeError())
432 return Err;
433 if (!*OldIsDummyExpected)
434 return Error::success();
435 Expected<bool> NewIsDummyExpected =
436 isCoverageMappingDummy(FuncHash, Mapping);
437 if (Error Err = NewIsDummyExpected.takeError())
438 return Err;
439 if (*NewIsDummyExpected)
440 return Error::success();
441 OldRecord.FunctionHash = FuncHash;
442 OldRecord.CoverageMapping = Mapping;
443 OldRecord.FilenamesBegin = FilenamesBegin;
444 OldRecord.FilenamesSize = Filenames.size() - FilenamesBegin;
445 return Error::success();
446 }
447
Xinliang David Lia9d78462016-01-13 23:29:33 +0000448public:
449 VersionedCovMapFuncRecordReader(
450 InstrProfSymtab &P,
451 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
452 std::vector<StringRef> &F)
453 : ProfileNames(P), Filenames(F), Records(R) {}
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000454
455 ~VersionedCovMapFuncRecordReader() override = default;
Xinliang David Lia9d78462016-01-13 23:29:33 +0000456
Vedant Kumar3739b952016-06-17 21:31:03 +0000457 Expected<const char *> readFunctionRecords(const char *Buf,
458 const char *End) override {
Xinliang David Lia9d78462016-01-13 23:29:33 +0000459 using namespace support;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000460
Xinliang David Li946558d2016-01-03 18:57:40 +0000461 if (Buf + sizeof(CovMapHeader) > End)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000462 return make_error<CoverageMapError>(coveragemap_error::malformed);
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000463 auto CovHeader = reinterpret_cast<const CovMapHeader *>(Buf);
Xinliang David Li81f18a52016-01-13 04:36:15 +0000464 uint32_t NRecords = CovHeader->getNRecords<Endian>();
465 uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
466 uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
Xinliang David Li84a2df32016-01-14 06:38:52 +0000467 assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
Xinliang David Lia9d78462016-01-13 23:29:33 +0000468 Buf = reinterpret_cast<const char *>(CovHeader + 1);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000469
Justin Bogner7b33cc92015-03-16 06:55:45 +0000470 // Skip past the function records, saving the start and end for later.
471 const char *FunBuf = Buf;
Xinliang David Lia9d78462016-01-13 23:29:33 +0000472 Buf += NRecords * sizeof(FuncRecordType);
Justin Bogner7b33cc92015-03-16 06:55:45 +0000473 const char *FunEnd = Buf;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000474
475 // Get the filenames.
Justin Bogner7b33cc92015-03-16 06:55:45 +0000476 if (Buf + FilenamesSize > End)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000477 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000478 size_t FilenamesBegin = Filenames.size();
Justin Bogner7b33cc92015-03-16 06:55:45 +0000479 RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000480 if (auto Err = Reader.read())
Vedant Kumar3739b952016-06-17 21:31:03 +0000481 return std::move(Err);
Justin Bogner7b33cc92015-03-16 06:55:45 +0000482 Buf += FilenamesSize;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000483
Justin Bogner7b33cc92015-03-16 06:55:45 +0000484 // We'll read the coverage mapping records in the loop below.
485 const char *CovBuf = Buf;
486 Buf += CoverageSize;
487 const char *CovEnd = Buf;
Justin Bognerd49d8ee2015-06-05 01:23:42 +0000488
Justin Bogner7b33cc92015-03-16 06:55:45 +0000489 if (Buf > End)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000490 return make_error<CoverageMapError>(coveragemap_error::malformed);
Justin Bognerd49d8ee2015-06-05 01:23:42 +0000491 // Each coverage map has an alignment of 8, so we need to adjust alignment
492 // before reading the next map.
493 Buf += alignmentAdjustment(Buf, 8);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000494
Xinliang David Lia9d78462016-01-13 23:29:33 +0000495 auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf);
Xinliang David Li192c7482015-11-05 00:47:26 +0000496 while ((const char *)CFR < FunEnd) {
Justin Bogner7b33cc92015-03-16 06:55:45 +0000497 // Read the function information
Xinliang David Li81f18a52016-01-13 04:36:15 +0000498 uint32_t DataSize = CFR->template getDataSize<Endian>();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000499
Justin Bogner7b33cc92015-03-16 06:55:45 +0000500 // Now use that to read the coverage data.
501 if (CovBuf + DataSize > CovEnd)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000502 return make_error<CoverageMapError>(coveragemap_error::malformed);
Justin Bogner7b33cc92015-03-16 06:55:45 +0000503 auto Mapping = StringRef(CovBuf, DataSize);
504 CovBuf += DataSize;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000505
Igor Kudrinac40e812016-05-20 09:14:24 +0000506 if (Error Err =
507 insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin))
Vedant Kumar3739b952016-06-17 21:31:03 +0000508 return std::move(Err);
Xinliang David Li81f18a52016-01-13 04:36:15 +0000509 CFR++;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000510 }
Vedant Kumar3739b952016-06-17 21:31:03 +0000511 return Buf;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000512 }
Xinliang David Lia9d78462016-01-13 23:29:33 +0000513};
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000514
Benjamin Kramer85c824f2016-02-05 13:50:53 +0000515} // end anonymous namespace
Alex Lorenza20a5d52014-07-24 23:57:54 +0000516
Xinliang David Lia9d78462016-01-13 23:29:33 +0000517template <class IntPtrT, support::endianness Endian>
Vedant Kumar9152fd12016-05-19 03:54:45 +0000518Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000519 CovMapVersion Version, InstrProfSymtab &P,
Xinliang David Lia9d78462016-01-13 23:29:33 +0000520 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
521 std::vector<StringRef> &F) {
522 using namespace coverage;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000523
Xinliang David Lia9d78462016-01-13 23:29:33 +0000524 switch (Version) {
Xinliang David Lid5d88872016-01-14 06:21:25 +0000525 case CovMapVersion::Version1:
Xinliang David Lia9d78462016-01-13 23:29:33 +0000526 return llvm::make_unique<VersionedCovMapFuncRecordReader<
Xinliang David Lid5d88872016-01-14 06:21:25 +0000527 CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
Xinliang David Lia82d6c02016-02-08 18:13:49 +0000528 case CovMapVersion::Version2:
529 // Decompress the name data.
Vedant Kumar9152fd12016-05-19 03:54:45 +0000530 if (Error E = P.create(P.getNameData()))
531 return std::move(E);
Xinliang David Lia82d6c02016-02-08 18:13:49 +0000532 return llvm::make_unique<VersionedCovMapFuncRecordReader<
533 CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
Xinliang David Lia9d78462016-01-13 23:29:33 +0000534 }
535 llvm_unreachable("Unsupported version");
Xinliang David Liaab986f2016-01-13 22:58:42 +0000536}
Xinliang David Lie62595c2016-01-13 23:12:53 +0000537
Xinliang David Lia9d78462016-01-13 23:29:33 +0000538template <typename T, support::endianness Endian>
Vedant Kumar9152fd12016-05-19 03:54:45 +0000539static Error readCoverageMappingData(
Xinliang David Lia9d78462016-01-13 23:29:33 +0000540 InstrProfSymtab &ProfileNames, StringRef Data,
541 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
542 std::vector<StringRef> &Filenames) {
543 using namespace coverage;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000544
Xinliang David Lia9d78462016-01-13 23:29:33 +0000545 // Read the records in the coverage data section.
546 auto CovHeader =
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000547 reinterpret_cast<const CovMapHeader *>(Data.data());
Xinliang David Lid5d88872016-01-14 06:21:25 +0000548 CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000549 if (Version > CovMapVersion::CurrentVersion)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000550 return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
551 Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
Xinliang David Lia9d78462016-01-13 23:29:33 +0000552 CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
553 Filenames);
Vedant Kumar9152fd12016-05-19 03:54:45 +0000554 if (Error E = ReaderExpected.takeError())
555 return E;
556 auto Reader = std::move(ReaderExpected.get());
Xinliang David Lia9d78462016-01-13 23:29:33 +0000557 for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) {
Vedant Kumar3739b952016-06-17 21:31:03 +0000558 auto NextHeaderOrErr = Reader->readFunctionRecords(Buf, End);
559 if (auto E = NextHeaderOrErr.takeError())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000560 return E;
Vedant Kumar3739b952016-06-17 21:31:03 +0000561 Buf = NextHeaderOrErr.get();
Xinliang David Lia9d78462016-01-13 23:29:33 +0000562 }
Vedant Kumar9152fd12016-05-19 03:54:45 +0000563 return Error::success();
Xinliang David Lia9d78462016-01-13 23:29:33 +0000564}
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000565
Alex Lorenze82d89c2014-08-22 22:56:03 +0000566static const char *TestingFormatMagic = "llvmcovmtestdata";
567
Vedant Kumar9152fd12016-05-19 03:54:45 +0000568static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames,
569 StringRef &CoverageMapping,
570 uint8_t &BytesInAddress,
571 support::endianness &Endian) {
Justin Bogner43e51632015-02-26 20:06:28 +0000572 BytesInAddress = 8;
Justin Bognera4387172015-03-16 21:40:18 +0000573 Endian = support::endianness::little;
Justin Bogner43e51632015-02-26 20:06:28 +0000574
Alex Lorenze82d89c2014-08-22 22:56:03 +0000575 Data = Data.substr(StringRef(TestingFormatMagic).size());
576 if (Data.size() < 1)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000577 return make_error<CoverageMapError>(coveragemap_error::truncated);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000578 unsigned N = 0;
579 auto ProfileNamesSize =
580 decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
581 if (N > Data.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000582 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000583 Data = Data.substr(N);
584 if (Data.size() < 1)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000585 return make_error<CoverageMapError>(coveragemap_error::truncated);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000586 N = 0;
Xinliang David Li50de45d2015-12-17 00:53:37 +0000587 uint64_t Address =
Alex Lorenze82d89c2014-08-22 22:56:03 +0000588 decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
589 if (N > Data.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000590 return make_error<CoverageMapError>(coveragemap_error::malformed);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000591 Data = Data.substr(N);
592 if (Data.size() < ProfileNamesSize)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000593 return make_error<CoverageMapError>(coveragemap_error::malformed);
594 if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
595 return E;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000596 CoverageMapping = Data.substr(ProfileNamesSize);
Igor Kudrineb103072016-05-18 07:43:27 +0000597 // Skip the padding bytes because coverage map data has an alignment of 8.
598 if (CoverageMapping.size() < 1)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000599 return make_error<CoverageMapError>(coveragemap_error::truncated);
Igor Kudrineb103072016-05-18 07:43:27 +0000600 size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8);
601 if (CoverageMapping.size() < Pad)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000602 return make_error<CoverageMapError>(coveragemap_error::malformed);
Igor Kudrineb103072016-05-18 07:43:27 +0000603 CoverageMapping = CoverageMapping.substr(Pad);
Vedant Kumar9152fd12016-05-19 03:54:45 +0000604 return Error::success();
Alex Lorenze82d89c2014-08-22 22:56:03 +0000605}
606
Vedant Kumar9152fd12016-05-19 03:54:45 +0000607static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) {
Justin Bogner5a5c3812015-05-07 00:31:58 +0000608 StringRef FoundName;
609 for (const auto &Section : OF.sections()) {
610 if (auto EC = Section.getName(FoundName))
Vedant Kumar9152fd12016-05-19 03:54:45 +0000611 return errorCodeToError(EC);
Justin Bogner5a5c3812015-05-07 00:31:58 +0000612 if (FoundName == Name)
613 return Section;
614 }
Vedant Kumar9152fd12016-05-19 03:54:45 +0000615 return make_error<CoverageMapError>(coveragemap_error::no_data_found);
Justin Bogner5a5c3812015-05-07 00:31:58 +0000616}
617
Vedant Kumar9152fd12016-05-19 03:54:45 +0000618static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer,
619 InstrProfSymtab &ProfileNames,
620 StringRef &CoverageMapping,
621 uint8_t &BytesInAddress,
622 support::endianness &Endian, StringRef Arch) {
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000623 auto BinOrErr = createBinary(ObjectBuffer);
Kevin Enderby3fcdf6a2016-04-06 22:14:09 +0000624 if (!BinOrErr)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000625 return BinOrErr.takeError();
Justin Bogner43795352015-03-11 02:30:51 +0000626 auto Bin = std::move(BinOrErr.get());
627 std::unique_ptr<ObjectFile> OF;
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000628 if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
Justin Bogner43795352015-03-11 02:30:51 +0000629 // If we have a universal binary, try to look up the object for the
630 // appropriate architecture.
631 auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
Kevin Enderby9acb1092016-05-31 20:35:34 +0000632 if (!ObjectFileOrErr)
633 return ObjectFileOrErr.takeError();
Justin Bogner43795352015-03-11 02:30:51 +0000634 OF = std::move(ObjectFileOrErr.get());
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000635 } else if (isa<ObjectFile>(Bin.get())) {
Justin Bogner43795352015-03-11 02:30:51 +0000636 // For any other object file, upcast and take ownership.
Eugene Zelenkoe78d1312017-03-03 01:07:34 +0000637 OF.reset(cast<ObjectFile>(Bin.release()));
Justin Bogner43795352015-03-11 02:30:51 +0000638 // If we've asked for a particular arch, make sure they match.
Frederic Rissebc162a2015-06-22 21:33:24 +0000639 if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000640 return errorCodeToError(object_error::arch_not_found);
Justin Bogner43795352015-03-11 02:30:51 +0000641 } else
642 // We can only handle object files.
Vedant Kumar9152fd12016-05-19 03:54:45 +0000643 return make_error<CoverageMapError>(coveragemap_error::malformed);
Justin Bogner43795352015-03-11 02:30:51 +0000644
645 // The coverage uses native pointer sizes for the object it's written in.
Justin Bogner43e51632015-02-26 20:06:28 +0000646 BytesInAddress = OF->getBytesInAddress();
Justin Bognera4387172015-03-16 21:40:18 +0000647 Endian = OF->isLittleEndian() ? support::endianness::little
648 : support::endianness::big;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000649
650 // Look for the sections that we are interested in.
Xinliang David Li57dea2d2017-04-13 23:37:12 +0000651 // TODO: with the current getInstrProfXXXSectionName interfaces, the
652 // the coverage reader host tool is limited to read coverage section on
653 // binaries with compatible profile section naming scheme as the host
654 // platform. Currently, COFF format binaries have different section
655 // naming scheme from the all the rest.
656 auto NamesSection = lookupSection(*OF, getInstrProfNameSectionName());
Vedant Kumar9152fd12016-05-19 03:54:45 +0000657 if (auto E = NamesSection.takeError())
658 return E;
Xinliang David Li57dea2d2017-04-13 23:37:12 +0000659 auto CoverageSection = lookupSection(*OF, getInstrProfCoverageSectionName());
Vedant Kumar9152fd12016-05-19 03:54:45 +0000660 if (auto E = CoverageSection.takeError())
661 return E;
Alex Lorenza20a5d52014-07-24 23:57:54 +0000662
Alex Lorenze82d89c2014-08-22 22:56:03 +0000663 // Get the contents of the given sections.
Vedant Kumar9152fd12016-05-19 03:54:45 +0000664 if (auto EC = CoverageSection->getContents(CoverageMapping))
665 return errorCodeToError(EC);
666 if (Error E = ProfileNames.create(*NamesSection))
667 return E;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000668
Vedant Kumar9152fd12016-05-19 03:54:45 +0000669 return Error::success();
Justin Bogner43e51632015-02-26 20:06:28 +0000670}
671
Vedant Kumar9152fd12016-05-19 03:54:45 +0000672Expected<std::unique_ptr<BinaryCoverageReader>>
Vedant Kumara30139d2016-06-29 05:33:24 +0000673BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
674 StringRef Arch) {
Justin Bogner43e51632015-02-26 20:06:28 +0000675 std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
676
Justin Bogner43e51632015-02-26 20:06:28 +0000677 StringRef Coverage;
678 uint8_t BytesInAddress;
Justin Bognera4387172015-03-16 21:40:18 +0000679 support::endianness Endian;
Mehdi Amini41af4302016-11-11 04:28:40 +0000680 Error E = Error::success();
Vedant Kumar9152fd12016-05-19 03:54:45 +0000681 consumeError(std::move(E));
Vedant Kumara30139d2016-06-29 05:33:24 +0000682 if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
Justin Bogner43e51632015-02-26 20:06:28 +0000683 // This is a special format used for testing.
Vedant Kumara30139d2016-06-29 05:33:24 +0000684 E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames,
Vedant Kumar9152fd12016-05-19 03:54:45 +0000685 Coverage, BytesInAddress, Endian);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000686 else
Vedant Kumara30139d2016-06-29 05:33:24 +0000687 E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames,
Vedant Kumar9152fd12016-05-19 03:54:45 +0000688 Coverage, BytesInAddress, Endian, Arch);
689 if (E)
690 return std::move(E);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000691
Justin Bognera4387172015-03-16 21:40:18 +0000692 if (BytesInAddress == 4 && Endian == support::endianness::little)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000693 E = readCoverageMappingData<uint32_t, support::endianness::little>(
Xinliang David Li42a13302016-01-18 06:48:01 +0000694 Reader->ProfileNames, Coverage, Reader->MappingRecords,
695 Reader->Filenames);
Justin Bognera4387172015-03-16 21:40:18 +0000696 else if (BytesInAddress == 4 && Endian == support::endianness::big)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000697 E = readCoverageMappingData<uint32_t, support::endianness::big>(
Xinliang David Li42a13302016-01-18 06:48:01 +0000698 Reader->ProfileNames, Coverage, Reader->MappingRecords,
699 Reader->Filenames);
Justin Bognera4387172015-03-16 21:40:18 +0000700 else if (BytesInAddress == 8 && Endian == support::endianness::little)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000701 E = readCoverageMappingData<uint64_t, support::endianness::little>(
Xinliang David Li42a13302016-01-18 06:48:01 +0000702 Reader->ProfileNames, Coverage, Reader->MappingRecords,
703 Reader->Filenames);
Justin Bognera4387172015-03-16 21:40:18 +0000704 else if (BytesInAddress == 8 && Endian == support::endianness::big)
Vedant Kumar9152fd12016-05-19 03:54:45 +0000705 E = readCoverageMappingData<uint64_t, support::endianness::big>(
Xinliang David Li42a13302016-01-18 06:48:01 +0000706 Reader->ProfileNames, Coverage, Reader->MappingRecords,
707 Reader->Filenames);
Justin Bogner43e51632015-02-26 20:06:28 +0000708 else
Vedant Kumar9152fd12016-05-19 03:54:45 +0000709 return make_error<CoverageMapError>(coveragemap_error::malformed);
710 if (E)
711 return std::move(E);
Justin Bogner43e51632015-02-26 20:06:28 +0000712 return std::move(Reader);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000713}
714
Vedant Kumar9152fd12016-05-19 03:54:45 +0000715Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
Alex Lorenza20a5d52014-07-24 23:57:54 +0000716 if (CurrentRecord >= MappingRecords.size())
Vedant Kumar9152fd12016-05-19 03:54:45 +0000717 return make_error<CoverageMapError>(coveragemap_error::eof);
Alex Lorenza20a5d52014-07-24 23:57:54 +0000718
719 FunctionsFilenames.clear();
720 Expressions.clear();
721 MappingRegions.clear();
722 auto &R = MappingRecords[CurrentRecord];
723 RawCoverageMappingReader Reader(
Justin Bogner195a4f02015-02-03 00:20:11 +0000724 R.CoverageMapping,
Justin Bogner346359d2015-02-03 00:00:00 +0000725 makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
Alex Lorenza20a5d52014-07-24 23:57:54 +0000726 FunctionsFilenames, Expressions, MappingRegions);
Justin Bogner195a4f02015-02-03 00:20:11 +0000727 if (auto Err = Reader.read())
Alex Lorenza20a5d52014-07-24 23:57:54 +0000728 return Err;
Justin Bogner195a4f02015-02-03 00:20:11 +0000729
730 Record.FunctionName = R.FunctionName;
Alex Lorenz936b99c2014-08-21 19:23:25 +0000731 Record.FunctionHash = R.FunctionHash;
Justin Bogner195a4f02015-02-03 00:20:11 +0000732 Record.Filenames = FunctionsFilenames;
733 Record.Expressions = Expressions;
734 Record.MappingRegions = MappingRegions;
735
Alex Lorenza20a5d52014-07-24 23:57:54 +0000736 ++CurrentRecord;
Vedant Kumar9152fd12016-05-19 03:54:45 +0000737 return Error::success();
Alex Lorenza20a5d52014-07-24 23:57:54 +0000738}