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//===----------------------------------------------------------------------===// 42using namespacecoverage;
45#define DEBUG_TYPE "coverage-mapping" 47STATISTIC(CovMapNumRecords,
"The # of coverage function records");
48STATISTIC(CovMapNumUsedRecords,
"The # of used coverage function records");
50void CoverageMappingIterator::increment() {
54// Check if all the records were read or if an error occurred while reading 72"the size of ULEB128 is too big");
80if (Result >= MaxPlus1)
81return make_error<CoverageMapError>(
83"the value of ULEB128 is greater than or equal to MaxPlus1");
92"the value of ULEB128 is too big");
107if (
auto Err =
readSize(NumFilenames))
111"number of filenames is zero");
114return readUncompressed(
Version, NumFilenames);
116// The uncompressed length may exceed the size of the encoded filenames. 117// Skip size validation. 123if (
auto Err =
readSize(CompressedLen))
126if (CompressedLen > 0) {
128return make_error<CoverageMapError>(
131// Allocate memory for the decompressed filenames. 134// Read compressed filenames. 138 arrayRefFromStringRef(CompressedFilenames), StorageBuf,
142return make_error<CoverageMapError>(
148return Delegate.readUncompressed(
Version, NumFilenames);
151return readUncompressed(
Version, NumFilenames);
156// Read uncompressed filenames. 158for (
size_tI = 0;
I < NumFilenames; ++
I) {
162 Filenames.push_back(Filename.str());
168 Filenames.push_back(CWD.
str());
170for (
size_tI = 1;
I < NumFilenames; ++
I) {
175 Filenames.push_back(Filename.str());
178if (!CompilationDir.
empty())
179P.assign(CompilationDir);
184 Filenames.push_back(
static_cast<std::string
>(
P.str()));
208if (
ID >= Expressions.size())
210"counter expression is invalid");
217"counter expression kind is invalid");
225readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
227if (
auto Err = decodeCounter(EncodedCounter,
C))
235/// Read the sub-array of regions for the given inferred file id. 236/// \param NumFileIDs the number of file ids that are defined for this 238Error RawCoverageMappingReader::readMappingRegionsSubArray(
239 std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID,
244unsigned LineStart = 0;
245for (
size_tI = 0;
I < NumRegions; ++
I) {
248// They are stored as internal values plus 1 (min is -1) 253// Read the combined counter + region kind. 255if (
auto Err =
readIntMax(EncodedCounterAndRegion,
256 std::numeric_limits<unsigned>::max()))
261// If Tag does not represent a ZeroCounter, then it is understood to refer 262// to a counter or counter expression with region kind assumed to be 263// "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the 264// referenced counter or counter expression (and nothing else). 266// If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set, 267// then EncodedCounterAndRegion is interpreted to represent an 268// ExpansionRegion. In all other cases, EncodedCounterAndRegion is 269// interpreted to refer to a specific region kind, after which additional 270// fields may be read (e.g. BranchRegions have two encoded counters that 271// follow an encoded region kind value). 273if (
auto Err = decodeCounter(EncodedCounterAndRegion,
C))
276// Is it an expansion region? 279 ExpandedFileID = EncodedCounterAndRegion >>
281if (ExpandedFileID >= NumFileIDs)
283"ExpandedFileID is invalid");
285switch (EncodedCounterAndRegion >>
288// Don't do anything when we have a code region with a zero counter. 294// For a Branch Region, read two successive counters. 296if (
auto Err = readCounter(
C))
298if (
auto Err = readCounter(C2))
302// For a MCDC Branch Region, read two successive counters and 3 IDs. 304if (
auto Err = readCounter(
C))
306if (
auto Err = readCounter(C2))
308if (
auto Err =
readIntMax(ID1, std::numeric_limits<int16_t>::max()))
310if (
auto Err =
readIntMax(TID1, std::numeric_limits<int16_t>::max()))
312if (
auto Err =
readIntMax(FID1, std::numeric_limits<int16_t>::max()))
315return make_error<CoverageMapError>(
317"MCDCConditionID shouldn't be zero");
319static_cast<int16_t
>(
static_cast<int16_t
>(ID1) - 1),
320 {
static_cast<int16_t
>(
static_cast<int16_t
>(FID1) - 1),
321static_cast<int16_t
>(
static_cast<int16_t
>(TID1) - 1)}};
325if (
auto Err =
readIntMax(BIDX, std::numeric_limits<unsigned>::max()))
327if (
auto Err =
readIntMax(
NC, std::numeric_limits<int16_t>::max()))
334"region kind is incorrect");
339// Read the source range. 340uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
342readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
346if (ColumnStart > std::numeric_limits<unsigned>::max())
348"start column is too big");
349if (
auto Err =
readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
351if (
auto Err =
readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
353 LineStart += LineStartDelta;
355// If the high bit of ColumnEnd is set, this is a gap region. 356if (ColumnEnd & (1U << 31)) {
358 ColumnEnd &= ~(1U << 31);
361// Adjust the column locations for the empty regions that are supposed to 362// cover whole lines. Those regions should be encoded with the 363// column range (1 -> std::numeric_limits<unsigned>::max()), but because 364// the encoded std::numeric_limits<unsigned>::max() is several bytes long, 365// we set the column range to (0 -> 0) to ensure that the column start and 366// column end take up one byte each. 367// The std::numeric_limits<unsigned>::max() is used to represent a column 368// position at the end of the line without knowing the length of that line. 369if (ColumnStart == 0 && ColumnEnd == 0) {
371 ColumnEnd = std::numeric_limits<unsigned>::max();
375dbgs() <<
"Counter in file " << InferredFileID <<
" " << LineStart <<
":" 376 << ColumnStart <<
" -> " << (LineStart + NumLines) <<
":" 379dbgs() <<
"Expands to file " << ExpandedFileID;
386C, C2, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
387 LineStart + NumLines, ColumnEnd,
Kind, Params);
388if (CMR.startLoc() > CMR.endLoc())
389return make_error<CoverageMapError>(
391"counter mapping region locations are incorrect");
392 MappingRegions.push_back(CMR);
398// Read the virtual file mapping. 401if (
auto Err =
readSize(NumFileMappings))
403for (
size_tI = 0;
I < NumFileMappings; ++
I) {
405if (
auto Err =
readIntMax(FilenameIndex, TranslationUnitFilenames.
size()))
407 VirtualFileMapping.
push_back(FilenameIndex);
410// Construct the files using unique filenames and virtual file mapping. 411for (
autoI : VirtualFileMapping) {
412 Filenames.push_back(TranslationUnitFilenames[
I]);
415// Read the expressions. 417if (
auto Err =
readSize(NumExpressions))
419// Create an array of dummy expressions that get the proper counters 420// when the expressions are read, and the proper kinds when the counters 425for (
size_tI = 0;
I < NumExpressions; ++
I) {
426if (
auto Err = readCounter(Expressions[
I].
LHS))
428if (
auto Err = readCounter(Expressions[
I].
RHS))
432// Read the mapping regions sub-arrays. 433for (
unsigned InferredFileID = 0, S = VirtualFileMapping.
size();
434 InferredFileID < S; ++InferredFileID) {
435if (
auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
436 VirtualFileMapping.
size()))
440// Set the counters for the expansion regions. 441// i.e. Counter of expansion region = counter of the first region 442// from the expanded file. 443// Perform multiple passes to correctly propagate the counters through 444// all the nested expansion regions. 446 FileIDExpansionRegionMapping.
resize(VirtualFileMapping.
size(),
nullptr);
448for (
auto &R : MappingRegions) {
451assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
452 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
454for (
auto &R : MappingRegions) {
455if (FileIDExpansionRegionMapping[R.FileID]) {
456 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
457 FileIDExpansionRegionMapping[R.FileID] =
nullptr;
466// A dummy coverage mapping data consists of just one region with zero count. 469return std::move(Err);
470if (NumFileMappings != 1)
472// We don't expect any specific value for the filename index, just skip it. 475readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
476return std::move(Err);
479return std::move(Err);
480if (NumExpressions != 0)
484return std::move(Err);
489 std::numeric_limits<unsigned>::max()))
490return std::move(Err);
495/// Determine if we should skip the first byte of the section content 498// If this is a linked PE/COFF file, then we have to skip over the null byte 499// that is allocated in the .lprfn$A section in the LLVM profiling runtime. 500// If the name section is .lprfcovnames, it doesn't have the null byte at the 531// Check if the mapping data is a dummy, i.e. is emitted for an unused function. 533// The hash value of dummy mapping records is always zero. 539/// A range of filename indices. Used to specify the location of a batch of 540/// filenames in a vector-like container. 554/// The interface to read coverage mapping function records for a module. 555structCovMapFuncRecordReader {
556virtual ~CovMapFuncRecordReader() =
default;
558// Read a coverage header. 560// \p CovBuf points to the buffer containing the \c CovHeader of the coverage 561// mapping data associated with the module. 563// Returns a pointer to the next \c CovHeader if it exists, or to an address 564// greater than \p CovEnd if not. 566constchar *CovBufEnd) = 0;
568// Read function records. 570// \p FuncRecBuf points to the buffer containing a batch of function records. 571// \p FuncRecBufEnd points past the end of the batch of records. 573// Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames 574// associated with the function records. It is unused in Version4. 576// Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage 577// mappings associated with the function records. It is unused in Version4. 579 readFunctionRecords(
constchar *FuncRecBuf,
constchar *FuncRecBufEnd,
580 std::optional<FilenameRange> OutOfLineFileRange,
581constchar *OutOfLineMappingBuf,
582constchar *OutOfLineMappingBufEnd) = 0;
584template <
class IntPtrT, llvm::endianness Endian>
587 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
StringRefD,
588 std::vector<std::string> &
F);
591// A class for reading coverage mapping function records for a module. 592template <CovMapVersion Version,
class IntPtrT, llvm::endianness Endian>
593classVersionedCovMapFuncRecordReader :
public CovMapFuncRecordReader {
598// Maps function's name references to the indexes of their records 603 std::vector<std::string> &Filenames;
604 std::vector<BinaryCoverageReader::ProfileMappingRecord> &
Records;
606// Maps a hash of the filenames in a TU to a \c FileRange. The range 607// specifies the location of the hashed filenames in \c Filenames. 610// Add the record to the collection if we don't already have a record that 611// points to the same function name. This is useful to ignore the redundant 612// records for the functions with ODR linkage. 613// In addition, prefer records with real coverage mapping data to dummy 614// records, which were emitted for inline functions which were seen but 615// not used in the corresponding translation unit. 616Error insertFunctionRecordIfNeeded(
const FuncRecordType *CFR,
620uint64_t FuncHash = CFR->template getFuncHash<Endian>();
621 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
623 FunctionRecords.
insert(std::make_pair(NameRef,
Records.size()));
624if (InsertResult.second) {
626if (
Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
629return make_error<InstrProfError>(instrprof_error::malformed,
630"function name is empty");
631 ++CovMapNumUsedRecords;
632Records.emplace_back(Version, FuncName, FuncHash, Mapping,
636// Update the existing record if it's a dummy and the new record is real. 637size_t OldRecordIndex = InsertResult.first->second;
644if (!*OldIsDummyExpected)
650if (*NewIsDummyExpected)
652 ++CovMapNumUsedRecords;
661 VersionedCovMapFuncRecordReader(
663 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
StringRefD,
664 std::vector<std::string> &
F)
665 : ProfileNames(
P), CompilationDir(
D), Filenames(
F),
Records(
R) {}
667 ~VersionedCovMapFuncRecordReader()
override =
default;
670constchar *CovBufEnd)
override{
671using namespacesupport;
674return make_error<CoverageMapError>(
675 coveragemap_error::malformed,
676"coverage mapping header section is larger than buffer size");
677auto CovHeader =
reinterpret_cast<constCovMapHeader *
>(CovBuf);
682 CovBuf =
reinterpret_cast<constchar *
>(CovHeader + 1);
684// Skip past the function records, saving the start and end for later. 685// This is a no-op in Version4 (function records are read after all headers 687constchar *FuncRecBuf =
nullptr;
688constchar *FuncRecBufEnd =
nullptr;
689if (Version < CovMapVersion::Version4)
691 CovBuf += NRecords *
sizeof(FuncRecordType);
692if (Version < CovMapVersion::Version4)
693 FuncRecBufEnd = CovBuf;
696if (CovBuf + FilenamesSize > CovBufEnd)
697return make_error<CoverageMapError>(
698 coveragemap_error::malformed,
699"filenames section is larger than buffer size");
700size_t FilenamesBegin = Filenames.size();
701StringRef FilenameRegion(CovBuf, FilenamesSize);
704if (
auto Err = Reader.read(Version))
705return std::move(Err);
706 CovBuf += FilenamesSize;
707FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
709if (Version >= CovMapVersion::Version4) {
710// Map a hash of the filenames region to the filename range associated 711// with this coverage header. 712 int64_t FilenamesRef =
715 FileRangeMap.
insert(std::make_pair(FilenamesRef, FileRange));
717// The same filenames ref was encountered twice. It's possible that 718// the associated filenames are the same. 719auto It = Filenames.begin();
725// Map the new range to the original one. 726 FileRange = OrigRange;
728// This is a hash collision. Mark the filenames ref invalid. 733// We'll read the coverage mapping records in the loop below. 734// This is a no-op in Version4 (coverage mappings are not affixed to the 736constchar *MappingBuf = CovBuf;
737if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
738return make_error<CoverageMapError>(coveragemap_error::malformed,
739"coverage mapping size is not zero");
740 CovBuf += CoverageSize;
741constchar *MappingEnd = CovBuf;
743if (CovBuf > CovBufEnd)
744return make_error<CoverageMapError>(
745 coveragemap_error::malformed,
746"function records section is larger than buffer size");
748if (Version < CovMapVersion::Version4) {
749// Read each function record. 750if (
ErrorE = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
751 MappingBuf, MappingEnd))
755// Each coverage map has an alignment of 8, so we need to adjust alignment 756// before reading the next map. 762Error readFunctionRecords(
constchar *FuncRecBuf,
constchar *FuncRecBufEnd,
763 std::optional<FilenameRange> OutOfLineFileRange,
764constchar *OutOfLineMappingBuf,
765constchar *OutOfLineMappingBufEnd)
override{
766auto CFR =
reinterpret_cast<constFuncRecordType *
>(FuncRecBuf);
767while ((
constchar *)CFR < FuncRecBufEnd) {
768// Validate the length of the coverage mapping for this function. 769constchar *NextMappingBuf;
770const FuncRecordType *NextCFR;
771 std::tie(NextMappingBuf, NextCFR) =
772 CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
773if (Version < CovMapVersion::Version4)
774if (NextMappingBuf > OutOfLineMappingBufEnd)
775return make_error<CoverageMapError>(
776 coveragemap_error::malformed,
777"next mapping buffer is larger than buffer size");
779// Look up the set of filenames associated with this function record. 780 std::optional<FilenameRange> FileRange;
781if (Version < CovMapVersion::Version4) {
782 FileRange = OutOfLineFileRange;
784uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
785auto It = FileRangeMap.
find(FilenamesRef);
786if (It == FileRangeMap.
end())
787return make_error<CoverageMapError>(
788 coveragemap_error::malformed,
789"no filename found for function with hash=0x" +
792 FileRange = It->getSecond();
795// Now, read the coverage data. 796if (FileRange && !FileRange->isInvalid()) {
798 CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
799if (Version >= CovMapVersion::Version4 &&
800 Mapping.
data() + Mapping.
size() > FuncRecBufEnd)
801return make_error<CoverageMapError>(
802 coveragemap_error::malformed,
803"coverage mapping data is larger than buffer size");
804if (
Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
808 std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
814}
// end anonymous namespace 816template <
class IntPtrT, llvm::endianness Endian>
819 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
StringRefD,
820 std::vector<std::string> &
F) {
821using namespacecoverage;
825return std::make_unique<VersionedCovMapFuncRecordReader<
833// Decompress the name data. 834if (
Error E =
P.create(
P.getNameData()))
837return std::make_unique<VersionedCovMapFuncRecordReader<
840return std::make_unique<VersionedCovMapFuncRecordReader<
843return std::make_unique<VersionedCovMapFuncRecordReader<
846return std::make_unique<VersionedCovMapFuncRecordReader<
849return std::make_unique<VersionedCovMapFuncRecordReader<
852return std::make_unique<VersionedCovMapFuncRecordReader<
858template <
typename T, llvm::endianness Endian>
861 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
862StringRef CompilationDir, std::vector<std::string> &Filenames) {
863using namespacecoverage;
865// Read the records in the coverage data section. 872 CovMapFuncRecordReader::get<T, Endian>(
Version, ProfileNames, Records,
873 CompilationDir, Filenames);
876auto Reader = std::move(ReaderExpected.
get());
877constchar *CovBuf = CovMap.
data();
878constchar *CovBufEnd = CovBuf + CovMap.
size();
879constchar *FuncRecBuf = FuncRecords.
data();
880constchar *FuncRecBufEnd = FuncRecords.
data() + FuncRecords.
size();
881while (CovBuf < CovBufEnd) {
882// Read the current coverage header & filename data. 884// Prior to Version4, this also reads all function records affixed to the 887// Return a pointer to the next coverage header. 888auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
889if (
auto E = NextOrErr.takeError())
891 CovBuf = NextOrErr.get();
893// In Version4, function records are not affixed to coverage headers. Read 894// the records from their dedicated section. 896return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
905 std::unique_ptr<InstrProfSymtab> ProfileNamesPtr,
uint8_t BytesInAddress,
907if (ProfileNamesPtr ==
nullptr)
909"Caller must provide ProfileNames");
910 std::unique_ptr<BinaryCoverageReader> Reader(
912 std::move(FuncRecords), std::move(CoverageMap)));
914StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
916if (
Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>(
917 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
918 CompilationDir, Reader->Filenames))
921if (
Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>(
922 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
923 CompilationDir, Reader->Filenames))
926if (
Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>(
927 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
928 CompilationDir, Reader->Filenames))
931if (
Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>(
932 ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
933 CompilationDir, Reader->Filenames))
936return make_error<CoverageMapError>(
938"not supported endianness or bytes in address");
939return std::move(Reader);
947// Read the magic and version. 951"the size of data is too small");
953 support::endian::byte_swap<uint64_t, llvm::endianness::little>(
957// Read the ProfileNames data. 963return make_error<CoverageMapError>(
965"the size of TestingFormatMagic is too big");
973"the size of ULEB128 is too big");
975if (
Data.size() < ProfileNamesSize)
977"the size of ProfileNames is too big");
978auto ProfileNames = std::make_unique<InstrProfSymtab>();
983// In Version2, the size of CoverageMapping is stored directly. 990"the size of ULEB128 is too big");
993return make_error<CoverageMapError>(
995"the size of CoverageMapping is teoo small");
1000// Skip the padding bytes because coverage map data has an alignment of 8. 1002if (
Data.size() < Pad)
1004"insufficient padding");
1007return make_error<CoverageMapError>(
1009"coverage mapping header section is larger than data size");
1010autoconst *CovHeader =
reinterpret_cast<constCovMapHeader *
>(
1015// In Version1, the size of CoverageMapping is calculated. 1018 CoverageMappingSize =
Data.size();
1022 CoverageMappingSize =
sizeof(
CovMapHeader) + FilenamesSize;
1027Data =
Data.substr(CoverageMappingSize);
1029// Read the CoverageRecords data. 1033"data is not empty");
1035// Skip the padding bytes because coverage records data has an alignment 1038if (
Data.size() < Pad)
1040"insufficient padding");
1048 std::move(ProfileNames), BytesInAddress,
Endian, CompilationDir);
1051/// Find all sections that match \p IPSK name. There may be more than one if 1052/// comdats are in use, e.g. for the __llvm_covfun section on ELF. 1058// On COFF, the object file section name may end in "$M". This tells the 1059// linker to sort these sections between "$A" and "$Z". The linker removes the 1060// dollar and everything after it in the final binary. Do the same to match. 1061bool IsCOFF = isa<COFFObjectFile>(OF);
1063return IsCOFF ?
N.split(
'$').first :
N;
1067 std::vector<SectionRef> Sections;
1068for (
constauto &Section : OF.
sections()) {
1072if (stripSuffix(*NameOrErr) ==
Name) {
1073// Skip empty profile name section. 1074// COFF profile name section contains two null bytes indicating the 1075// start/end of the section. If its size is 2 bytes, it's empty. 1076if (IPSK == IPSK_name &&
1077 (Section.getSize() == 0 || (IsCOFF && Section.getSize() == 2)))
1079 Sections.push_back(Section);
1082if (Sections.empty())
1087/// Find a section that matches \p Name and is allocatable at runtime. 1089/// Returns the contents of the section and its start offset in the object file. 1092// On Wasm, allocatable sections can live only in data segments. 1093if (
auto *WOF = dyn_cast<WasmObjectFile>(&OF)) {
1094 std::vector<const WasmSegment *> Segments;
1098for (
constauto &DebugName : WOF->debugNames()) {
1100 DebugName.Name !=
Name)
1102if (DebugName.Index >= WOF->dataSegments().size())
1104auto &Segment = WOF->dataSegments()[DebugName.Index];
1105 Segments.push_back(&Segment);
1107if (Segments.empty())
1109if (Segments.size() != 1)
1112constauto &Segment = *Segments.front();
1113auto &
Data = Segment.Data;
1115Data.Content.size());
1116return std::make_pair(
Content, Segment.SectionOffset);
1119// On other object file types, delegate to lookupSections to find the section. 1122return Sections.takeError();
1123if (Sections->size() != 1)
1124return make_error<CoverageMapError>(
1126"the size of coverage mapping section is not one");
1127auto &Section = Sections->front();
1128auto ContentsOrErr = Section.getContents();
1130return ContentsOrErr.takeError();
1134return std::make_pair(
Content, Section.getAddress());
1141 std::unique_ptr<ObjectFile> OF;
1142if (
auto *Universal = dyn_cast<MachOUniversalBinary>(
Bin.get())) {
1143// If we have a universal binary, try to look up the object for the 1144// appropriate architecture. 1145auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
1146if (!ObjectFileOrErr)
1147return ObjectFileOrErr.takeError();
1148 OF = std::move(ObjectFileOrErr.get());
1149 }
elseif (isa<ObjectFile>(
Bin.get())) {
1150// For any other object file, upcast and take ownership. 1151 OF.reset(cast<ObjectFile>(
Bin.release()));
1152// If we've asked for a particular arch, make sure they match. 1153if (!Arch.
empty() && OF->getArch() !=
Triple(Arch).getArch())
1156// We can only handle object files. 1158"binary is not an object file");
1160// The coverage uses native pointer sizes for the object it's written in. 1161uint8_t BytesInAddress = OF->getBytesInAddress();
1165// Look for the sections that we are interested in. 1166auto ProfileNames = std::make_unique<InstrProfSymtab>();
1167// If IPSK_name is not found, fallback to search for IPK_covname, which is 1168// used when binary correlation is enabled. 1170if (
auto E = NamesSection.takeError()) {
1173if (
auto E = NamesSection.takeError())
1179 std::tie(NamesContent, NamesAddress) = *NamesSection;
1180if (
Error E = ProfileNames->
create(NamesContent, NamesAddress))
1184if (
auto E = CoverageSection.takeError())
1186 std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
1187if (CoverageSectionRefs.size() != 1)
1189"the size of name section is not one");
1190auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
1191if (!CoverageMappingOrErr)
1192return CoverageMappingOrErr.takeError();
1195// If the coverage mapping section is not aligned to 8 bytes, copy it to a 1196// new buffer that is. Wasm format typically has unaligned section contents 1197// because it doesn't have a good way to insert padding bytes. 1198 std::unique_ptr<MemoryBuffer> CoverageMapCopy;
1204// Look for the coverage records section (Version4 only). 1208if (
auto E = CoverageRecordsSections.takeError()) {
1212// Compute the FuncRecordsBuffer of the buffer, taking into account the 1213// padding between each record, and making sure the first block is aligned 1214// in memory to maintain consistency between buffer address and size 1216constAlign RecordAlignment(8);
1218for (
SectionRef Section : *CoverageRecordsSections) {
1219auto CoverageRecordsOrErr = Section.getContents();
1220if (!CoverageRecordsOrErr)
1221return CoverageRecordsOrErr.takeError();
1222 FuncRecordsSize +=
alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
1224auto WritableBuffer =
1226char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
1228"Allocated memory is correctly aligned");
1230for (
SectionRef Section : *CoverageRecordsSections) {
1231auto CoverageRecordsOrErr = Section.getContents();
1232if (!CoverageRecordsOrErr)
1233return CoverageRecordsOrErr.takeError();
1234constauto &CoverageRecords = CoverageRecordsOrErr.get();
1235 FuncRecordsBuffer = std::copy(CoverageRecords.begin(),
1236 CoverageRecords.end(), FuncRecordsBuffer);
1238 std::fill_n(FuncRecordsBuffer,
1239alignAddr(FuncRecordsBuffer, RecordAlignment) -
1240 (uintptr_t)FuncRecordsBuffer,
1243assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
1245 FuncRecords = std::move(WritableBuffer);
1253 std::move(ProfileNames), BytesInAddress,
Endian, CompilationDir);
1256/// Determine whether \p Arch is invalid or empty, given \p Bin. 1258// If we have a universal binary and Arch doesn't identify any of its slices, 1260if (
auto *Universal = dyn_cast<MachOUniversalBinary>(
Bin)) {
1261for (
auto &ObjForArch : Universal->objects())
1262if (Arch == ObjForArch.getArchFlagName())
1274 std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
1278 support::endian::byte_swap<uint64_t, llvm::endianness::little>(
1281// This is a special format used for testing. 1285return ReaderOrErr.takeError();
1286 Readers.push_back(std::move(ReaderOrErr.get()));
1287return std::move(Readers);
1293return BinOrErr.takeError();
1294 std::unique_ptr<Binary>
Bin = std::move(BinOrErr.get());
1297return make_error<CoverageMapError>(
1300// MachO universal binaries which contain archives need to be treated as 1301// archives, not as regular binaries. 1302if (
auto *Universal = dyn_cast<MachOUniversalBinary>(
Bin.get())) {
1303for (
auto &ObjForArch : Universal->objects()) {
1304// Skip slices within the universal binary which target the wrong arch. 1305 std::string ObjArch = ObjForArch.getArchFlagName();
1309auto ArchiveOrErr = ObjForArch.getAsArchive();
1311// If this is not an archive, try treating it as a regular object. 1317 ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
1318 CompilationDir, BinaryIDs);
1322// Load coverage out of archive members. 1323if (
auto *Ar = dyn_cast<Archive>(
Bin.get())) {
1325for (
auto &Child : Ar->children(Err)) {
1331 ChildBufOrErr.
get(), Arch, ObjectFileBuffers, CompilationDir,
1333if (!ChildReadersOrErr)
1334return ChildReadersOrErr.takeError();
1335for (
auto &Reader : ChildReadersOrErr.get())
1336 Readers.push_back(std::move(Reader));
1339return std::move(Err);
1341// Thin archives reference object files outside of the archive file, i.e. 1342// files which reside in memory not owned by the caller. Transfer ownership 1345for (
auto &Buffer : Ar->takeThinBuffers())
1346 ObjectFileBuffers.push_back(std::move(Buffer));
1348return std::move(Readers);
1353 BinaryIDs ? &BinaryID :
nullptr);
1355return ReaderOrErr.takeError();
1356 Readers.push_back(std::move(ReaderOrErr.get()));
1357if (!BinaryID.
empty())
1359return std::move(Readers);
1363if (CurrentRecord >= MappingRecords.size())
1366 FunctionsFilenames.clear();
1367 Expressions.clear();
1368 MappingRegions.clear();
1369auto &R = MappingRecords[CurrentRecord];
1370autoF =
ArrayRef(Filenames).
slice(R.FilenamesBegin, R.FilenamesSize);
1372 Expressions, MappingRegions);
1373if (
auto Err = Reader.
read())
1376Record.FunctionName = R.FunctionName;
1377Record.FunctionHash = R.FunctionHash;
1378Record.Filenames = FunctionsFilenames;
1379Record.Expressions = Expressions;
1380Record.MappingRegions = MappingRegions;
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static Error readCoverageMappingData(InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, std::vector< BinaryCoverageReader::ProfileMappingRecord > &Records, StringRef CompilationDir, std::vector< std::string > &Filenames)
static Expected< std::pair< StringRef, uint64_t > > lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK)
Find a section that matches Name and is allocatable at runtime.
static Expected< std::unique_ptr< BinaryCoverageReader > > loadBinaryFormat(std::unique_ptr< Binary > Bin, StringRef Arch, StringRef CompilationDir="", object::BuildIDRef *BinaryID=nullptr)
static Expected< std::unique_ptr< BinaryCoverageReader > > loadTestingFormat(StringRef Data, StringRef CompilationDir)
static Expected< std::vector< SectionRef > > lookupSections(ObjectFile &OF, InstrProfSectKind IPSK)
Find all sections that match IPSK name.
static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch)
Determine whether Arch is invalid or empty, given Bin.
static bool shouldSkipSectionFirstByte(SectionRef &Section)
Determine if we should skip the first byte of the section content.
static Expected< bool > isCoverageMappingDummy(uint64_t Hash, StringRef Mapping)
static const unsigned EncodingExpansionRegionBit
This file defines the DenseMap class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function's PGO name from the function name's symbol address in the object file.
const char * getBufferStart() const
StringRef getBuffer() const
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Pass interface - Implemented by all 'passes'.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
empty - Check if the string is empty.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
const unsigned char * bytes_begin() const
Triple - Helper class for working with autoconf configuration names.
static Twine utohexstr(const uint64_t &Val)
LLVM Value Representation.
static std::unique_ptr< WritableMemoryBuffer > getNewUninitMemBuffer(size_t Size, const Twine &BufferName="", std::optional< Align > Alignment=std::nullopt)
Allocate a new MemoryBuffer of the specified size that is not initialized.
Reader for the coverage mapping data that is emitted by the frontend and stored in an object file.
static Expected< std::unique_ptr< BinaryCoverageReader > > createCoverageReaderFromBuffer(StringRef Coverage, FuncRecordsStorage &&FuncRecords, CoverageMapCopyStorage &&CoverageMap, std::unique_ptr< InstrProfSymtab > ProfileNamesPtr, uint8_t BytesInAddress, llvm::endianness Endian, StringRef CompilationDir="")
std::unique_ptr< MemoryBuffer > CoverageMapCopyStorage
static Expected< std::vector< std::unique_ptr< BinaryCoverageReader > > > create(MemoryBufferRef ObjectBuffer, StringRef Arch, SmallVectorImpl< std::unique_ptr< MemoryBuffer > > &ObjectFileBuffers, StringRef CompilationDir="", SmallVectorImpl< object::BuildIDRef > *BinaryIDs=nullptr)
std::unique_ptr< MemoryBuffer > FuncRecordsStorage
Error readNextRecord(CoverageMappingRecord &Record) override
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
void dump(const Counter &C, raw_ostream &OS) const
coveragemap_error get() const
A file format agnostic iterator over coverage mapping data.
virtual Error readNextRecord(CoverageMappingRecord &Record)=0
The mapping of profile information to coverage data.
Reader for the raw coverage filenames.
Error read(CovMapVersion Version)
Checks if the given coverage mapping data is exported for an unused function.
Expected< bool > isDummy()
Reader for the raw coverage mapping data.
Error readSize(uint64_t &Result)
Error readIntMax(uint64_t &Result, uint64_t MaxPlus1)
Error readULEB128(uint64_t &Result)
Error readString(StringRef &Result)
Triple::ObjectFormatType getTripleObjectFormat() const
This class is the base class for all object file types.
section_iterator_range sections() const
virtual bool isRelocatableObject() const =0
True if this is a relocatable object (.o/.obj).
Represents a GOFF physical record.
This is a value type class that represents a single section in the list of sections in the object fil...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
uint64_t ComputeHash(StringRef K)
llvm::SmallVector< std::shared_ptr< RecordsSlice >, 4 > Records
Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)
std::variant< std::monostate, DecisionParameters, BranchParameters > Parameters
The type of MC/DC-specific parameters.
@ invalid_or_missing_arch_specifier
constexpr uint64_t TestingFormatMagic
BuildIDRef getBuildID(const ObjectFile *Obj)
Returns the build ID, if any, contained in the given object file.
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
This is an optimization pass for GlobalISel generic memory operations.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
uint64_t offsetToAlignedAddr(const void *Addr, Align Alignment)
Returns the necessary adjustment for aligning Addr to Alignment bytes, rounding up.
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
void consumeError(Error Err)
Consume a Error without doing anything.
bool isAddrAligned(Align Lhs, const void *Addr)
Checks that Addr is a multiple of the alignment.
uintptr_t alignAddr(const void *Addr, Align Alignment)
Aligns Addr to Alignment bytes, rounding up.
A range of filename indices.
FilenameRange(unsigned StartingIndex, unsigned Length)
This struct is a compact representation of a valid (non-zero power of two) alignment.
StringRef CoverageMapping
A Counter expression is a value that represents an arithmetic operation with two counters.
A Counter mapping region associates a source range with a specific counter.
@ ExpansionRegion
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
@ MCDCDecisionRegion
A DecisionRegion represents a top-level boolean expression and is associated with a variable length b...
@ MCDCBranchRegion
A Branch Region can be extended to include IDs to facilitate MC/DC.
@ SkippedRegion
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
@ GapRegion
A GapRegion is like a CodeRegion, but its count is only set as the line execution count when its the ...
@ BranchRegion
A BranchRegion represents leaf-level boolean expressions and is associated with two counters,...
@ CodeRegion
A CodeRegion associates some code with a counter.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static const unsigned EncodingTagBits
static Counter getZero()
Return the counter that represents the number zero.
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.
static const unsigned EncodingCounterTagAndExpansionRegionTagBits
static const unsigned EncodingTagMask
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
Coverage mapping information for a single function.