diff options
author | MaggieYingYi <29144504+MaggieYingYi@users.noreply.github.com> | 2023-09-06 15:02:31 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-09-06 15:02:31 +0100 |
commit | cd8fe1dbcb7dd36f700681ced34b41993e844239 (patch) | |
tree | 1cf9fb3a828c34675abc6234508b83e606ef5739 /llvm/lib/ProfileData/Coverage | |
parent | 6258912880876edd44944e130aef01b33480168b (diff) | |
download | llvm-cd8fe1dbcb7dd36f700681ced34b41993e844239.zip llvm-cd8fe1dbcb7dd36f700681ced34b41993e844239.tar.gz llvm-cd8fe1dbcb7dd36f700681ced34b41993e844239.tar.bz2 |
[llvm-cov] - Output better error message when the error kind is `coveragemap_error::malforme`. (#65264)
The current llvm-cov error message for kind `coveragemap_error::malforme`, just gives the issue kind without any reason for what caused the issue. This patch is aimed at improving the llvm-cov error message to help identify what caused the issue.
Reviewed By: MaskRay
Close: https://github.com/llvm/llvm-project/pull/65264
Diffstat (limited to 'llvm/lib/ProfileData/Coverage')
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMapping.cpp | 46 | ||||
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | 107 |
2 files changed, 109 insertions, 44 deletions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp index 849ee80..ff4171d 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp @@ -237,7 +237,8 @@ Error CoverageMapping::loadFunctionRecord( IndexedInstrProfReader &ProfileReader) { StringRef OrigFuncName = Record.FunctionName; if (OrigFuncName.empty()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "record function name is empty"); if (Record.Filenames.empty()) OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName); @@ -342,7 +343,7 @@ static Error handleMaybeNoDataFoundError(Error E) { std::move(E), [](const CoverageMapError &CME) { if (CME.get() == coveragemap_error::no_data_found) return static_cast<Error>(Error::success()); - return make_error<CoverageMapError>(CME.get()); + return make_error<CoverageMapError>(CME.get(), CME.getMessage()); }); } @@ -925,26 +926,45 @@ LineCoverageIterator &LineCoverageIterator::operator++() { return *this; } -static std::string getCoverageMapErrString(coveragemap_error Err) { +static std::string getCoverageMapErrString(coveragemap_error Err, + const std::string &ErrMsg = "") { + std::string Msg; + raw_string_ostream OS(Msg); + switch (Err) { case coveragemap_error::success: - return "Success"; + OS << "success"; + break; case coveragemap_error::eof: - return "End of File"; + OS << "end of File"; + break; case coveragemap_error::no_data_found: - return "No coverage data found"; + OS << "no coverage data found"; + break; case coveragemap_error::unsupported_version: - return "Unsupported coverage format version"; + OS << "unsupported coverage format version"; + break; case coveragemap_error::truncated: - return "Truncated coverage data"; + OS << "truncated coverage data"; + break; case coveragemap_error::malformed: - return "Malformed coverage data"; + OS << "malformed coverage data"; + break; case coveragemap_error::decompression_failed: - return "Failed to decompress coverage data (zlib)"; + OS << "failed to decompress coverage data (zlib)"; + break; case coveragemap_error::invalid_or_missing_arch_specifier: - return "`-arch` specifier is invalid or missing for universal binary"; + OS << "`-arch` specifier is invalid or missing for universal binary"; + break; + default: + llvm_unreachable("invalid coverage mapping error."); } - llvm_unreachable("A value of coveragemap_error has no message."); + + // If optional error message is not empty, append it to the message. + if (!ErrMsg.empty()) + OS << ": " << ErrMsg; + + return Msg; } namespace { @@ -962,7 +982,7 @@ class CoverageMappingErrorCategoryType : public std::error_category { } // end anonymous namespace std::string CoverageMapError::message() const { - return getCoverageMapErrString(Err); + return getCoverageMapErrString(Err, Msg); } const std::error_category &llvm::coverage::coveragemap_category() { diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index bee9c8d..e468fbf 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/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(); } @@ -268,7 +275,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) { @@ -287,7 +295,8 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( return Err; break; default: - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "region kind is incorrect"); } } } @@ -300,7 +309,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())) @@ -341,7 +351,9 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray( 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(); @@ -613,7 +625,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 +648,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 +689,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 +726,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 +738,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 +752,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; } @@ -854,7 +880,9 @@ BinaryCoverageReader::createCoverageReaderFromBuffer( 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); } @@ -866,7 +894,8 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { // Read the magic and version. Data = Data.substr(sizeof(TestingFormatMagic)); if (Data.size() < sizeof(uint64_t)) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "the size of data is too small"); auto TestingVersion = support::endian::byte_swap<uint64_t, support::endianness::little>( *reinterpret_cast<const uint64_t *>(Data.data())); @@ -878,17 +907,21 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { 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); @@ -900,10 +933,13 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { N = 0; CoverageMappingSize = 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 (CoverageMappingSize < sizeof(CovMapHeader)) - return make_error<CoverageMapError>(coveragemap_error::malformed); + 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); } @@ -911,10 +947,13 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { // Skip the padding bytes because coverage map data has an alignment of 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()); auto Version = @@ -937,13 +976,15 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { // Read the CoverageRecords data. if (Version < CovMapVersion::Version4) { if (!Data.empty()) - return make_error<CoverageMapError>(coveragemap_error::malformed); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "data is not empty"); } else { // 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); + return make_error<CoverageMapError>(coveragemap_error::malformed, + "insufficient padding"); Data = Data.substr(Pad); } BinaryCoverageReader::FuncRecordsStorage CoverageRecords = @@ -1000,7 +1041,8 @@ 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(); @@ -1022,7 +1064,8 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, 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(); @@ -1031,7 +1074,9 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch, InstrProfSymtab ProfileNames; std::vector<SectionRef> NamesSectionRefs = *NamesSection; if (NamesSectionRefs.size() != 1) - return make_error<CoverageMapError>(coveragemap_error::malformed); + 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); |