From 406a47c17fa332c38cc8506e82876f2246ae88f7 Mon Sep 17 00:00:00 2001 From: Justin Bogner Date: Wed, 6 May 2015 23:19:35 +0000 Subject: [PATCH] InstrProf: Give coverage its own errors instead of piggy backing on instrprof Since the coverage mapping reader and the instrprof reader were emitting a shared set of error codes, the error messages you'd get back from llvm-cov were ambiguous about what was actually wrong. Add another error category to fix this. I've also improved the wording on a couple of the instrprof errors, for consistency. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236665 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ProfileData/CoverageMapping.h | 19 ++++++ lib/ProfileData/CoverageMapping.cpp | 31 ++++++++++ lib/ProfileData/CoverageMappingReader.cpp | 58 +++++++++---------- lib/ProfileData/InstrProf.cpp | 8 +-- .../raw-magic-but-no-header.test | 2 +- 5 files changed, 84 insertions(+), 34 deletions(-) diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h index e9d6ea5a492..94e655c3edc 100644 --- a/include/llvm/ProfileData/CoverageMapping.h +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -484,7 +484,26 @@ template<> struct DenseMapInfo { } }; +const std::error_category &coveragemap_category(); + +enum class coveragemap_error { + success = 0, + eof, + no_data_found, + unsupported_version, + truncated, + malformed +}; + +inline std::error_code make_error_code(coveragemap_error E) { + return std::error_code(static_cast(E), coveragemap_category()); +} } // end namespace llvm +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} + #endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ diff --git a/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp index 5f1d94af715..db70ef219aa 100644 --- a/lib/ProfileData/CoverageMapping.cpp +++ b/lib/ProfileData/CoverageMapping.cpp @@ -20,6 +20,7 @@ #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -495,3 +496,33 @@ CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) { return ExpansionCoverage; } + +namespace { +class CoverageMappingErrorCategoryType : public std::error_category { + const char *name() const LLVM_NOEXCEPT override { return "llvm.coveragemap"; } + std::string message(int IE) const override { + auto E = static_cast(IE); + switch (E) { + case coveragemap_error::success: + return "Success"; + case coveragemap_error::eof: + return "End of File"; + case coveragemap_error::no_data_found: + return "No coverage data found"; + case coveragemap_error::unsupported_version: + return "Unsupported coverage format version"; + case coveragemap_error::truncated: + return "Truncated coverage data"; + case coveragemap_error::malformed: + return "Malformed coverage data"; + } + llvm_unreachable("A value of coveragemap_error has no message."); + } +}; +} + +static ManagedStatic ErrorCategory; + +const std::error_category &llvm::coveragemap_category() { + return *ErrorCategory; +} diff --git a/lib/ProfileData/CoverageMappingReader.cpp b/lib/ProfileData/CoverageMappingReader.cpp index 2de8d2f8740..eb77f775ca6 100644 --- a/lib/ProfileData/CoverageMappingReader.cpp +++ b/lib/ProfileData/CoverageMappingReader.cpp @@ -36,11 +36,11 @@ void CoverageMappingIterator::increment() { std::error_code RawCoverageReader::readULEB128(uint64_t &Result) { if (Data.size() < 1) - return instrprof_error::truncated; + return coveragemap_error::truncated; unsigned N = 0; Result = decodeULEB128(reinterpret_cast(Data.data()), &N); if (N > Data.size()) - return instrprof_error::malformed; + return coveragemap_error::malformed; Data = Data.substr(N); return std::error_code(); } @@ -50,7 +50,7 @@ std::error_code RawCoverageReader::readIntMax(uint64_t &Result, if (auto Err = readULEB128(Result)) return Err; if (Result >= MaxPlus1) - return instrprof_error::malformed; + return coveragemap_error::malformed; return std::error_code(); } @@ -59,7 +59,7 @@ std::error_code RawCoverageReader::readSize(uint64_t &Result) { return Err; // Sanity check the number. if (Result > Data.size()) - return instrprof_error::malformed; + return coveragemap_error::malformed; return std::error_code(); } @@ -104,13 +104,13 @@ std::error_code RawCoverageMappingReader::decodeCounter(unsigned Value, case CounterExpression::Add: { auto ID = Value >> Counter::EncodingTagBits; if (ID >= Expressions.size()) - return instrprof_error::malformed; + return coveragemap_error::malformed; Expressions[ID].Kind = CounterExpression::ExprKind(Tag); C = Counter::getExpression(ID); break; } default: - return instrprof_error::malformed; + return coveragemap_error::malformed; } return std::error_code(); } @@ -159,7 +159,7 @@ std::error_code RawCoverageMappingReader::readMappingRegionsSubArray( ExpandedFileID = EncodedCounterAndRegion >> Counter::EncodingCounterTagAndExpansionRegionTagBits; if (ExpandedFileID >= NumFileIDs) - return instrprof_error::malformed; + return coveragemap_error::malformed; } else { switch (EncodedCounterAndRegion >> Counter::EncodingCounterTagAndExpansionRegionTagBits) { @@ -170,7 +170,7 @@ std::error_code RawCoverageMappingReader::readMappingRegionsSubArray( Kind = CounterMappingRegion::SkippedRegion; break; default: - return instrprof_error::malformed; + return coveragemap_error::malformed; } } } @@ -183,7 +183,7 @@ std::error_code RawCoverageMappingReader::readMappingRegionsSubArray( if (auto Err = readULEB128(ColumnStart)) return Err; if (ColumnStart > std::numeric_limits::max()) - return instrprof_error::malformed; + return coveragemap_error::malformed; if (auto Err = readIntMax(NumLines, std::numeric_limits::max())) return Err; if (auto Err = readIntMax(ColumnEnd, std::numeric_limits::max())) @@ -301,17 +301,17 @@ struct SectionData { if (auto Err = Section.getContents(Data)) return Err; Address = Section.getAddress(); - return instrprof_error::success; + return std::error_code(); } std::error_code get(uint64_t Pointer, size_t Size, StringRef &Result) { if (Pointer < Address) - return instrprof_error::malformed; + return coveragemap_error::malformed; auto Offset = Pointer - Address; if (Offset + Size > Data.size()) - return instrprof_error::malformed; + return coveragemap_error::malformed; Result = Data.substr(Pointer - Address, Size); - return instrprof_error::success; + return std::error_code(); } }; } @@ -327,7 +327,7 @@ std::error_code readCoverageMappingData( // Read the records in the coverage data section. for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { if (Buf + 4 * sizeof(uint32_t) > End) - return instrprof_error::malformed; + return coveragemap_error::malformed; uint32_t NRecords = endian::readNext(Buf); uint32_t FilenamesSize = endian::readNext(Buf); uint32_t CoverageSize = endian::readNext(Buf); @@ -337,7 +337,7 @@ std::error_code readCoverageMappingData( case CoverageMappingVersion1: break; default: - return instrprof_error::unsupported_version; + return coveragemap_error::unsupported_version; } // Skip past the function records, saving the start and end for later. @@ -347,7 +347,7 @@ std::error_code readCoverageMappingData( // Get the filenames. if (Buf + FilenamesSize > End) - return instrprof_error::malformed; + return coveragemap_error::malformed; size_t FilenamesBegin = Filenames.size(); RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); if (auto Err = Reader.read()) @@ -359,7 +359,7 @@ std::error_code readCoverageMappingData( Buf += CoverageSize; const char *CovEnd = Buf; if (Buf > End) - return instrprof_error::malformed; + return coveragemap_error::malformed; while (FunBuf < FunEnd) { // Read the function information @@ -370,7 +370,7 @@ std::error_code readCoverageMappingData( // Now use that to read the coverage data. if (CovBuf + DataSize > CovEnd) - return instrprof_error::malformed; + return coveragemap_error::malformed; auto Mapping = StringRef(CovBuf, DataSize); CovBuf += DataSize; @@ -390,7 +390,7 @@ std::error_code readCoverageMappingData( } } - return instrprof_error::success; + return std::error_code(); } static const char *TestingFormatMagic = "llvmcovmtestdata"; @@ -405,26 +405,26 @@ static std::error_code loadTestingFormat(StringRef Data, Data = Data.substr(StringRef(TestingFormatMagic).size()); if (Data.size() < 1) - return instrprof_error::truncated; + return coveragemap_error::truncated; unsigned N = 0; auto ProfileNamesSize = decodeULEB128(reinterpret_cast(Data.data()), &N); if (N > Data.size()) - return instrprof_error::malformed; + return coveragemap_error::malformed; Data = Data.substr(N); if (Data.size() < 1) - return instrprof_error::truncated; + return coveragemap_error::truncated; N = 0; ProfileNames.Address = decodeULEB128(reinterpret_cast(Data.data()), &N); if (N > Data.size()) - return instrprof_error::malformed; + return coveragemap_error::malformed; Data = Data.substr(N); if (Data.size() < ProfileNamesSize) - return instrprof_error::malformed; + return coveragemap_error::malformed; ProfileNames.Data = Data.substr(0, ProfileNamesSize); CoverageMapping = Data.substr(ProfileNamesSize); - return instrprof_error::success; + return std::error_code(); } static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, @@ -453,7 +453,7 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, return object_error::arch_not_found; } else // We can only handle object files. - return instrprof_error::malformed; + return coveragemap_error::malformed; // The coverage uses native pointer sizes for the object it's written in. BytesInAddress = OF->getBytesInAddress(); @@ -476,7 +476,7 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, ++FoundSectionCount; } if (FoundSectionCount != 2) - return instrprof_error::bad_header; + return coveragemap_error::no_data_found; // Get the contents of the given sections. if (std::error_code EC = CoverageSection.getContents(CoverageMapping)) @@ -520,7 +520,7 @@ BinaryCoverageReader::create(std::unique_ptr &ObjectBuffer, EC = readCoverageMappingData( Profile, Coverage, Reader->MappingRecords, Reader->Filenames); else - return instrprof_error::malformed; + return coveragemap_error::malformed; if (EC) return EC; return std::move(Reader); @@ -529,7 +529,7 @@ BinaryCoverageReader::create(std::unique_ptr &ObjectBuffer, std::error_code BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { if (CurrentRecord >= MappingRecords.size()) - return instrprof_error::eof; + return coveragemap_error::eof; FunctionsFilenames.clear(); Expressions.clear(); diff --git a/lib/ProfileData/InstrProf.cpp b/lib/ProfileData/InstrProf.cpp index 900dff96739..92822a71402 100644 --- a/lib/ProfileData/InstrProf.cpp +++ b/lib/ProfileData/InstrProf.cpp @@ -29,13 +29,13 @@ class InstrProfErrorCategoryType : public std::error_category { case instrprof_error::eof: return "End of File"; case instrprof_error::bad_magic: - return "Invalid file format (bad magic)"; + return "Invalid profile data (bad magic)"; case instrprof_error::bad_header: - return "Invalid header"; + return "Invalid profile data (file header is corrupt)"; case instrprof_error::unsupported_version: - return "Unsupported format version"; + return "Unsupported profiling format version"; case instrprof_error::unsupported_hash_type: - return "Unsupported hash function"; + return "Unsupported profiling hash"; case instrprof_error::too_large: return "Too much profile data"; case instrprof_error::truncated: diff --git a/test/tools/llvm-profdata/raw-magic-but-no-header.test b/test/tools/llvm-profdata/raw-magic-but-no-header.test index 6db723c3e25..b2a697042b0 100644 --- a/test/tools/llvm-profdata/raw-magic-but-no-header.test +++ b/test/tools/llvm-profdata/raw-magic-but-no-header.test @@ -3,4 +3,4 @@ RUN: not llvm-profdata show %t 2>&1 | FileCheck %s RUN: printf '\377lprofr\201' > %t RUN: not llvm-profdata show %t 2>&1 | FileCheck %s -CHECK: error: {{.+}}: Invalid header +CHECK: error: {{.+}}: Invalid profile data (file header is corrupt) -- 2.34.1