42 using namespace coverage;
45 #define DEBUG_TYPE "coverage-mapping"
47 STATISTIC(CovMapNumRecords,
"The # of coverage function records");
48 STATISTIC(CovMapNumUsedRecords,
"The # of used coverage function records");
50 void CoverageMappingIterator::increment() {
56 if (
auto E = Reader->readNextRecord(
Record))
79 if (Result >= MaxPlus1)
87 if (Result >
Data.size())
94 if (
auto Err = readSize(Length))
96 Result =
Data.substr(0, Length);
103 if (
auto Err = readSize(NumFilenames))
109 return readUncompressed(
Version, NumFilenames);
118 if (
auto Err = readSize(CompressedLen))
121 if (CompressedLen > 0) {
123 return make_error<CoverageMapError>(
130 StringRef CompressedFilenames =
Data.substr(0, CompressedLen);
136 return make_error<CoverageMapError>(
140 StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size());
143 return Delegate.readUncompressed(
Version, NumFilenames);
146 return readUncompressed(
Version, NumFilenames);
153 for (
size_t I = 0;
I < NumFilenames; ++
I) {
157 Filenames.push_back(Filename.
str());
163 Filenames.push_back(CWD.
str());
165 for (
size_t I = 1;
I < NumFilenames; ++
I) {
170 Filenames.push_back(Filename.
str());
173 if (!CompilationDir.empty())
174 P.assign(CompilationDir);
179 Filenames.push_back(
static_cast<std::string
>(
P.str()));
220 if (
auto Err = decodeCounter(EncodedCounter,
C))
231 Error RawCoverageMappingReader::readMappingRegionsSubArray(
232 std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID,
235 if (
auto Err = readSize(NumRegions))
237 unsigned LineStart = 0;
238 for (
size_t I = 0;
I < NumRegions; ++
I) {
244 if (
auto Err = readIntMax(EncodedCounterAndRegion,
262 if (
auto Err = decodeCounter(EncodedCounterAndRegion,
C))
268 ExpandedFileID = EncodedCounterAndRegion >>
270 if (ExpandedFileID >= NumFileIDs)
273 switch (EncodedCounterAndRegion >>
284 if (
auto Err = readCounter(
C))
286 if (
auto Err = readCounter(C2))
296 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
308 LineStart += LineStartDelta;
311 if (ColumnEnd & (1U << 31)) {
313 ColumnEnd &= ~(1U << 31);
324 if (ColumnStart == 0 && ColumnEnd == 0) {
330 dbgs() <<
"Counter in file " << InferredFileID <<
" " << LineStart <<
":"
331 << ColumnStart <<
" -> " << (LineStart + NumLines) <<
":"
332 << ColumnEnd <<
", ";
334 dbgs() <<
"Expands to file " << ExpandedFileID;
341 LineStart, ColumnStart,
342 LineStart + NumLines, ColumnEnd,
Kind);
343 if (CMR.startLoc() > CMR.endLoc())
345 MappingRegions.push_back(CMR);
354 if (
auto Err = readSize(NumFileMappings))
356 for (
size_t I = 0;
I < NumFileMappings; ++
I) {
358 if (
auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
360 VirtualFileMapping.push_back(FilenameIndex);
364 for (
auto I : VirtualFileMapping) {
365 Filenames.push_back(TranslationUnitFilenames[
I]);
370 if (
auto Err = readSize(NumExpressions))
378 for (
size_t I = 0;
I < NumExpressions; ++
I) {
386 for (
unsigned InferredFileID = 0,
S = VirtualFileMapping.size();
387 InferredFileID <
S; ++InferredFileID) {
388 if (
auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
389 VirtualFileMapping.size()))
399 FileIDExpansionRegionMapping.
resize(VirtualFileMapping.size(),
nullptr);
400 for (
unsigned Pass = 1,
S = VirtualFileMapping.size();
Pass <
S; ++
Pass) {
401 for (
auto &R : MappingRegions) {
404 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
405 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
407 for (
auto &R : MappingRegions) {
408 if (FileIDExpansionRegionMapping[R.FileID]) {
409 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
410 FileIDExpansionRegionMapping[R.FileID] =
nullptr;
421 if (
Error Err = readSize(NumFileMappings))
423 if (NumFileMappings != 1)
431 if (
Error Err = readSize(NumExpressions))
433 if (NumExpressions != 0)
436 if (
Error Err = readSize(NumRegions))
441 if (
Error Err = readIntMax(EncodedCounterAndRegion,
453 Address = Section.getAddress();
457 const ObjectFile *Obj = Section.getObject();
458 if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
465 if (Pointer < Address)
467 auto Offset = Pointer - Address;
468 if (Offset + Size >
Data.size())
470 return Data.substr(Pointer - Address, Size);
488 : StartingIndex(StartingIndex), Length(Length) {}
497 struct CovMapFuncRecordReader {
498 virtual ~CovMapFuncRecordReader() =
default;
508 const char *CovBufEnd) = 0;
520 virtual Error readFunctionRecords(
const char *FuncRecBuf,
521 const char *FuncRecBufEnd,
523 const char *OutOfLineMappingBuf,
524 const char *OutOfLineMappingBufEnd) = 0;
526 template <
class IntPtrT, support::endianness Endian>
529 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
StringRef D,
530 std::vector<std::string> &
F);
534 template <CovMapVersion Version,
class IntPtrT, support::endianness Endian>
535 class VersionedCovMapFuncRecordReader :
public CovMapFuncRecordReader {
536 using FuncRecordType =
545 std::vector<std::string> &Filenames;
546 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
558 Error insertFunctionRecordIfNeeded(
const FuncRecordType *CFR,
562 uint64_t FuncHash = CFR->template getFuncHash<Endian>();
563 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
565 FunctionRecords.
insert(std::make_pair(NameRef, Records.size()));
566 if (InsertResult.second) {
568 if (
Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
570 if (FuncName.
empty())
572 "function name is empty");
573 ++CovMapNumUsedRecords;
574 Records.emplace_back(
Version, FuncName, FuncHash, Mapping,
579 size_t OldRecordIndex = InsertResult.first->second;
581 Records[OldRecordIndex];
586 if (!*OldIsDummyExpected)
592 if (*NewIsDummyExpected)
594 ++CovMapNumUsedRecords;
603 VersionedCovMapFuncRecordReader(
605 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
StringRef D,
606 std::vector<std::string> &
F)
607 : ProfileNames(
P), CompilationDir(
D), Filenames(
F), Records(
R) {}
609 ~VersionedCovMapFuncRecordReader()
override =
default;
612 const char *CovBufEnd)
override {
617 auto CovHeader =
reinterpret_cast<const CovMapHeader *
>(CovBuf);
618 uint32_t NRecords = CovHeader->getNRecords<Endian>();
619 uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
620 uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
622 CovBuf =
reinterpret_cast<const char *
>(CovHeader + 1);
627 const char *FuncRecBuf =
nullptr;
628 const char *FuncRecBufEnd =
nullptr;
631 CovBuf += NRecords *
sizeof(FuncRecordType);
633 FuncRecBufEnd = CovBuf;
636 if (CovBuf + FilenamesSize > CovBufEnd)
638 size_t FilenamesBegin = Filenames.size();
639 StringRef FilenameRegion(CovBuf, FilenamesSize);
642 if (
auto Err = Reader.read(
Version))
644 CovBuf += FilenamesSize;
645 FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
650 int64_t FilenamesRef =
653 FileRangeMap.
insert(std::make_pair(FilenamesRef, FileRange));
657 auto It = Filenames.begin();
664 FileRange = OrigRange;
674 const char *MappingBuf = CovBuf;
677 CovBuf += CoverageSize;
678 const char *MappingEnd = CovBuf;
680 if (CovBuf > CovBufEnd)
685 if (
Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
686 MappingBuf, MappingEnd))
697 Error readFunctionRecords(
const char *FuncRecBuf,
const char *FuncRecBufEnd,
699 const char *OutOfLineMappingBuf,
700 const char *OutOfLineMappingBufEnd)
override {
701 auto CFR =
reinterpret_cast<const FuncRecordType *
>(FuncRecBuf);
702 while ((
const char *)CFR < FuncRecBufEnd) {
704 const char *NextMappingBuf;
705 const FuncRecordType *NextCFR;
706 std::tie(NextMappingBuf, NextCFR) =
707 CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
709 if (NextMappingBuf > OutOfLineMappingBufEnd)
715 FileRange = OutOfLineFileRange;
717 uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
718 auto It = FileRangeMap.
find(FilenamesRef);
719 if (It == FileRangeMap.
end())
722 FileRange = It->getSecond();
726 if (FileRange && !FileRange->
isInvalid()) {
728 CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
730 Mapping.
data() + Mapping.
size() > FuncRecBufEnd)
732 if (
Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
736 std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
744 template <
class IntPtrT, support::endianness Endian>
747 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
StringRef D,
748 std::vector<std::string> &
F) {
749 using namespace coverage;
753 return std::make_unique<VersionedCovMapFuncRecordReader<
761 if (
Error E =
P.create(
P.getNameData()))
764 return std::make_unique<VersionedCovMapFuncRecordReader<
767 return std::make_unique<VersionedCovMapFuncRecordReader<
770 return std::make_unique<VersionedCovMapFuncRecordReader<
773 return std::make_unique<VersionedCovMapFuncRecordReader<
776 return std::make_unique<VersionedCovMapFuncRecordReader<
782 template <
typename T, support::endianness Endian>
785 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
786 StringRef CompilationDir, std::vector<std::string> &Filenames) {
787 using namespace coverage;
796 CovMapFuncRecordReader::get<T, Endian>(
Version, ProfileNames, Records,
797 CompilationDir, Filenames);
801 const char *CovBuf = CovMap.
data();
802 const char *CovBufEnd = CovBuf + CovMap.
size();
803 const char *FuncRecBuf = FuncRecords.
data();
804 const char *FuncRecBufEnd = FuncRecords.
data() + FuncRecords.
size();
805 while (CovBuf < CovBufEnd) {
812 auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
813 if (
auto E = NextOrErr.takeError())
815 CovBuf = NextOrErr.get();
820 return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd,
None,
nullptr,
832 std::unique_ptr<BinaryCoverageReader> Reader(
834 Reader->ProfileNames =
std::move(ProfileNames);
835 StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
838 readCoverageMappingData<uint32_t, support::endianness::little>(
839 Reader->ProfileNames, Coverage, FuncRecordsRef,
840 Reader->MappingRecords, CompilationDir, Reader->Filenames))
843 if (
Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
844 Reader->ProfileNames, Coverage, FuncRecordsRef,
845 Reader->MappingRecords, CompilationDir, Reader->Filenames))
849 readCoverageMappingData<uint64_t, support::endianness::little>(
850 Reader->ProfileNames, Coverage, FuncRecordsRef,
851 Reader->MappingRecords, CompilationDir, Reader->Filenames))
854 if (
Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
855 Reader->ProfileNames, Coverage, FuncRecordsRef,
856 Reader->MappingRecords, CompilationDir, Reader->Filenames))
865 uint8_t BytesInAddress = 8;
883 if (
Data.size() < ProfileNamesSize)
886 if (
Error E = ProfileNames.
create(
Data.substr(0, ProfileNamesSize), Address))
888 Data =
Data.substr(ProfileNamesSize);
891 if (
Data.size() < Pad)
896 auto const *CovHeader =
reinterpret_cast<const CovMapHeader *
>(
914 Data =
Data.substr(CoverageMappingSize);
918 if (
Data.size() < Pad)
921 if (CoverageRecords->getBufferSize() == 0)
926 BytesInAddress, Endian, CompilationDir);
936 bool IsCOFF = isa<COFFObjectFile>(OF);
938 return IsCOFF ?
N.split(
'$').first :
N;
942 std::vector<SectionRef> Sections;
943 for (
const auto &Section : OF.sections()) {
947 if (stripSuffix(*NameOrErr) ==
Name)
948 Sections.push_back(Section);
950 if (Sections.empty())
958 std::unique_ptr<ObjectFile> OF;
959 if (
auto *Universal = dyn_cast<MachOUniversalBinary>(
Bin.get())) {
962 auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
963 if (!ObjectFileOrErr)
964 return ObjectFileOrErr.takeError();
966 }
else if (isa<ObjectFile>(
Bin.get())) {
968 OF.reset(cast<ObjectFile>(
Bin.release()));
970 if (!Arch.
empty() && OF->getArch() !=
Triple(Arch).getArch())
977 uint8_t BytesInAddress = OF->getBytesInAddress();
983 auto ObjFormat = OF->getTripleObjectFormat();
987 if (
auto E = NamesSection.takeError())
989 auto CoverageSection =
992 if (
auto E = CoverageSection.takeError())
994 std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
995 if (CoverageSectionRefs.size() != 1)
997 auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
998 if (!CoverageMappingOrErr)
999 return CoverageMappingOrErr.takeError();
1003 std::vector<SectionRef> NamesSectionRefs = *NamesSection;
1004 if (NamesSectionRefs.size() != 1)
1006 if (
Error E = ProfileNames.
create(NamesSectionRefs.back()))
1010 auto CoverageRecordsSections =
1015 if (
auto E = CoverageRecordsSections.takeError()) {
1023 const Align RecordAlignment(8);
1025 for (SectionRef Section : *CoverageRecordsSections) {
1026 auto CoverageRecordsOrErr = Section.getContents();
1027 if (!CoverageRecordsOrErr)
1028 return CoverageRecordsOrErr.takeError();
1029 FuncRecordsSize +=
alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
1031 auto WritableBuffer =
1033 char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
1035 "Allocated memory is correctly aligned");
1037 for (SectionRef Section : *CoverageRecordsSections) {
1038 auto CoverageRecordsOrErr = Section.getContents();
1039 if (!CoverageRecordsOrErr)
1040 return CoverageRecordsOrErr.takeError();
1041 const auto &CoverageRecords = CoverageRecordsOrErr.get();
1042 FuncRecordsBuffer =
std::copy(CoverageRecords.begin(),
1043 CoverageRecords.end(), FuncRecordsBuffer);
1045 std::fill_n(FuncRecordsBuffer,
1046 alignAddr(FuncRecordsBuffer, RecordAlignment) -
1047 (uintptr_t)FuncRecordsBuffer,
1050 assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
1052 FuncRecords =
std::move(WritableBuffer);
1057 BytesInAddress, Endian, CompilationDir);
1064 if (
auto *Universal = dyn_cast<MachOUniversalBinary>(
Bin)) {
1065 for (
auto &ObjForArch : Universal->objects())
1066 if (Arch == ObjForArch.getArchFlagName())
1078 std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
1085 return ReaderOrErr.takeError();
1086 Readers.push_back(
std::move(ReaderOrErr.get()));
1092 return BinOrErr.takeError();
1093 std::unique_ptr<Binary>
Bin =
std::move(BinOrErr.get());
1096 return make_error<CoverageMapError>(
1101 if (
auto *Universal = dyn_cast<MachOUniversalBinary>(
Bin.get())) {
1102 for (
auto &ObjForArch : Universal->objects()) {
1104 std::string ObjArch = ObjForArch.getArchFlagName();
1105 if (Arch != ObjArch)
1108 auto ArchiveOrErr = ObjForArch.getAsArchive();
1109 if (!ArchiveOrErr) {
1116 ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
1122 if (
auto *Ar = dyn_cast<Archive>(
Bin.get())) {
1124 for (
auto &Child : Ar->children(Err)) {
1130 ChildBufOrErr.
get(), Arch, ObjectFileBuffers, CompilationDir);
1131 if (!ChildReadersOrErr)
1132 return ChildReadersOrErr.takeError();
1133 for (
auto &Reader : ChildReadersOrErr.get())
1143 for (
auto &Buffer : Ar->takeThinBuffers())
1144 ObjectFileBuffers.push_back(
std::move(Buffer));
1151 return ReaderOrErr.takeError();
1152 Readers.push_back(
std::move(ReaderOrErr.get()));
1157 if (CurrentRecord >= MappingRecords.size())
1160 FunctionsFilenames.clear();
1162 MappingRegions.clear();
1163 auto &R = MappingRecords[CurrentRecord];
1164 auto F =
makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
1167 if (
auto Err = Reader.
read())
1170 Record.FunctionName = R.FunctionName;
1171 Record.FunctionHash = R.FunctionHash;
1172 Record.Filenames = FunctionsFilenames;
1174 Record.MappingRegions = MappingRegions;