1 //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains support for reading coverage mapping data for
11 // instrumentation based coverage.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/Triple.h"
22 #include "llvm/Object/Binary.h"
23 #include "llvm/Object/Error.h"
24 #include "llvm/Object/MachOUniversal.h"
25 #include "llvm/Object/ObjectFile.h"
26 #include "llvm/ProfileData/InstrProf.h"
27 #include "llvm/Support/Casting.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/Endian.h"
30 #include "llvm/Support/Error.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/LEB128.h"
33 #include "llvm/Support/MathExtras.h"
34 #include "llvm/Support/raw_ostream.h"
38 using namespace coverage
;
39 using namespace object
;
41 #define DEBUG_TYPE "coverage-mapping"
43 void CoverageMappingIterator::increment() {
44 if (ReadErr
!= coveragemap_error::success
)
47 // Check if all the records were read or if an error occurred while reading
49 if (auto E
= Reader
->readNextRecord(Record
))
50 handleAllErrors(std::move(E
), [&](const CoverageMapError
&CME
) {
51 if (CME
.get() == coveragemap_error::eof
)
52 *this = CoverageMappingIterator();
58 Error
RawCoverageReader::readULEB128(uint64_t &Result
) {
60 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
62 Result
= decodeULEB128(reinterpret_cast<const uint8_t *>(Data
.data()), &N
);
64 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
65 Data
= Data
.substr(N
);
66 return Error::success();
69 Error
RawCoverageReader::readIntMax(uint64_t &Result
, uint64_t MaxPlus1
) {
70 if (auto Err
= readULEB128(Result
))
72 if (Result
>= MaxPlus1
)
73 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
74 return Error::success();
77 Error
RawCoverageReader::readSize(uint64_t &Result
) {
78 if (auto Err
= readULEB128(Result
))
80 // Sanity check the number.
81 if (Result
> Data
.size())
82 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
83 return Error::success();
86 Error
RawCoverageReader::readString(StringRef
&Result
) {
88 if (auto Err
= readSize(Length
))
90 Result
= Data
.substr(0, Length
);
91 Data
= Data
.substr(Length
);
92 return Error::success();
95 Error
RawCoverageFilenamesReader::read() {
96 uint64_t NumFilenames
;
97 if (auto Err
= readSize(NumFilenames
))
99 for (size_t I
= 0; I
< NumFilenames
; ++I
) {
101 if (auto Err
= readString(Filename
))
103 Filenames
.push_back(Filename
);
105 return Error::success();
108 Error
RawCoverageMappingReader::decodeCounter(unsigned Value
, Counter
&C
) {
109 auto Tag
= Value
& Counter::EncodingTagMask
;
112 C
= Counter::getZero();
113 return Error::success();
114 case Counter::CounterValueReference
:
115 C
= Counter::getCounter(Value
>> Counter::EncodingTagBits
);
116 return Error::success();
120 Tag
-= Counter::Expression
;
122 case CounterExpression::Subtract
:
123 case CounterExpression::Add
: {
124 auto ID
= Value
>> Counter::EncodingTagBits
;
125 if (ID
>= Expressions
.size())
126 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
127 Expressions
[ID
].Kind
= CounterExpression::ExprKind(Tag
);
128 C
= Counter::getExpression(ID
);
132 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
134 return Error::success();
137 Error
RawCoverageMappingReader::readCounter(Counter
&C
) {
138 uint64_t EncodedCounter
;
140 readIntMax(EncodedCounter
, std::numeric_limits
<unsigned>::max()))
142 if (auto Err
= decodeCounter(EncodedCounter
, C
))
144 return Error::success();
147 static const unsigned EncodingExpansionRegionBit
= 1
148 << Counter::EncodingTagBits
;
150 /// Read the sub-array of regions for the given inferred file id.
151 /// \param NumFileIDs the number of file ids that are defined for this
153 Error
RawCoverageMappingReader::readMappingRegionsSubArray(
154 std::vector
<CounterMappingRegion
> &MappingRegions
, unsigned InferredFileID
,
157 if (auto Err
= readSize(NumRegions
))
159 unsigned LineStart
= 0;
160 for (size_t I
= 0; I
< NumRegions
; ++I
) {
162 CounterMappingRegion::RegionKind Kind
= CounterMappingRegion::CodeRegion
;
164 // Read the combined counter + region kind.
165 uint64_t EncodedCounterAndRegion
;
166 if (auto Err
= readIntMax(EncodedCounterAndRegion
,
167 std::numeric_limits
<unsigned>::max()))
169 unsigned Tag
= EncodedCounterAndRegion
& Counter::EncodingTagMask
;
170 uint64_t ExpandedFileID
= 0;
171 if (Tag
!= Counter::Zero
) {
172 if (auto Err
= decodeCounter(EncodedCounterAndRegion
, C
))
175 // Is it an expansion region?
176 if (EncodedCounterAndRegion
& EncodingExpansionRegionBit
) {
177 Kind
= CounterMappingRegion::ExpansionRegion
;
178 ExpandedFileID
= EncodedCounterAndRegion
>>
179 Counter::EncodingCounterTagAndExpansionRegionTagBits
;
180 if (ExpandedFileID
>= NumFileIDs
)
181 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
183 switch (EncodedCounterAndRegion
>>
184 Counter::EncodingCounterTagAndExpansionRegionTagBits
) {
185 case CounterMappingRegion::CodeRegion
:
186 // Don't do anything when we have a code region with a zero counter.
188 case CounterMappingRegion::SkippedRegion
:
189 Kind
= CounterMappingRegion::SkippedRegion
;
192 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
197 // Read the source range.
198 uint64_t LineStartDelta
, ColumnStart
, NumLines
, ColumnEnd
;
200 readIntMax(LineStartDelta
, std::numeric_limits
<unsigned>::max()))
202 if (auto Err
= readULEB128(ColumnStart
))
204 if (ColumnStart
> std::numeric_limits
<unsigned>::max())
205 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
206 if (auto Err
= readIntMax(NumLines
, std::numeric_limits
<unsigned>::max()))
208 if (auto Err
= readIntMax(ColumnEnd
, std::numeric_limits
<unsigned>::max()))
210 LineStart
+= LineStartDelta
;
212 // If the high bit of ColumnEnd is set, this is a gap region.
213 if (ColumnEnd
& (1U << 31)) {
214 Kind
= CounterMappingRegion::GapRegion
;
215 ColumnEnd
&= ~(1U << 31);
218 // Adjust the column locations for the empty regions that are supposed to
219 // cover whole lines. Those regions should be encoded with the
220 // column range (1 -> std::numeric_limits<unsigned>::max()), but because
221 // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
222 // we set the column range to (0 -> 0) to ensure that the column start and
223 // column end take up one byte each.
224 // The std::numeric_limits<unsigned>::max() is used to represent a column
225 // position at the end of the line without knowing the length of that line.
226 if (ColumnStart
== 0 && ColumnEnd
== 0) {
228 ColumnEnd
= std::numeric_limits
<unsigned>::max();
232 dbgs() << "Counter in file " << InferredFileID
<< " " << LineStart
<< ":"
233 << ColumnStart
<< " -> " << (LineStart
+ NumLines
) << ":"
234 << ColumnEnd
<< ", ";
235 if (Kind
== CounterMappingRegion::ExpansionRegion
)
236 dbgs() << "Expands to file " << ExpandedFileID
;
238 CounterMappingContext(Expressions
).dump(C
, dbgs());
242 auto CMR
= CounterMappingRegion(C
, InferredFileID
, ExpandedFileID
,
243 LineStart
, ColumnStart
,
244 LineStart
+ NumLines
, ColumnEnd
, Kind
);
245 if (CMR
.startLoc() > CMR
.endLoc())
246 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
247 MappingRegions
.push_back(CMR
);
249 return Error::success();
252 Error
RawCoverageMappingReader::read() {
253 // Read the virtual file mapping.
254 SmallVector
<unsigned, 8> VirtualFileMapping
;
255 uint64_t NumFileMappings
;
256 if (auto Err
= readSize(NumFileMappings
))
258 for (size_t I
= 0; I
< NumFileMappings
; ++I
) {
259 uint64_t FilenameIndex
;
260 if (auto Err
= readIntMax(FilenameIndex
, TranslationUnitFilenames
.size()))
262 VirtualFileMapping
.push_back(FilenameIndex
);
265 // Construct the files using unique filenames and virtual file mapping.
266 for (auto I
: VirtualFileMapping
) {
267 Filenames
.push_back(TranslationUnitFilenames
[I
]);
270 // Read the expressions.
271 uint64_t NumExpressions
;
272 if (auto Err
= readSize(NumExpressions
))
274 // Create an array of dummy expressions that get the proper counters
275 // when the expressions are read, and the proper kinds when the counters
279 CounterExpression(CounterExpression::Subtract
, Counter(), Counter()));
280 for (size_t I
= 0; I
< NumExpressions
; ++I
) {
281 if (auto Err
= readCounter(Expressions
[I
].LHS
))
283 if (auto Err
= readCounter(Expressions
[I
].RHS
))
287 // Read the mapping regions sub-arrays.
288 for (unsigned InferredFileID
= 0, S
= VirtualFileMapping
.size();
289 InferredFileID
< S
; ++InferredFileID
) {
290 if (auto Err
= readMappingRegionsSubArray(MappingRegions
, InferredFileID
,
291 VirtualFileMapping
.size()))
295 // Set the counters for the expansion regions.
296 // i.e. Counter of expansion region = counter of the first region
297 // from the expanded file.
298 // Perform multiple passes to correctly propagate the counters through
299 // all the nested expansion regions.
300 SmallVector
<CounterMappingRegion
*, 8> FileIDExpansionRegionMapping
;
301 FileIDExpansionRegionMapping
.resize(VirtualFileMapping
.size(), nullptr);
302 for (unsigned Pass
= 1, S
= VirtualFileMapping
.size(); Pass
< S
; ++Pass
) {
303 for (auto &R
: MappingRegions
) {
304 if (R
.Kind
!= CounterMappingRegion::ExpansionRegion
)
306 assert(!FileIDExpansionRegionMapping
[R
.ExpandedFileID
]);
307 FileIDExpansionRegionMapping
[R
.ExpandedFileID
] = &R
;
309 for (auto &R
: MappingRegions
) {
310 if (FileIDExpansionRegionMapping
[R
.FileID
]) {
311 FileIDExpansionRegionMapping
[R
.FileID
]->Count
= R
.Count
;
312 FileIDExpansionRegionMapping
[R
.FileID
] = nullptr;
317 return Error::success();
320 Expected
<bool> RawCoverageMappingDummyChecker::isDummy() {
321 // A dummy coverage mapping data consists of just one region with zero count.
322 uint64_t NumFileMappings
;
323 if (Error Err
= readSize(NumFileMappings
))
324 return std::move(Err
);
325 if (NumFileMappings
!= 1)
327 // We don't expect any specific value for the filename index, just skip it.
328 uint64_t FilenameIndex
;
330 readIntMax(FilenameIndex
, std::numeric_limits
<unsigned>::max()))
331 return std::move(Err
);
332 uint64_t NumExpressions
;
333 if (Error Err
= readSize(NumExpressions
))
334 return std::move(Err
);
335 if (NumExpressions
!= 0)
338 if (Error Err
= readSize(NumRegions
))
339 return std::move(Err
);
342 uint64_t EncodedCounterAndRegion
;
343 if (Error Err
= readIntMax(EncodedCounterAndRegion
,
344 std::numeric_limits
<unsigned>::max()))
345 return std::move(Err
);
346 unsigned Tag
= EncodedCounterAndRegion
& Counter::EncodingTagMask
;
347 return Tag
== Counter::Zero
;
350 Error
InstrProfSymtab::create(SectionRef
&Section
) {
351 if (auto EC
= Section
.getContents(Data
))
352 return errorCodeToError(EC
);
353 Address
= Section
.getAddress();
354 return Error::success();
357 StringRef
InstrProfSymtab::getFuncName(uint64_t Pointer
, size_t Size
) {
358 if (Pointer
< Address
)
360 auto Offset
= Pointer
- Address
;
361 if (Offset
+ Size
> Data
.size())
363 return Data
.substr(Pointer
- Address
, Size
);
366 // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
367 static Expected
<bool> isCoverageMappingDummy(uint64_t Hash
, StringRef Mapping
) {
368 // The hash value of dummy mapping records is always zero.
371 return RawCoverageMappingDummyChecker(Mapping
).isDummy();
376 struct CovMapFuncRecordReader
{
377 virtual ~CovMapFuncRecordReader() = default;
379 // The interface to read coverage mapping function records for a module.
381 // \p Buf points to the buffer containing the \c CovHeader of the coverage
382 // mapping data associated with the module.
384 // Returns a pointer to the next \c CovHeader if it exists, or a pointer
385 // greater than \p End if not.
386 virtual Expected
<const char *> readFunctionRecords(const char *Buf
,
387 const char *End
) = 0;
389 template <class IntPtrT
, support::endianness Endian
>
390 static Expected
<std::unique_ptr
<CovMapFuncRecordReader
>>
391 get(CovMapVersion Version
, InstrProfSymtab
&P
,
392 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &R
,
393 std::vector
<StringRef
> &F
);
396 // A class for reading coverage mapping function records for a module.
397 template <CovMapVersion Version
, class IntPtrT
, support::endianness Endian
>
398 class VersionedCovMapFuncRecordReader
: public CovMapFuncRecordReader
{
399 using FuncRecordType
=
400 typename CovMapTraits
<Version
, IntPtrT
>::CovMapFuncRecordType
;
401 using NameRefType
= typename CovMapTraits
<Version
, IntPtrT
>::NameRefType
;
403 // Maps function's name references to the indexes of their records
405 DenseMap
<NameRefType
, size_t> FunctionRecords
;
406 InstrProfSymtab
&ProfileNames
;
407 std::vector
<StringRef
> &Filenames
;
408 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &Records
;
410 // Add the record to the collection if we don't already have a record that
411 // points to the same function name. This is useful to ignore the redundant
412 // records for the functions with ODR linkage.
413 // In addition, prefer records with real coverage mapping data to dummy
414 // records, which were emitted for inline functions which were seen but
415 // not used in the corresponding translation unit.
416 Error
insertFunctionRecordIfNeeded(const FuncRecordType
*CFR
,
417 StringRef Mapping
, size_t FilenamesBegin
) {
418 uint64_t FuncHash
= CFR
->template getFuncHash
<Endian
>();
419 NameRefType NameRef
= CFR
->template getFuncNameRef
<Endian
>();
421 FunctionRecords
.insert(std::make_pair(NameRef
, Records
.size()));
422 if (InsertResult
.second
) {
424 if (Error Err
= CFR
->template getFuncName
<Endian
>(ProfileNames
, FuncName
))
426 if (FuncName
.empty())
427 return make_error
<InstrProfError
>(instrprof_error::malformed
);
428 Records
.emplace_back(Version
, FuncName
, FuncHash
, Mapping
, FilenamesBegin
,
429 Filenames
.size() - FilenamesBegin
);
430 return Error::success();
432 // Update the existing record if it's a dummy and the new record is real.
433 size_t OldRecordIndex
= InsertResult
.first
->second
;
434 BinaryCoverageReader::ProfileMappingRecord
&OldRecord
=
435 Records
[OldRecordIndex
];
436 Expected
<bool> OldIsDummyExpected
= isCoverageMappingDummy(
437 OldRecord
.FunctionHash
, OldRecord
.CoverageMapping
);
438 if (Error Err
= OldIsDummyExpected
.takeError())
440 if (!*OldIsDummyExpected
)
441 return Error::success();
442 Expected
<bool> NewIsDummyExpected
=
443 isCoverageMappingDummy(FuncHash
, Mapping
);
444 if (Error Err
= NewIsDummyExpected
.takeError())
446 if (*NewIsDummyExpected
)
447 return Error::success();
448 OldRecord
.FunctionHash
= FuncHash
;
449 OldRecord
.CoverageMapping
= Mapping
;
450 OldRecord
.FilenamesBegin
= FilenamesBegin
;
451 OldRecord
.FilenamesSize
= Filenames
.size() - FilenamesBegin
;
452 return Error::success();
456 VersionedCovMapFuncRecordReader(
458 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &R
,
459 std::vector
<StringRef
> &F
)
460 : ProfileNames(P
), Filenames(F
), Records(R
) {}
462 ~VersionedCovMapFuncRecordReader() override
= default;
464 Expected
<const char *> readFunctionRecords(const char *Buf
,
465 const char *End
) override
{
466 using namespace support
;
468 if (Buf
+ sizeof(CovMapHeader
) > End
)
469 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
470 auto CovHeader
= reinterpret_cast<const CovMapHeader
*>(Buf
);
471 uint32_t NRecords
= CovHeader
->getNRecords
<Endian
>();
472 uint32_t FilenamesSize
= CovHeader
->getFilenamesSize
<Endian
>();
473 uint32_t CoverageSize
= CovHeader
->getCoverageSize
<Endian
>();
474 assert((CovMapVersion
)CovHeader
->getVersion
<Endian
>() == Version
);
475 Buf
= reinterpret_cast<const char *>(CovHeader
+ 1);
477 // Skip past the function records, saving the start and end for later.
478 const char *FunBuf
= Buf
;
479 Buf
+= NRecords
* sizeof(FuncRecordType
);
480 const char *FunEnd
= Buf
;
482 // Get the filenames.
483 if (Buf
+ FilenamesSize
> End
)
484 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
485 size_t FilenamesBegin
= Filenames
.size();
486 RawCoverageFilenamesReader
Reader(StringRef(Buf
, FilenamesSize
), Filenames
);
487 if (auto Err
= Reader
.read())
488 return std::move(Err
);
489 Buf
+= FilenamesSize
;
491 // We'll read the coverage mapping records in the loop below.
492 const char *CovBuf
= Buf
;
494 const char *CovEnd
= Buf
;
497 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
498 // Each coverage map has an alignment of 8, so we need to adjust alignment
499 // before reading the next map.
500 Buf
+= alignmentAdjustment(Buf
, 8);
502 auto CFR
= reinterpret_cast<const FuncRecordType
*>(FunBuf
);
503 while ((const char *)CFR
< FunEnd
) {
504 // Read the function information
505 uint32_t DataSize
= CFR
->template getDataSize
<Endian
>();
507 // Now use that to read the coverage data.
508 if (CovBuf
+ DataSize
> CovEnd
)
509 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
510 auto Mapping
= StringRef(CovBuf
, DataSize
);
514 insertFunctionRecordIfNeeded(CFR
, Mapping
, FilenamesBegin
))
515 return std::move(Err
);
522 } // end anonymous namespace
524 template <class IntPtrT
, support::endianness Endian
>
525 Expected
<std::unique_ptr
<CovMapFuncRecordReader
>> CovMapFuncRecordReader::get(
526 CovMapVersion Version
, InstrProfSymtab
&P
,
527 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &R
,
528 std::vector
<StringRef
> &F
) {
529 using namespace coverage
;
532 case CovMapVersion::Version1
:
533 return llvm::make_unique
<VersionedCovMapFuncRecordReader
<
534 CovMapVersion::Version1
, IntPtrT
, Endian
>>(P
, R
, F
);
535 case CovMapVersion::Version2
:
536 case CovMapVersion::Version3
:
537 // Decompress the name data.
538 if (Error E
= P
.create(P
.getNameData()))
540 if (Version
== CovMapVersion::Version2
)
541 return llvm::make_unique
<VersionedCovMapFuncRecordReader
<
542 CovMapVersion::Version2
, IntPtrT
, Endian
>>(P
, R
, F
);
544 return llvm::make_unique
<VersionedCovMapFuncRecordReader
<
545 CovMapVersion::Version3
, IntPtrT
, Endian
>>(P
, R
, F
);
547 llvm_unreachable("Unsupported version");
550 template <typename T
, support::endianness Endian
>
551 static Error
readCoverageMappingData(
552 InstrProfSymtab
&ProfileNames
, StringRef Data
,
553 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &Records
,
554 std::vector
<StringRef
> &Filenames
) {
555 using namespace coverage
;
557 // Read the records in the coverage data section.
559 reinterpret_cast<const CovMapHeader
*>(Data
.data());
560 CovMapVersion Version
= (CovMapVersion
)CovHeader
->getVersion
<Endian
>();
561 if (Version
> CovMapVersion::CurrentVersion
)
562 return make_error
<CoverageMapError
>(coveragemap_error::unsupported_version
);
563 Expected
<std::unique_ptr
<CovMapFuncRecordReader
>> ReaderExpected
=
564 CovMapFuncRecordReader::get
<T
, Endian
>(Version
, ProfileNames
, Records
,
566 if (Error E
= ReaderExpected
.takeError())
568 auto Reader
= std::move(ReaderExpected
.get());
569 for (const char *Buf
= Data
.data(), *End
= Buf
+ Data
.size(); Buf
< End
;) {
570 auto NextHeaderOrErr
= Reader
->readFunctionRecords(Buf
, End
);
571 if (auto E
= NextHeaderOrErr
.takeError())
573 Buf
= NextHeaderOrErr
.get();
575 return Error::success();
578 static const char *TestingFormatMagic
= "llvmcovmtestdata";
580 static Error
loadTestingFormat(StringRef Data
, InstrProfSymtab
&ProfileNames
,
581 StringRef
&CoverageMapping
,
582 uint8_t &BytesInAddress
,
583 support::endianness
&Endian
) {
585 Endian
= support::endianness::little
;
587 Data
= Data
.substr(StringRef(TestingFormatMagic
).size());
589 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
591 auto ProfileNamesSize
=
592 decodeULEB128(reinterpret_cast<const uint8_t *>(Data
.data()), &N
);
594 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
595 Data
= Data
.substr(N
);
597 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
600 decodeULEB128(reinterpret_cast<const uint8_t *>(Data
.data()), &N
);
602 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
603 Data
= Data
.substr(N
);
604 if (Data
.size() < ProfileNamesSize
)
605 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
606 if (Error E
= ProfileNames
.create(Data
.substr(0, ProfileNamesSize
), Address
))
608 CoverageMapping
= Data
.substr(ProfileNamesSize
);
609 // Skip the padding bytes because coverage map data has an alignment of 8.
610 if (CoverageMapping
.empty())
611 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
612 size_t Pad
= alignmentAdjustment(CoverageMapping
.data(), 8);
613 if (CoverageMapping
.size() < Pad
)
614 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
615 CoverageMapping
= CoverageMapping
.substr(Pad
);
616 return Error::success();
619 static Expected
<SectionRef
> lookupSection(ObjectFile
&OF
, StringRef Name
) {
621 for (const auto &Section
: OF
.sections()) {
622 if (auto EC
= Section
.getName(FoundName
))
623 return errorCodeToError(EC
);
624 if (FoundName
== Name
)
627 return make_error
<CoverageMapError
>(coveragemap_error::no_data_found
);
630 static Error
loadBinaryFormat(MemoryBufferRef ObjectBuffer
,
631 InstrProfSymtab
&ProfileNames
,
632 StringRef
&CoverageMapping
,
633 uint8_t &BytesInAddress
,
634 support::endianness
&Endian
, StringRef Arch
) {
635 auto BinOrErr
= createBinary(ObjectBuffer
);
637 return BinOrErr
.takeError();
638 auto Bin
= std::move(BinOrErr
.get());
639 std::unique_ptr
<ObjectFile
> OF
;
640 if (auto *Universal
= dyn_cast
<MachOUniversalBinary
>(Bin
.get())) {
641 // If we have a universal binary, try to look up the object for the
642 // appropriate architecture.
643 auto ObjectFileOrErr
= Universal
->getObjectForArch(Arch
);
644 if (!ObjectFileOrErr
)
645 return ObjectFileOrErr
.takeError();
646 OF
= std::move(ObjectFileOrErr
.get());
647 } else if (isa
<ObjectFile
>(Bin
.get())) {
648 // For any other object file, upcast and take ownership.
649 OF
.reset(cast
<ObjectFile
>(Bin
.release()));
650 // If we've asked for a particular arch, make sure they match.
651 if (!Arch
.empty() && OF
->getArch() != Triple(Arch
).getArch())
652 return errorCodeToError(object_error::arch_not_found
);
654 // We can only handle object files.
655 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
657 // The coverage uses native pointer sizes for the object it's written in.
658 BytesInAddress
= OF
->getBytesInAddress();
659 Endian
= OF
->isLittleEndian() ? support::endianness::little
660 : support::endianness::big
;
662 // Look for the sections that we are interested in.
663 auto ObjFormat
= OF
->getTripleObjectFormat();
665 lookupSection(*OF
, getInstrProfSectionName(IPSK_name
, ObjFormat
,
666 /*AddSegmentInfo=*/false));
667 if (auto E
= NamesSection
.takeError())
669 auto CoverageSection
=
670 lookupSection(*OF
, getInstrProfSectionName(IPSK_covmap
, ObjFormat
,
671 /*AddSegmentInfo=*/false));
672 if (auto E
= CoverageSection
.takeError())
675 // Get the contents of the given sections.
676 if (auto EC
= CoverageSection
->getContents(CoverageMapping
))
677 return errorCodeToError(EC
);
678 if (Error E
= ProfileNames
.create(*NamesSection
))
681 return Error::success();
684 Expected
<std::unique_ptr
<BinaryCoverageReader
>>
685 BinaryCoverageReader::create(std::unique_ptr
<MemoryBuffer
> &ObjectBuffer
,
687 std::unique_ptr
<BinaryCoverageReader
> Reader(new BinaryCoverageReader());
690 uint8_t BytesInAddress
;
691 support::endianness Endian
;
692 Error E
= Error::success();
693 consumeError(std::move(E
));
694 if (ObjectBuffer
->getBuffer().startswith(TestingFormatMagic
))
695 // This is a special format used for testing.
696 E
= loadTestingFormat(ObjectBuffer
->getBuffer(), Reader
->ProfileNames
,
697 Coverage
, BytesInAddress
, Endian
);
699 E
= loadBinaryFormat(ObjectBuffer
->getMemBufferRef(), Reader
->ProfileNames
,
700 Coverage
, BytesInAddress
, Endian
, Arch
);
704 if (BytesInAddress
== 4 && Endian
== support::endianness::little
)
705 E
= readCoverageMappingData
<uint32_t, support::endianness::little
>(
706 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
708 else if (BytesInAddress
== 4 && Endian
== support::endianness::big
)
709 E
= readCoverageMappingData
<uint32_t, support::endianness::big
>(
710 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
712 else if (BytesInAddress
== 8 && Endian
== support::endianness::little
)
713 E
= readCoverageMappingData
<uint64_t, support::endianness::little
>(
714 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
716 else if (BytesInAddress
== 8 && Endian
== support::endianness::big
)
717 E
= readCoverageMappingData
<uint64_t, support::endianness::big
>(
718 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
721 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
724 return std::move(Reader
);
727 Error
BinaryCoverageReader::readNextRecord(CoverageMappingRecord
&Record
) {
728 if (CurrentRecord
>= MappingRecords
.size())
729 return make_error
<CoverageMapError
>(coveragemap_error::eof
);
731 FunctionsFilenames
.clear();
733 MappingRegions
.clear();
734 auto &R
= MappingRecords
[CurrentRecord
];
735 RawCoverageMappingReader
Reader(
737 makeArrayRef(Filenames
).slice(R
.FilenamesBegin
, R
.FilenamesSize
),
738 FunctionsFilenames
, Expressions
, MappingRegions
);
739 if (auto Err
= Reader
.read())
742 Record
.FunctionName
= R
.FunctionName
;
743 Record
.FunctionHash
= R
.FunctionHash
;
744 Record
.Filenames
= FunctionsFilenames
;
745 Record
.Expressions
= Expressions
;
746 Record
.MappingRegions
= MappingRegions
;
749 return Error::success();