Skip to content

Commit f8ad86c

Browse files
yhgu2000gulfemsavrun
authored andcommitted
[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
1 parent 2660fef commit f8ad86c

32 files changed

+28
-22
lines changed

llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -886,41 +886,46 @@ loadTestingFormat(StringRef Data, StringRef CompilationDir) {
886886
if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
887887
return std::move(E);
888888
Data = Data.substr(ProfileNamesSize);
889+
890+
N = 0;
891+
uint64_t CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N);
892+
if (N > Data.size())
893+
return make_error<CoverageMapError>(coveragemap_error::malformed);
894+
Data = Data.substr(N);
895+
889896
// Skip the padding bytes because coverage map data has an alignment of 8.
890897
size_t Pad = offsetToAlignedAddr(Data.data(), Align(8));
891898
if (Data.size() < Pad)
892899
return make_error<CoverageMapError>(coveragemap_error::malformed);
893900
Data = Data.substr(Pad);
894-
if (Data.size() < sizeof(CovMapHeader))
901+
if (Data.size() < CoverageMappingSize)
902+
return make_error<CoverageMapError>(coveragemap_error::malformed);
903+
StringRef CoverageMapping = Data.substr(0, CoverageMappingSize);
904+
Data = Data.substr(CoverageMappingSize);
905+
906+
// Skip the padding bytes because coverage records data has an alignment of 8.
907+
Pad = offsetToAlignedAddr(Data.data(), Align(8));
908+
if (Data.size() < Pad)
895909
return make_error<CoverageMapError>(coveragemap_error::malformed);
896-
auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
897-
Data.substr(0, sizeof(CovMapHeader)).data());
910+
Data = Data.substr(Pad);
911+
BinaryCoverageReader::FuncRecordsStorage CoverageRecords =
912+
MemoryBuffer::getMemBuffer(Data);
913+
914+
// Some extra checking.
915+
if (CoverageMapping.size() < sizeof(CovMapHeader))
916+
return make_error<CoverageMapError>(coveragemap_error::truncated);
917+
auto const *CovHeader =
918+
reinterpret_cast<const CovMapHeader *>(CoverageMapping.data());
898919
CovMapVersion Version =
899920
(CovMapVersion)CovHeader->getVersion<support::endianness::little>();
900-
StringRef CoverageMapping;
901-
BinaryCoverageReader::FuncRecordsStorage CoverageRecords;
902921
if (Version < CovMapVersion::Version4) {
903-
CoverageMapping = Data;
904-
if (CoverageMapping.empty())
905-
return make_error<CoverageMapError>(coveragemap_error::truncated);
906-
CoverageRecords = MemoryBuffer::getMemBuffer("");
907-
} else {
908-
uint32_t FilenamesSize =
909-
CovHeader->getFilenamesSize<support::endianness::little>();
910-
uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
911-
CoverageMapping = Data.substr(0, CoverageMappingSize);
912-
if (CoverageMapping.empty())
913-
return make_error<CoverageMapError>(coveragemap_error::truncated);
914-
Data = Data.substr(CoverageMappingSize);
915-
// Skip the padding bytes because coverage records data has an alignment
916-
// of 8.
917-
Pad = offsetToAlignedAddr(Data.data(), Align(8));
918-
if (Data.size() < Pad)
922+
if (CoverageRecords->getBufferSize() != 0)
919923
return make_error<CoverageMapError>(coveragemap_error::malformed);
920-
CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad));
924+
} else {
921925
if (CoverageRecords->getBufferSize() == 0)
922926
return make_error<CoverageMapError>(coveragemap_error::truncated);
923927
}
928+
924929
return BinaryCoverageReader::createCoverageReaderFromBuffer(
925930
CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames),
926931
BytesInAddress, Endian, CompilationDir);
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

llvm/tools/llvm-cov/TestingSupport.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ int convertForTestingMain(int argc, const char *argv[]) {
111111
encodeULEB128(ProfileNamesData.size(), OS);
112112
encodeULEB128(ProfileNamesAddress, OS);
113113
OS << ProfileNamesData;
114+
encodeULEB128(CoverageMappingData.size(), OS);
114115
// Coverage mapping data is expected to have an alignment of 8.
115116
for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad)
116117
OS.write(uint8_t(0));

0 commit comments

Comments
 (0)