1 //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains support for reading coverage mapping data for
10 // instrumentation based coverage.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallVector.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"
23 #include "llvm/Object/MachOUniversal.h"
24 #include "llvm/Object/ObjectFile.h"
25 #include "llvm/ProfileData/InstrProf.h"
26 #include "llvm/Support/Casting.h"
27 #include "llvm/Support/Debug.h"
28 #include "llvm/Support/Endian.h"
29 #include "llvm/Support/Error.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/LEB128.h"
32 #include "llvm/Support/MathExtras.h"
33 #include "llvm/Support/raw_ostream.h"
37 using namespace coverage
;
38 using namespace object
;
40 #define DEBUG_TYPE "coverage-mapping"
42 void CoverageMappingIterator::increment() {
43 if (ReadErr
!= coveragemap_error::success
)
46 // Check if all the records were read or if an error occurred while reading
48 if (auto E
= Reader
->readNextRecord(Record
))
49 handleAllErrors(std::move(E
), [&](const CoverageMapError
&CME
) {
50 if (CME
.get() == coveragemap_error::eof
)
51 *this = CoverageMappingIterator();
57 Error
RawCoverageReader::readULEB128(uint64_t &Result
) {
59 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
61 Result
= decodeULEB128(reinterpret_cast<const uint8_t *>(Data
.data()), &N
);
63 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
64 Data
= Data
.substr(N
);
65 return Error::success();
68 Error
RawCoverageReader::readIntMax(uint64_t &Result
, uint64_t MaxPlus1
) {
69 if (auto Err
= readULEB128(Result
))
71 if (Result
>= MaxPlus1
)
72 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
73 return Error::success();
76 Error
RawCoverageReader::readSize(uint64_t &Result
) {
77 if (auto Err
= readULEB128(Result
))
79 // Sanity check the number.
80 if (Result
> Data
.size())
81 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
82 return Error::success();
85 Error
RawCoverageReader::readString(StringRef
&Result
) {
87 if (auto Err
= readSize(Length
))
89 Result
= Data
.substr(0, Length
);
90 Data
= Data
.substr(Length
);
91 return Error::success();
94 Error
RawCoverageFilenamesReader::read() {
95 uint64_t NumFilenames
;
96 if (auto Err
= readSize(NumFilenames
))
98 for (size_t I
= 0; I
< NumFilenames
; ++I
) {
100 if (auto Err
= readString(Filename
))
102 Filenames
.push_back(Filename
);
104 return Error::success();
107 Error
RawCoverageMappingReader::decodeCounter(unsigned Value
, Counter
&C
) {
108 auto Tag
= Value
& Counter::EncodingTagMask
;
111 C
= Counter::getZero();
112 return Error::success();
113 case Counter::CounterValueReference
:
114 C
= Counter::getCounter(Value
>> Counter::EncodingTagBits
);
115 return Error::success();
119 Tag
-= Counter::Expression
;
121 case CounterExpression::Subtract
:
122 case CounterExpression::Add
: {
123 auto ID
= Value
>> Counter::EncodingTagBits
;
124 if (ID
>= Expressions
.size())
125 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
126 Expressions
[ID
].Kind
= CounterExpression::ExprKind(Tag
);
127 C
= Counter::getExpression(ID
);
131 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
133 return Error::success();
136 Error
RawCoverageMappingReader::readCounter(Counter
&C
) {
137 uint64_t EncodedCounter
;
139 readIntMax(EncodedCounter
, std::numeric_limits
<unsigned>::max()))
141 if (auto Err
= decodeCounter(EncodedCounter
, C
))
143 return Error::success();
146 static const unsigned EncodingExpansionRegionBit
= 1
147 << Counter::EncodingTagBits
;
149 /// Read the sub-array of regions for the given inferred file id.
150 /// \param NumFileIDs the number of file ids that are defined for this
152 Error
RawCoverageMappingReader::readMappingRegionsSubArray(
153 std::vector
<CounterMappingRegion
> &MappingRegions
, unsigned InferredFileID
,
156 if (auto Err
= readSize(NumRegions
))
158 unsigned LineStart
= 0;
159 for (size_t I
= 0; I
< NumRegions
; ++I
) {
161 CounterMappingRegion::RegionKind Kind
= CounterMappingRegion::CodeRegion
;
163 // Read the combined counter + region kind.
164 uint64_t EncodedCounterAndRegion
;
165 if (auto Err
= readIntMax(EncodedCounterAndRegion
,
166 std::numeric_limits
<unsigned>::max()))
168 unsigned Tag
= EncodedCounterAndRegion
& Counter::EncodingTagMask
;
169 uint64_t ExpandedFileID
= 0;
170 if (Tag
!= Counter::Zero
) {
171 if (auto Err
= decodeCounter(EncodedCounterAndRegion
, C
))
174 // Is it an expansion region?
175 if (EncodedCounterAndRegion
& EncodingExpansionRegionBit
) {
176 Kind
= CounterMappingRegion::ExpansionRegion
;
177 ExpandedFileID
= EncodedCounterAndRegion
>>
178 Counter::EncodingCounterTagAndExpansionRegionTagBits
;
179 if (ExpandedFileID
>= NumFileIDs
)
180 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
182 switch (EncodedCounterAndRegion
>>
183 Counter::EncodingCounterTagAndExpansionRegionTagBits
) {
184 case CounterMappingRegion::CodeRegion
:
185 // Don't do anything when we have a code region with a zero counter.
187 case CounterMappingRegion::SkippedRegion
:
188 Kind
= CounterMappingRegion::SkippedRegion
;
191 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
196 // Read the source range.
197 uint64_t LineStartDelta
, ColumnStart
, NumLines
, ColumnEnd
;
199 readIntMax(LineStartDelta
, std::numeric_limits
<unsigned>::max()))
201 if (auto Err
= readULEB128(ColumnStart
))
203 if (ColumnStart
> std::numeric_limits
<unsigned>::max())
204 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
205 if (auto Err
= readIntMax(NumLines
, std::numeric_limits
<unsigned>::max()))
207 if (auto Err
= readIntMax(ColumnEnd
, std::numeric_limits
<unsigned>::max()))
209 LineStart
+= LineStartDelta
;
211 // If the high bit of ColumnEnd is set, this is a gap region.
212 if (ColumnEnd
& (1U << 31)) {
213 Kind
= CounterMappingRegion::GapRegion
;
214 ColumnEnd
&= ~(1U << 31);
217 // Adjust the column locations for the empty regions that are supposed to
218 // cover whole lines. Those regions should be encoded with the
219 // column range (1 -> std::numeric_limits<unsigned>::max()), but because
220 // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
221 // we set the column range to (0 -> 0) to ensure that the column start and
222 // column end take up one byte each.
223 // The std::numeric_limits<unsigned>::max() is used to represent a column
224 // position at the end of the line without knowing the length of that line.
225 if (ColumnStart
== 0 && ColumnEnd
== 0) {
227 ColumnEnd
= std::numeric_limits
<unsigned>::max();
231 dbgs() << "Counter in file " << InferredFileID
<< " " << LineStart
<< ":"
232 << ColumnStart
<< " -> " << (LineStart
+ NumLines
) << ":"
233 << ColumnEnd
<< ", ";
234 if (Kind
== CounterMappingRegion::ExpansionRegion
)
235 dbgs() << "Expands to file " << ExpandedFileID
;
237 CounterMappingContext(Expressions
).dump(C
, dbgs());
241 auto CMR
= CounterMappingRegion(C
, InferredFileID
, ExpandedFileID
,
242 LineStart
, ColumnStart
,
243 LineStart
+ NumLines
, ColumnEnd
, Kind
);
244 if (CMR
.startLoc() > CMR
.endLoc())
245 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
246 MappingRegions
.push_back(CMR
);
248 return Error::success();
251 Error
RawCoverageMappingReader::read() {
252 // Read the virtual file mapping.
253 SmallVector
<unsigned, 8> VirtualFileMapping
;
254 uint64_t NumFileMappings
;
255 if (auto Err
= readSize(NumFileMappings
))
257 for (size_t I
= 0; I
< NumFileMappings
; ++I
) {
258 uint64_t FilenameIndex
;
259 if (auto Err
= readIntMax(FilenameIndex
, TranslationUnitFilenames
.size()))
261 VirtualFileMapping
.push_back(FilenameIndex
);
264 // Construct the files using unique filenames and virtual file mapping.
265 for (auto I
: VirtualFileMapping
) {
266 Filenames
.push_back(TranslationUnitFilenames
[I
]);
269 // Read the expressions.
270 uint64_t NumExpressions
;
271 if (auto Err
= readSize(NumExpressions
))
273 // Create an array of dummy expressions that get the proper counters
274 // when the expressions are read, and the proper kinds when the counters
278 CounterExpression(CounterExpression::Subtract
, Counter(), Counter()));
279 for (size_t I
= 0; I
< NumExpressions
; ++I
) {
280 if (auto Err
= readCounter(Expressions
[I
].LHS
))
282 if (auto Err
= readCounter(Expressions
[I
].RHS
))
286 // Read the mapping regions sub-arrays.
287 for (unsigned InferredFileID
= 0, S
= VirtualFileMapping
.size();
288 InferredFileID
< S
; ++InferredFileID
) {
289 if (auto Err
= readMappingRegionsSubArray(MappingRegions
, InferredFileID
,
290 VirtualFileMapping
.size()))
294 // Set the counters for the expansion regions.
295 // i.e. Counter of expansion region = counter of the first region
296 // from the expanded file.
297 // Perform multiple passes to correctly propagate the counters through
298 // all the nested expansion regions.
299 SmallVector
<CounterMappingRegion
*, 8> FileIDExpansionRegionMapping
;
300 FileIDExpansionRegionMapping
.resize(VirtualFileMapping
.size(), nullptr);
301 for (unsigned Pass
= 1, S
= VirtualFileMapping
.size(); Pass
< S
; ++Pass
) {
302 for (auto &R
: MappingRegions
) {
303 if (R
.Kind
!= CounterMappingRegion::ExpansionRegion
)
305 assert(!FileIDExpansionRegionMapping
[R
.ExpandedFileID
]);
306 FileIDExpansionRegionMapping
[R
.ExpandedFileID
] = &R
;
308 for (auto &R
: MappingRegions
) {
309 if (FileIDExpansionRegionMapping
[R
.FileID
]) {
310 FileIDExpansionRegionMapping
[R
.FileID
]->Count
= R
.Count
;
311 FileIDExpansionRegionMapping
[R
.FileID
] = nullptr;
316 return Error::success();
319 Expected
<bool> RawCoverageMappingDummyChecker::isDummy() {
320 // A dummy coverage mapping data consists of just one region with zero count.
321 uint64_t NumFileMappings
;
322 if (Error Err
= readSize(NumFileMappings
))
323 return std::move(Err
);
324 if (NumFileMappings
!= 1)
326 // We don't expect any specific value for the filename index, just skip it.
327 uint64_t FilenameIndex
;
329 readIntMax(FilenameIndex
, std::numeric_limits
<unsigned>::max()))
330 return std::move(Err
);
331 uint64_t NumExpressions
;
332 if (Error Err
= readSize(NumExpressions
))
333 return std::move(Err
);
334 if (NumExpressions
!= 0)
337 if (Error Err
= readSize(NumRegions
))
338 return std::move(Err
);
341 uint64_t EncodedCounterAndRegion
;
342 if (Error Err
= readIntMax(EncodedCounterAndRegion
,
343 std::numeric_limits
<unsigned>::max()))
344 return std::move(Err
);
345 unsigned Tag
= EncodedCounterAndRegion
& Counter::EncodingTagMask
;
346 return Tag
== Counter::Zero
;
349 Error
InstrProfSymtab::create(SectionRef
&Section
) {
350 if (auto EC
= Section
.getContents(Data
))
351 return errorCodeToError(EC
);
352 Address
= Section
.getAddress();
353 return Error::success();
356 StringRef
InstrProfSymtab::getFuncName(uint64_t Pointer
, size_t Size
) {
357 if (Pointer
< Address
)
359 auto Offset
= Pointer
- Address
;
360 if (Offset
+ Size
> Data
.size())
362 return Data
.substr(Pointer
- Address
, Size
);
365 // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
366 static Expected
<bool> isCoverageMappingDummy(uint64_t Hash
, StringRef Mapping
) {
367 // The hash value of dummy mapping records is always zero.
370 return RawCoverageMappingDummyChecker(Mapping
).isDummy();
375 struct CovMapFuncRecordReader
{
376 virtual ~CovMapFuncRecordReader() = default;
378 // The interface to read coverage mapping function records for a module.
380 // \p Buf points to the buffer containing the \c CovHeader of the coverage
381 // mapping data associated with the module.
383 // Returns a pointer to the next \c CovHeader if it exists, or a pointer
384 // greater than \p End if not.
385 virtual Expected
<const char *> readFunctionRecords(const char *Buf
,
386 const char *End
) = 0;
388 template <class IntPtrT
, support::endianness Endian
>
389 static Expected
<std::unique_ptr
<CovMapFuncRecordReader
>>
390 get(CovMapVersion Version
, InstrProfSymtab
&P
,
391 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &R
,
392 std::vector
<StringRef
> &F
);
395 // A class for reading coverage mapping function records for a module.
396 template <CovMapVersion Version
, class IntPtrT
, support::endianness Endian
>
397 class VersionedCovMapFuncRecordReader
: public CovMapFuncRecordReader
{
398 using FuncRecordType
=
399 typename CovMapTraits
<Version
, IntPtrT
>::CovMapFuncRecordType
;
400 using NameRefType
= typename CovMapTraits
<Version
, IntPtrT
>::NameRefType
;
402 // Maps function's name references to the indexes of their records
404 DenseMap
<NameRefType
, size_t> FunctionRecords
;
405 InstrProfSymtab
&ProfileNames
;
406 std::vector
<StringRef
> &Filenames
;
407 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &Records
;
409 // Add the record to the collection if we don't already have a record that
410 // points to the same function name. This is useful to ignore the redundant
411 // records for the functions with ODR linkage.
412 // In addition, prefer records with real coverage mapping data to dummy
413 // records, which were emitted for inline functions which were seen but
414 // not used in the corresponding translation unit.
415 Error
insertFunctionRecordIfNeeded(const FuncRecordType
*CFR
,
416 StringRef Mapping
, size_t FilenamesBegin
) {
417 uint64_t FuncHash
= CFR
->template getFuncHash
<Endian
>();
418 NameRefType NameRef
= CFR
->template getFuncNameRef
<Endian
>();
420 FunctionRecords
.insert(std::make_pair(NameRef
, Records
.size()));
421 if (InsertResult
.second
) {
423 if (Error Err
= CFR
->template getFuncName
<Endian
>(ProfileNames
, FuncName
))
425 if (FuncName
.empty())
426 return make_error
<InstrProfError
>(instrprof_error::malformed
);
427 Records
.emplace_back(Version
, FuncName
, FuncHash
, Mapping
, FilenamesBegin
,
428 Filenames
.size() - FilenamesBegin
);
429 return Error::success();
431 // Update the existing record if it's a dummy and the new record is real.
432 size_t OldRecordIndex
= InsertResult
.first
->second
;
433 BinaryCoverageReader::ProfileMappingRecord
&OldRecord
=
434 Records
[OldRecordIndex
];
435 Expected
<bool> OldIsDummyExpected
= isCoverageMappingDummy(
436 OldRecord
.FunctionHash
, OldRecord
.CoverageMapping
);
437 if (Error Err
= OldIsDummyExpected
.takeError())
439 if (!*OldIsDummyExpected
)
440 return Error::success();
441 Expected
<bool> NewIsDummyExpected
=
442 isCoverageMappingDummy(FuncHash
, Mapping
);
443 if (Error Err
= NewIsDummyExpected
.takeError())
445 if (*NewIsDummyExpected
)
446 return Error::success();
447 OldRecord
.FunctionHash
= FuncHash
;
448 OldRecord
.CoverageMapping
= Mapping
;
449 OldRecord
.FilenamesBegin
= FilenamesBegin
;
450 OldRecord
.FilenamesSize
= Filenames
.size() - FilenamesBegin
;
451 return Error::success();
455 VersionedCovMapFuncRecordReader(
457 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &R
,
458 std::vector
<StringRef
> &F
)
459 : ProfileNames(P
), Filenames(F
), Records(R
) {}
461 ~VersionedCovMapFuncRecordReader() override
= default;
463 Expected
<const char *> readFunctionRecords(const char *Buf
,
464 const char *End
) override
{
465 using namespace support
;
467 if (Buf
+ sizeof(CovMapHeader
) > End
)
468 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
469 auto CovHeader
= reinterpret_cast<const CovMapHeader
*>(Buf
);
470 uint32_t NRecords
= CovHeader
->getNRecords
<Endian
>();
471 uint32_t FilenamesSize
= CovHeader
->getFilenamesSize
<Endian
>();
472 uint32_t CoverageSize
= CovHeader
->getCoverageSize
<Endian
>();
473 assert((CovMapVersion
)CovHeader
->getVersion
<Endian
>() == Version
);
474 Buf
= reinterpret_cast<const char *>(CovHeader
+ 1);
476 // Skip past the function records, saving the start and end for later.
477 const char *FunBuf
= Buf
;
478 Buf
+= NRecords
* sizeof(FuncRecordType
);
479 const char *FunEnd
= Buf
;
481 // Get the filenames.
482 if (Buf
+ FilenamesSize
> End
)
483 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
484 size_t FilenamesBegin
= Filenames
.size();
485 RawCoverageFilenamesReader
Reader(StringRef(Buf
, FilenamesSize
), Filenames
);
486 if (auto Err
= Reader
.read())
487 return std::move(Err
);
488 Buf
+= FilenamesSize
;
490 // We'll read the coverage mapping records in the loop below.
491 const char *CovBuf
= Buf
;
493 const char *CovEnd
= Buf
;
496 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
497 // Each coverage map has an alignment of 8, so we need to adjust alignment
498 // before reading the next map.
499 Buf
+= alignmentAdjustment(Buf
, 8);
501 auto CFR
= reinterpret_cast<const FuncRecordType
*>(FunBuf
);
502 while ((const char *)CFR
< FunEnd
) {
503 // Read the function information
504 uint32_t DataSize
= CFR
->template getDataSize
<Endian
>();
506 // Now use that to read the coverage data.
507 if (CovBuf
+ DataSize
> CovEnd
)
508 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
509 auto Mapping
= StringRef(CovBuf
, DataSize
);
513 insertFunctionRecordIfNeeded(CFR
, Mapping
, FilenamesBegin
))
514 return std::move(Err
);
521 } // end anonymous namespace
523 template <class IntPtrT
, support::endianness Endian
>
524 Expected
<std::unique_ptr
<CovMapFuncRecordReader
>> CovMapFuncRecordReader::get(
525 CovMapVersion Version
, InstrProfSymtab
&P
,
526 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &R
,
527 std::vector
<StringRef
> &F
) {
528 using namespace coverage
;
531 case CovMapVersion::Version1
:
532 return llvm::make_unique
<VersionedCovMapFuncRecordReader
<
533 CovMapVersion::Version1
, IntPtrT
, Endian
>>(P
, R
, F
);
534 case CovMapVersion::Version2
:
535 case CovMapVersion::Version3
:
536 // Decompress the name data.
537 if (Error E
= P
.create(P
.getNameData()))
539 if (Version
== CovMapVersion::Version2
)
540 return llvm::make_unique
<VersionedCovMapFuncRecordReader
<
541 CovMapVersion::Version2
, IntPtrT
, Endian
>>(P
, R
, F
);
543 return llvm::make_unique
<VersionedCovMapFuncRecordReader
<
544 CovMapVersion::Version3
, IntPtrT
, Endian
>>(P
, R
, F
);
546 llvm_unreachable("Unsupported version");
549 template <typename T
, support::endianness Endian
>
550 static Error
readCoverageMappingData(
551 InstrProfSymtab
&ProfileNames
, StringRef Data
,
552 std::vector
<BinaryCoverageReader::ProfileMappingRecord
> &Records
,
553 std::vector
<StringRef
> &Filenames
) {
554 using namespace coverage
;
556 // Read the records in the coverage data section.
558 reinterpret_cast<const CovMapHeader
*>(Data
.data());
559 CovMapVersion Version
= (CovMapVersion
)CovHeader
->getVersion
<Endian
>();
560 if (Version
> CovMapVersion::CurrentVersion
)
561 return make_error
<CoverageMapError
>(coveragemap_error::unsupported_version
);
562 Expected
<std::unique_ptr
<CovMapFuncRecordReader
>> ReaderExpected
=
563 CovMapFuncRecordReader::get
<T
, Endian
>(Version
, ProfileNames
, Records
,
565 if (Error E
= ReaderExpected
.takeError())
567 auto Reader
= std::move(ReaderExpected
.get());
568 for (const char *Buf
= Data
.data(), *End
= Buf
+ Data
.size(); Buf
< End
;) {
569 auto NextHeaderOrErr
= Reader
->readFunctionRecords(Buf
, End
);
570 if (auto E
= NextHeaderOrErr
.takeError())
572 Buf
= NextHeaderOrErr
.get();
574 return Error::success();
577 static const char *TestingFormatMagic
= "llvmcovmtestdata";
579 static Error
loadTestingFormat(StringRef Data
, InstrProfSymtab
&ProfileNames
,
580 StringRef
&CoverageMapping
,
581 uint8_t &BytesInAddress
,
582 support::endianness
&Endian
) {
584 Endian
= support::endianness::little
;
586 Data
= Data
.substr(StringRef(TestingFormatMagic
).size());
588 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
590 auto ProfileNamesSize
=
591 decodeULEB128(reinterpret_cast<const uint8_t *>(Data
.data()), &N
);
593 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
594 Data
= Data
.substr(N
);
596 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
599 decodeULEB128(reinterpret_cast<const uint8_t *>(Data
.data()), &N
);
601 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
602 Data
= Data
.substr(N
);
603 if (Data
.size() < ProfileNamesSize
)
604 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
605 if (Error E
= ProfileNames
.create(Data
.substr(0, ProfileNamesSize
), Address
))
607 CoverageMapping
= Data
.substr(ProfileNamesSize
);
608 // Skip the padding bytes because coverage map data has an alignment of 8.
609 if (CoverageMapping
.empty())
610 return make_error
<CoverageMapError
>(coveragemap_error::truncated
);
611 size_t Pad
= alignmentAdjustment(CoverageMapping
.data(), 8);
612 if (CoverageMapping
.size() < Pad
)
613 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
614 CoverageMapping
= CoverageMapping
.substr(Pad
);
615 return Error::success();
618 static Expected
<SectionRef
> lookupSection(ObjectFile
&OF
, StringRef Name
) {
620 for (const auto &Section
: OF
.sections()) {
621 if (auto EC
= Section
.getName(FoundName
))
622 return errorCodeToError(EC
);
623 if (FoundName
== Name
)
626 return make_error
<CoverageMapError
>(coveragemap_error::no_data_found
);
629 static Error
loadBinaryFormat(MemoryBufferRef ObjectBuffer
,
630 InstrProfSymtab
&ProfileNames
,
631 StringRef
&CoverageMapping
,
632 uint8_t &BytesInAddress
,
633 support::endianness
&Endian
, StringRef Arch
) {
634 auto BinOrErr
= createBinary(ObjectBuffer
);
636 return BinOrErr
.takeError();
637 auto Bin
= std::move(BinOrErr
.get());
638 std::unique_ptr
<ObjectFile
> OF
;
639 if (auto *Universal
= dyn_cast
<MachOUniversalBinary
>(Bin
.get())) {
640 // If we have a universal binary, try to look up the object for the
641 // appropriate architecture.
642 auto ObjectFileOrErr
= Universal
->getObjectForArch(Arch
);
643 if (!ObjectFileOrErr
)
644 return ObjectFileOrErr
.takeError();
645 OF
= std::move(ObjectFileOrErr
.get());
646 } else if (isa
<ObjectFile
>(Bin
.get())) {
647 // For any other object file, upcast and take ownership.
648 OF
.reset(cast
<ObjectFile
>(Bin
.release()));
649 // If we've asked for a particular arch, make sure they match.
650 if (!Arch
.empty() && OF
->getArch() != Triple(Arch
).getArch())
651 return errorCodeToError(object_error::arch_not_found
);
653 // We can only handle object files.
654 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
656 // The coverage uses native pointer sizes for the object it's written in.
657 BytesInAddress
= OF
->getBytesInAddress();
658 Endian
= OF
->isLittleEndian() ? support::endianness::little
659 : support::endianness::big
;
661 // Look for the sections that we are interested in.
662 auto ObjFormat
= OF
->getTripleObjectFormat();
664 lookupSection(*OF
, getInstrProfSectionName(IPSK_name
, ObjFormat
,
665 /*AddSegmentInfo=*/false));
666 if (auto E
= NamesSection
.takeError())
668 auto CoverageSection
=
669 lookupSection(*OF
, getInstrProfSectionName(IPSK_covmap
, ObjFormat
,
670 /*AddSegmentInfo=*/false));
671 if (auto E
= CoverageSection
.takeError())
674 // Get the contents of the given sections.
675 if (auto EC
= CoverageSection
->getContents(CoverageMapping
))
676 return errorCodeToError(EC
);
677 if (Error E
= ProfileNames
.create(*NamesSection
))
680 return Error::success();
683 Expected
<std::unique_ptr
<BinaryCoverageReader
>>
684 BinaryCoverageReader::create(std::unique_ptr
<MemoryBuffer
> &ObjectBuffer
,
686 std::unique_ptr
<BinaryCoverageReader
> Reader(new BinaryCoverageReader());
689 uint8_t BytesInAddress
;
690 support::endianness Endian
;
691 Error E
= Error::success();
692 consumeError(std::move(E
));
693 if (ObjectBuffer
->getBuffer().startswith(TestingFormatMagic
))
694 // This is a special format used for testing.
695 E
= loadTestingFormat(ObjectBuffer
->getBuffer(), Reader
->ProfileNames
,
696 Coverage
, BytesInAddress
, Endian
);
698 E
= loadBinaryFormat(ObjectBuffer
->getMemBufferRef(), Reader
->ProfileNames
,
699 Coverage
, BytesInAddress
, Endian
, Arch
);
703 if (BytesInAddress
== 4 && Endian
== support::endianness::little
)
704 E
= readCoverageMappingData
<uint32_t, support::endianness::little
>(
705 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
707 else if (BytesInAddress
== 4 && Endian
== support::endianness::big
)
708 E
= readCoverageMappingData
<uint32_t, support::endianness::big
>(
709 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
711 else if (BytesInAddress
== 8 && Endian
== support::endianness::little
)
712 E
= readCoverageMappingData
<uint64_t, support::endianness::little
>(
713 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
715 else if (BytesInAddress
== 8 && Endian
== support::endianness::big
)
716 E
= readCoverageMappingData
<uint64_t, support::endianness::big
>(
717 Reader
->ProfileNames
, Coverage
, Reader
->MappingRecords
,
720 return make_error
<CoverageMapError
>(coveragemap_error::malformed
);
723 return std::move(Reader
);
726 Error
BinaryCoverageReader::readNextRecord(CoverageMappingRecord
&Record
) {
727 if (CurrentRecord
>= MappingRecords
.size())
728 return make_error
<CoverageMapError
>(coveragemap_error::eof
);
730 FunctionsFilenames
.clear();
732 MappingRegions
.clear();
733 auto &R
= MappingRecords
[CurrentRecord
];
734 RawCoverageMappingReader
Reader(
736 makeArrayRef(Filenames
).slice(R
.FilenamesBegin
, R
.FilenamesSize
),
737 FunctionsFilenames
, Expressions
, MappingRegions
);
738 if (auto Err
= Reader
.read())
741 Record
.FunctionName
= R
.FunctionName
;
742 Record
.FunctionHash
= R
.FunctionHash
;
743 Record
.Filenames
= FunctionsFilenames
;
744 Record
.Expressions
= Expressions
;
745 Record
.MappingRegions
= MappingRegions
;
748 return Error::success();