diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | |
parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | 333 |
1 files changed, 226 insertions, 107 deletions
diff --git a/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 05737323314a..ac8e6b56379f 100644 --- a/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/contrib/llvm-project/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -68,7 +68,8 @@ Error RawCoverageReader::readULEB128(uint64_t &Result) { unsigned N = 0; Result = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of ULEB128 is too big"); Data = Data.substr(N); return Error::success(); } @@ -77,7 +78,9 @@ Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) { if (auto Err = readULEB128(Result)) return Err; if (Result >= MaxPlus1) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "the value of ULEB128 is greater than or equal to MaxPlus1"); return Error::success(); } @@ -85,7 +88,8 @@ Error RawCoverageReader::readSize(uint64_t &Result) { if (auto Err = readULEB128(Result)) return Err; if (Result > Data.size()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the value of ULEB128 is too big"); return Error::success(); } @@ -103,7 +107,8 @@ Error RawCoverageFilenamesReader::read(CovMapVersion Version) { if (auto Err = readSize(NumFilenames)) return Err; if (!NumFilenames) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "number of filenames is zero"); if (Version < CovMapVersion::Version4) return readUncompressed(Version, NumFilenames); @@ -201,13 +206,15 @@ Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) { case CounterExpression::Add: { auto ID = Value >> Counter::EncodingTagBits; if (ID >= Expressions.size()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "counter expression is invalid"); Expressions[ID].Kind = CounterExpression::ExprKind(Tag); C = Counter::getExpression(ID); break; } default: - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "counter expression kind is invalid"); } return Error::success(); } @@ -237,6 +244,7 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( unsigned LineStart = 0; for (size_t I = 0; I < NumRegions; ++I) { Counter C, C2; + uint64_t BIDX = 0, NC = 0, ID = 0, TID = 0, FID = 0; CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; // Read the combined counter + region kind. @@ -268,7 +276,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( ExpandedFileID = EncodedCounterAndRegion >> Counter::EncodingCounterTagAndExpansionRegionTagBits; if (ExpandedFileID >= NumFileIDs) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "ExpandedFileID is invalid"); } else { switch (EncodedCounterAndRegion >> Counter::EncodingCounterTagAndExpansionRegionTagBits) { @@ -286,8 +295,30 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( if (auto Err = readCounter(C2)) return Err; break; + case CounterMappingRegion::MCDCBranchRegion: + // For a MCDC Branch Region, read two successive counters and 3 IDs. + Kind = CounterMappingRegion::MCDCBranchRegion; + if (auto Err = readCounter(C)) + return Err; + if (auto Err = readCounter(C2)) + return Err; + if (auto Err = readIntMax(ID, std::numeric_limits<unsigned>::max())) + return Err; + if (auto Err = readIntMax(TID, std::numeric_limits<unsigned>::max())) + return Err; + if (auto Err = readIntMax(FID, std::numeric_limits<unsigned>::max())) + return Err; + break; + case CounterMappingRegion::MCDCDecisionRegion: + Kind = CounterMappingRegion::MCDCDecisionRegion; + if (auto Err = readIntMax(BIDX, std::numeric_limits<unsigned>::max())) + return Err; + if (auto Err = readIntMax(NC, std::numeric_limits<unsigned>::max())) + return Err; + break; default: - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "region kind is incorrect"); } } } @@ -300,7 +331,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( if (auto Err = readULEB128(ColumnStart)) return Err; if (ColumnStart > std::numeric_limits<unsigned>::max()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "start column is too big"); if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max())) return Err; if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max())) @@ -337,11 +369,18 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( dbgs() << "\n"; }); - auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID, - LineStart, ColumnStart, - LineStart + NumLines, ColumnEnd, Kind); + auto CMR = CounterMappingRegion( + C, C2, + CounterMappingRegion::MCDCParameters{ + static_cast<unsigned>(BIDX), static_cast<unsigned>(NC), + static_cast<unsigned>(ID), static_cast<unsigned>(TID), + static_cast<unsigned>(FID)}, + InferredFileID, ExpandedFileID, LineStart, ColumnStart, + LineStart + NumLines, ColumnEnd, Kind); if (CMR.startLoc() > CMR.endLoc()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "counter mapping region locations are incorrect"); MappingRegions.push_back(CMR); } return Error::success(); @@ -454,9 +493,13 @@ Error InstrProfSymtab::create(SectionRef &Section) { // If this is a linked PE/COFF file, then we have to skip over the null byte // that is allocated in the .lprfn$A section in the LLVM profiling runtime. + // If the name section is .lprfcovnames, it doesn't have the null byte at the + // beginning. const ObjectFile *Obj = Section.getObject(); if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject()) - Data = Data.drop_front(1); + if (Expected<StringRef> NameOrErr = Section.getName()) + if (*NameOrErr != getInstrProfSectionName(IPSK_covname, Triple::COFF)) + Data = Data.drop_front(1); return Error::success(); } @@ -523,7 +566,7 @@ struct CovMapFuncRecordReader { const char *OutOfLineMappingBuf, const char *OutOfLineMappingBufEnd) = 0; - template <class IntPtrT, support::endianness Endian> + template <class IntPtrT, llvm::endianness Endian> static Expected<std::unique_ptr<CovMapFuncRecordReader>> get(CovMapVersion Version, InstrProfSymtab &P, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, @@ -531,7 +574,7 @@ struct CovMapFuncRecordReader { }; // A class for reading coverage mapping function records for a module. -template <CovMapVersion Version, class IntPtrT, support::endianness Endian> +template <CovMapVersion Version, class IntPtrT, llvm::endianness Endian> class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { using FuncRecordType = typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType; @@ -613,7 +656,9 @@ public: using namespace support; if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "coverage mapping header section is larger than buffer size"); auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf); uint32_t NRecords = CovHeader->getNRecords<Endian>(); uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>(); @@ -634,7 +679,9 @@ public: // Get the filenames. if (CovBuf + FilenamesSize > CovBufEnd) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "filenames section is larger than buffer size"); size_t FilenamesBegin = Filenames.size(); StringRef FilenameRegion(CovBuf, FilenamesSize); RawCoverageFilenamesReader Reader(FilenameRegion, Filenames, @@ -673,12 +720,15 @@ public: // coverage header). const char *MappingBuf = CovBuf; if (Version >= CovMapVersion::Version4 && CoverageSize != 0) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "coverage mapping size is not zero"); CovBuf += CoverageSize; const char *MappingEnd = CovBuf; if (CovBuf > CovBufEnd) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "function records section is larger than buffer size"); if (Version < CovMapVersion::Version4) { // Read each function record. @@ -707,7 +757,9 @@ public: CFR->template advanceByOne<Endian>(OutOfLineMappingBuf); if (Version < CovMapVersion::Version4) if (NextMappingBuf > OutOfLineMappingBufEnd) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "next mapping buffer is larger than buffer size"); // Look up the set of filenames associated with this function record. std::optional<FilenameRange> FileRange; @@ -717,7 +769,10 @@ public: uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>(); auto It = FileRangeMap.find(FilenamesRef); if (It == FileRangeMap.end()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "no filename found for function with hash=0x" + + Twine::utohexstr(FilenamesRef)); else FileRange = It->getSecond(); } @@ -728,7 +783,9 @@ public: CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf); if (Version >= CovMapVersion::Version4 && Mapping.data() + Mapping.size() > FuncRecBufEnd) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "coverage mapping data is larger than buffer size"); if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange)) return Err; } @@ -741,7 +798,7 @@ public: } // end anonymous namespace -template <class IntPtrT, support::endianness Endian> +template <class IntPtrT, llvm::endianness Endian> Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( CovMapVersion Version, InstrProfSymtab &P, std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D, @@ -757,6 +814,7 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( case CovMapVersion::Version4: case CovMapVersion::Version5: case CovMapVersion::Version6: + case CovMapVersion::Version7: // Decompress the name data. if (Error E = P.create(P.getNameData())) return std::move(E); @@ -775,11 +833,14 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get( else if (Version == CovMapVersion::Version6) return std::make_unique<VersionedCovMapFuncRecordReader< CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F); + else if (Version == CovMapVersion::Version7) + return std::make_unique<VersionedCovMapFuncRecordReader< + CovMapVersion::Version7, IntPtrT, Endian>>(P, R, D, F); } llvm_unreachable("Unsupported version"); } -template <typename T, support::endianness Endian> +template <typename T, llvm::endianness Endian> static Error readCoverageMappingData( InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, @@ -822,114 +883,158 @@ static Error readCoverageMappingData( return Error::success(); } -static const char *TestingFormatMagic = "llvmcovmtestdata"; - Expected<std::unique_ptr<BinaryCoverageReader>> BinaryCoverageReader::createCoverageReaderFromBuffer( StringRef Coverage, FuncRecordsStorage &&FuncRecords, InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress, - support::endianness Endian, StringRef CompilationDir) { + llvm::endianness Endian, StringRef CompilationDir) { std::unique_ptr<BinaryCoverageReader> Reader( new BinaryCoverageReader(std::move(FuncRecords))); Reader->ProfileNames = std::move(ProfileNames); StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer(); - if (BytesInAddress == 4 && Endian == support::endianness::little) { - if (Error E = - readCoverageMappingData<uint32_t, support::endianness::little>( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + if (BytesInAddress == 4 && Endian == llvm::endianness::little) { + if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>( + Reader->ProfileNames, Coverage, FuncRecordsRef, + Reader->MappingRecords, CompilationDir, Reader->Filenames)) return std::move(E); - } else if (BytesInAddress == 4 && Endian == support::endianness::big) { - if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>( + } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) { + if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>( Reader->ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, CompilationDir, Reader->Filenames)) return std::move(E); - } else if (BytesInAddress == 8 && Endian == support::endianness::little) { - if (Error E = - readCoverageMappingData<uint64_t, support::endianness::little>( - Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, CompilationDir, Reader->Filenames)) + } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) { + if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>( + Reader->ProfileNames, Coverage, FuncRecordsRef, + Reader->MappingRecords, CompilationDir, Reader->Filenames)) return std::move(E); - } else if (BytesInAddress == 8 && Endian == support::endianness::big) { - if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>( + } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) { + if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>( Reader->ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords, CompilationDir, Reader->Filenames)) return std::move(E); } else - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "not supported endianness or bytes in address"); return std::move(Reader); } static Expected<std::unique_ptr<BinaryCoverageReader>> loadTestingFormat(StringRef Data, StringRef CompilationDir) { uint8_t BytesInAddress = 8; - support::endianness Endian = support::endianness::little; - - Data = Data.substr(StringRef(TestingFormatMagic).size()); + llvm::endianness Endian = llvm::endianness::little; + + // Read the magic and version. + Data = Data.substr(sizeof(TestingFormatMagic)); + if (Data.size() < sizeof(uint64_t)) + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of data is too small"); + auto TestingVersion = + support::endian::byte_swap<uint64_t, llvm::endianness::little>( + *reinterpret_cast<const uint64_t *>(Data.data())); + Data = Data.substr(sizeof(uint64_t)); + + // Read the ProfileNames data. if (Data.empty()) return make_error<CoverageMapError>(coveragemap_error::truncated); unsigned N = 0; uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "the size of TestingFormatMagic is too big"); Data = Data.substr(N); if (Data.empty()) return make_error<CoverageMapError>(coveragemap_error::truncated); N = 0; uint64_t Address = decodeULEB128(Data.bytes_begin(), &N); if (N > Data.size()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of ULEB128 is too big"); Data = Data.substr(N); if (Data.size() < ProfileNamesSize) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of ProfileNames is too big"); InstrProfSymtab ProfileNames; if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) return std::move(E); Data = Data.substr(ProfileNamesSize); + + // In Version2, the size of CoverageMapping is stored directly. + uint64_t CoverageMappingSize; + if (TestingVersion == uint64_t(TestingFormatVersion::Version2)) { + N = 0; + CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N); + if (N > Data.size()) + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of ULEB128 is too big"); + Data = Data.substr(N); + if (CoverageMappingSize < sizeof(CovMapHeader)) + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "the size of CoverageMapping is teoo small"); + } else if (TestingVersion != uint64_t(TestingFormatVersion::Version1)) { + return make_error<CoverageMapError>(coveragemap_error::unsupported_version); + } + // Skip the padding bytes because coverage map data has an alignment of 8. - size_t Pad = offsetToAlignedAddr(Data.data(), Align(8)); + auto Pad = offsetToAlignedAddr(Data.data(), Align(8)); if (Data.size() < Pad) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "insufficient padding"); Data = Data.substr(Pad); if (Data.size() < sizeof(CovMapHeader)) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "coverage mapping header section is larger than data size"); auto const *CovHeader = reinterpret_cast<const CovMapHeader *>( Data.substr(0, sizeof(CovMapHeader)).data()); - CovMapVersion Version = - (CovMapVersion)CovHeader->getVersion<support::endianness::little>(); - StringRef CoverageMapping; - BinaryCoverageReader::FuncRecordsStorage CoverageRecords; + auto Version = + CovMapVersion(CovHeader->getVersion<llvm::endianness::little>()); + + // In Version1, the size of CoverageMapping is calculated. + if (TestingVersion == uint64_t(TestingFormatVersion::Version1)) { + if (Version < CovMapVersion::Version4) { + CoverageMappingSize = Data.size(); + } else { + auto FilenamesSize = + CovHeader->getFilenamesSize<llvm::endianness::little>(); + CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize; + } + } + + auto CoverageMapping = Data.substr(0, CoverageMappingSize); + Data = Data.substr(CoverageMappingSize); + + // Read the CoverageRecords data. if (Version < CovMapVersion::Version4) { - CoverageMapping = Data; - if (CoverageMapping.empty()) - return make_error<CoverageMapError>(coveragemap_error::truncated); - CoverageRecords = MemoryBuffer::getMemBuffer(""); + if (!Data.empty()) + return make_error<CoverageMapError>(coveragemap_error::malformed, + "data is not empty"); } else { - uint32_t FilenamesSize = - CovHeader->getFilenamesSize<support::endianness::little>(); - uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize; - CoverageMapping = Data.substr(0, CoverageMappingSize); - if (CoverageMapping.empty()) - return make_error<CoverageMapError>(coveragemap_error::truncated); - Data = Data.substr(CoverageMappingSize); // Skip the padding bytes because coverage records data has an alignment // of 8. Pad = offsetToAlignedAddr(Data.data(), Align(8)); if (Data.size() < Pad) - return make_error<CoverageMapError>(coveragemap_error::malformed); - CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad)); - if (CoverageRecords->getBufferSize() == 0) - return make_error<CoverageMapError>(coveragemap_error::truncated); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "insufficient padding"); + Data = Data.substr(Pad); } + BinaryCoverageReader::FuncRecordsStorage CoverageRecords = + MemoryBuffer::getMemBuffer(Data); + return BinaryCoverageReader::createCoverageReaderFromBuffer( CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames), BytesInAddress, Endian, CompilationDir); } -/// Find all sections that match \p Name. There may be more than one if comdats -/// are in use, e.g. for the __llvm_covfun section on ELF. -static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF, - StringRef Name) { +/// Find all sections that match \p IPSK name. There may be more than one if +/// comdats are in use, e.g. for the __llvm_covfun section on ELF. +static Expected<std::vector<SectionRef>> +lookupSections(ObjectFile &OF, InstrProfSectKind IPSK) { + auto ObjFormat = OF.getTripleObjectFormat(); + auto Name = + getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false); // On COFF, the object file section name may end in "$M". This tells the // linker to sort these sections between "$A" and "$Z". The linker removes the // dollar and everything after it in the final binary. Do the same to match. @@ -944,8 +1049,13 @@ static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF, Expected<StringRef> NameOrErr = Section.getName(); if (!NameOrErr) return NameOrErr.takeError(); - if (stripSuffix(*NameOrErr) == Name) + if (stripSuffix(*NameOrErr) == Name) { + // COFF profile name section contains two null bytes indicating the + // start/end of the section. If its size is 2 bytes, it's empty. + if (IsCOFF && IPSK == IPSK_name && Section.getSize() == 2) + continue; Sections.push_back(Section); + } } if (Sections.empty()) return make_error<CoverageMapError>(coveragemap_error::no_data_found); @@ -972,45 +1082,49 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, return errorCodeToError(object_error::arch_not_found); } else // We can only handle object files. - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "binary is not an object file"); // The coverage uses native pointer sizes for the object it's written in. uint8_t BytesInAddress = OF->getBytesInAddress(); - support::endianness Endian = OF->isLittleEndian() - ? support::endianness::little - : support::endianness::big; + llvm::endianness Endian = + OF->isLittleEndian() ? llvm::endianness::little : llvm::endianness::big; // Look for the sections that we are interested in. - auto ObjFormat = OF->getTripleObjectFormat(); - auto NamesSection = - lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat, - /*AddSegmentInfo=*/false)); - if (auto E = NamesSection.takeError()) + InstrProfSymtab ProfileNames; + std::vector<SectionRef> NamesSectionRefs; + // If IPSK_name is not found, fallback to search for IPK_covname, which is + // used when binary correlation is enabled. + auto NamesSection = lookupSections(*OF, IPSK_name); + if (auto E = NamesSection.takeError()) { + consumeError(std::move(E)); + NamesSection = lookupSections(*OF, IPSK_covname); + if (auto E = NamesSection.takeError()) + return std::move(E); + } + NamesSectionRefs = *NamesSection; + + if (NamesSectionRefs.size() != 1) + return make_error<CoverageMapError>( + coveragemap_error::malformed, + "the size of coverage mapping section is not one"); + if (Error E = ProfileNames.create(NamesSectionRefs.back())) return std::move(E); - auto CoverageSection = - lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat, - /*AddSegmentInfo=*/false)); + + auto CoverageSection = lookupSections(*OF, IPSK_covmap); if (auto E = CoverageSection.takeError()) return std::move(E); std::vector<SectionRef> CoverageSectionRefs = *CoverageSection; if (CoverageSectionRefs.size() != 1) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of name section is not one"); auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents(); if (!CoverageMappingOrErr) return CoverageMappingOrErr.takeError(); StringRef CoverageMapping = CoverageMappingOrErr.get(); - InstrProfSymtab ProfileNames; - std::vector<SectionRef> NamesSectionRefs = *NamesSection; - if (NamesSectionRefs.size() != 1) - return make_error<CoverageMapError>(coveragemap_error::malformed); - if (Error E = ProfileNames.create(NamesSectionRefs.back())) - return std::move(E); - // Look for the coverage records section (Version4 only). - auto CoverageRecordsSections = - lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat, - /*AddSegmentInfo=*/false)); + auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun); BinaryCoverageReader::FuncRecordsStorage FuncRecords; if (auto E = CoverageRecordsSections.takeError()) { @@ -1081,14 +1195,19 @@ BinaryCoverageReader::create( StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) { std::vector<std::unique_ptr<BinaryCoverageReader>> Readers; - if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) { - // This is a special format used for testing. - auto ReaderOrErr = - loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir); - if (!ReaderOrErr) - return ReaderOrErr.takeError(); - Readers.push_back(std::move(ReaderOrErr.get())); - return std::move(Readers); + if (ObjectBuffer.getBuffer().size() > sizeof(TestingFormatMagic)) { + uint64_t Magic = + support::endian::byte_swap<uint64_t, llvm::endianness::little>( + *reinterpret_cast<const uint64_t *>(ObjectBuffer.getBufferStart())); + if (Magic == TestingFormatMagic) { + // This is a special format used for testing. + auto ReaderOrErr = + loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir); + if (!ReaderOrErr) + return ReaderOrErr.takeError(); + Readers.push_back(std::move(ReaderOrErr.get())); + return std::move(Readers); + } } auto BinOrErr = createBinary(ObjectBuffer); |