diff options
author | Yuhao Gu <yhgu2000@outlook.com> | 2023-08-15 00:36:54 +0000 |
---|---|---|
committer | Gulfem Savrun Yeniceri <gulfem@google.com> | 2023-08-15 02:51:28 +0000 |
commit | f8ad86c23405168a8cd189590184fdcc296627e0 (patch) | |
tree | 794bc25062b2a57d7a2c4b51fc3518aa9c20fb0b /llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | |
parent | 2660fef880190f2895490414d89265134a0732a0 (diff) | |
download | llvm-f8ad86c23405168a8cd189590184fdcc296627e0.zip llvm-f8ad86c23405168a8cd189590184fdcc296627e0.tar.gz llvm-f8ad86c23405168a8cd189590184fdcc296627e0.tar.bz2 |
[llvm-cov] Fix a bug about using `convert-for-testing` on multi-source object files
`llvm-cov convert-for-testing` is used to build the .covmapping files used in its regression tests. However the current implementation only works when there's only one source file in the mapping information data. If there are more than 1 source files, `llvm-cov convert-for-testing` can still produce a .covmapping file, but when read it back, `llvm-cov` will report:
```
error: Failed to load coverage: 'main.covmapping': Malformed coverage data
```
This is because the output .covmapping file doesn't have any mark to indicate the boundary between file records and function records, and current implementation jsut assume there's only one file record in the .covmapping file.
Changes to the code:
- Make `llvm-cov convert-for-testing` output a LEB128 number before file records to indicate its size.
- Change the testing format parsing code correspondingly.
- Update existing .covmapping files.
Reviewed By: gulfem
Differential Revision: https://reviews.llvm.org/D156611
Diffstat (limited to 'llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp')
-rw-r--r-- | llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp | 49 |
1 files changed, 27 insertions, 22 deletions
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 0573732..2f290b2 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -886,41 +886,46 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) { if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address)) return std::move(E); Data = Data.substr(ProfileNamesSize); + + N = 0; + uint64_t CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N); + if (N > Data.size()) + return make_error<CoverageMapError>(coveragemap_error::malformed); + Data = Data.substr(N); + // Skip the padding bytes because coverage map data has an alignment of 8. size_t Pad = offsetToAlignedAddr(Data.data(), Align(8)); if (Data.size() < Pad) return make_error<CoverageMapError>(coveragemap_error::malformed); Data = Data.substr(Pad); - if (Data.size() < sizeof(CovMapHeader)) + if (Data.size() < CoverageMappingSize) + return make_error<CoverageMapError>(coveragemap_error::malformed); + StringRef CoverageMapping = Data.substr(0, CoverageMappingSize); + 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); - auto const *CovHeader = reinterpret_cast<const CovMapHeader *>( - Data.substr(0, sizeof(CovMapHeader)).data()); + Data = Data.substr(Pad); + BinaryCoverageReader::FuncRecordsStorage CoverageRecords = + MemoryBuffer::getMemBuffer(Data); + + // Some extra checking. + if (CoverageMapping.size() < sizeof(CovMapHeader)) + return make_error<CoverageMapError>(coveragemap_error::truncated); + auto const *CovHeader = + reinterpret_cast<const CovMapHeader *>(CoverageMapping.data()); CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<support::endianness::little>(); - StringRef CoverageMapping; - BinaryCoverageReader::FuncRecordsStorage CoverageRecords; if (Version < CovMapVersion::Version4) { - CoverageMapping = Data; - if (CoverageMapping.empty()) - return make_error<CoverageMapError>(coveragemap_error::truncated); - CoverageRecords = MemoryBuffer::getMemBuffer(""); - } 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) + if (CoverageRecords->getBufferSize() != 0) return make_error<CoverageMapError>(coveragemap_error::malformed); - CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad)); + } else { if (CoverageRecords->getBufferSize() == 0) return make_error<CoverageMapError>(coveragemap_error::truncated); } + return BinaryCoverageReader::createCoverageReaderFromBuffer( CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames), BytesInAddress, Endian, CompilationDir); |