From: Justin Bogner Date: Mon, 16 Mar 2015 21:40:18 +0000 (+0000) Subject: InstrProf: Fix CoverageMappingReader on big endian X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=4fefd5cdf45243e09249ef1a4b50259dc2d33b5a;p=oota-llvm.git InstrProf: Fix CoverageMappingReader on big endian This makes the reader check the endianness of the object file its given and behave appropriately. For the test I dug up a really old linker and created a ppc-apple-darwin file for llvm-cov to read. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232422 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ProfileData/CoverageMappingReader.cpp b/lib/ProfileData/CoverageMappingReader.cpp index fde6874fe40..0ca42e4bfdb 100644 --- a/lib/ProfileData/CoverageMappingReader.cpp +++ b/lib/ProfileData/CoverageMappingReader.cpp @@ -315,7 +315,7 @@ struct SectionData { }; } -template +template std::error_code readCoverageMappingData( SectionData &ProfileNames, StringRef Data, std::vector &Records, @@ -327,10 +327,10 @@ std::error_code readCoverageMappingData( for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { if (Buf + 4 * sizeof(uint32_t) > End) return instrprof_error::malformed; - uint32_t NRecords = endian::readNext(Buf); - uint32_t FilenamesSize = endian::readNext(Buf); - uint32_t CoverageSize = endian::readNext(Buf); - uint32_t Version = endian::readNext(Buf); + uint32_t NRecords = endian::readNext(Buf); + uint32_t FilenamesSize = endian::readNext(Buf); + uint32_t CoverageSize = endian::readNext(Buf); + uint32_t Version = endian::readNext(Buf); switch (Version) { case CoverageMappingVersion1: @@ -362,10 +362,10 @@ std::error_code readCoverageMappingData( while (FunBuf < FunEnd) { // Read the function information - T NamePtr = endian::readNext(FunBuf); - uint32_t NameSize = endian::readNext(FunBuf); - uint32_t DataSize = endian::readNext(FunBuf); - uint64_t FuncHash = endian::readNext(FunBuf); + T NamePtr = endian::readNext(FunBuf); + uint32_t NameSize = endian::readNext(FunBuf); + uint32_t DataSize = endian::readNext(FunBuf); + uint64_t FuncHash = endian::readNext(FunBuf); // Now use that to read the coverage data. if (CovBuf + DataSize > CovEnd) @@ -397,8 +397,10 @@ static const char *TestingFormatMagic = "llvmcovmtestdata"; static std::error_code loadTestingFormat(StringRef Data, SectionData &ProfileNames, StringRef &CoverageMapping, - uint8_t &BytesInAddress) { + uint8_t &BytesInAddress, + support::endianness &Endian) { BytesInAddress = 8; + Endian = support::endianness::little; Data = Data.substr(StringRef(TestingFormatMagic).size()); if (Data.size() < 1) @@ -428,6 +430,7 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, SectionData &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, + support::endianness &Endian, Triple::ArchType Arch) { auto BinOrErr = object::createBinary(ObjectBuffer); if (std::error_code EC = BinOrErr.getError()) @@ -453,6 +456,8 @@ static std::error_code loadBinaryFormat(MemoryBufferRef ObjectBuffer, // The coverage uses native pointer sizes for the object it's written in. BytesInAddress = OF->getBytesInAddress(); + Endian = OF->isLittleEndian() ? support::endianness::little + : support::endianness::big; // Look for the sections that we are interested in. int FoundSectionCount = 0; @@ -489,22 +494,29 @@ BinaryCoverageReader::create(std::unique_ptr &ObjectBuffer, SectionData Profile; StringRef Coverage; uint8_t BytesInAddress; + support::endianness Endian; std::error_code EC; if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) // This is a special format used for testing. EC = loadTestingFormat(ObjectBuffer->getBuffer(), Profile, Coverage, - BytesInAddress); + BytesInAddress, Endian); else EC = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Profile, Coverage, - BytesInAddress, Arch); + BytesInAddress, Endian, Arch); if (EC) return EC; - if (BytesInAddress == 4) - EC = readCoverageMappingData( + if (BytesInAddress == 4 && Endian == support::endianness::little) + EC = readCoverageMappingData( Profile, Coverage, Reader->MappingRecords, Reader->Filenames); - else if (BytesInAddress == 8) - EC = readCoverageMappingData( + else if (BytesInAddress == 4 && Endian == support::endianness::big) + EC = readCoverageMappingData( + Profile, Coverage, Reader->MappingRecords, Reader->Filenames); + else if (BytesInAddress == 8 && Endian == support::endianness::little) + EC = readCoverageMappingData( + Profile, Coverage, Reader->MappingRecords, Reader->Filenames); + else if (BytesInAddress == 8 && Endian == support::endianness::big) + EC = readCoverageMappingData( Profile, Coverage, Reader->MappingRecords, Reader->Filenames); else return instrprof_error::malformed; diff --git a/test/tools/llvm-cov/Inputs/binary-formats.macho32b b/test/tools/llvm-cov/Inputs/binary-formats.macho32b new file mode 100755 index 00000000000..bb9f356c9dc Binary files /dev/null and b/test/tools/llvm-cov/Inputs/binary-formats.macho32b differ diff --git a/test/tools/llvm-cov/binary-formats.c b/test/tools/llvm-cov/binary-formats.c index e03b8b5739e..6ebd089fbe9 100644 --- a/test/tools/llvm-cov/binary-formats.c +++ b/test/tools/llvm-cov/binary-formats.c @@ -6,3 +6,4 @@ int main(int argc, const char *argv[]) {} // RUN: llvm-profdata merge %S/Inputs/binary-formats.proftext -o %t.profdata // RUN: llvm-cov show %S/Inputs/binary-formats.macho32l -instr-profile %t.profdata -no-colors -filename-equivalence %s | FileCheck %s // RUN: llvm-cov show %S/Inputs/binary-formats.macho64l -instr-profile %t.profdata -no-colors -filename-equivalence %s | FileCheck %s +// RUN: llvm-cov show %S/Inputs/binary-formats.macho32b -instr-profile %t.profdata -no-colors -filename-equivalence %s | FileCheck %s