diff options
Diffstat (limited to 'llvm/lib/ProfileData/CoverageMappingReader.cpp')
-rw-r--r-- | llvm/lib/ProfileData/CoverageMappingReader.cpp | 100 |
1 files changed, 41 insertions, 59 deletions
diff --git a/llvm/lib/ProfileData/CoverageMappingReader.cpp b/llvm/lib/ProfileData/CoverageMappingReader.cpp index 3f8f76f6094..fde6874fe40 100644 --- a/llvm/lib/ProfileData/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/CoverageMappingReader.cpp @@ -17,6 +17,7 @@ #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/LEB128.h" using namespace llvm; @@ -288,24 +289,6 @@ std::error_code RawCoverageMappingReader::read() { } namespace { -/// \brief The coverage mapping data for a single function. -/// It points to the function's name. -template <typename IntPtrT> struct CoverageMappingFunctionRecord { - IntPtrT FunctionNamePtr; - uint32_t FunctionNameSize; - uint32_t CoverageMappingSize; - uint64_t FunctionHash; -}; - -/// \brief The coverage mapping data for a single translation unit. -/// It points to the array of function coverage mapping records and the encoded -/// filenames array. -template <typename IntPtrT> struct CoverageMappingTURecord { - uint32_t FunctionRecordsSize; - uint32_t FilenamesSize; - uint32_t CoverageMappingsSize; - uint32_t Version; -}; /// \brief A helper structure to access the data from a section /// in an object file. @@ -337,72 +320,71 @@ std::error_code readCoverageMappingData( SectionData &ProfileNames, StringRef Data, std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records, std::vector<StringRef> &Filenames) { + using namespace support; llvm::DenseSet<T> UniqueFunctionMappingData; // Read the records in the coverage data section. - while (!Data.empty()) { - if (Data.size() < sizeof(CoverageMappingTURecord<T>)) + for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { + if (Buf + 4 * sizeof(uint32_t) > End) return instrprof_error::malformed; - auto TU = reinterpret_cast<const CoverageMappingTURecord<T> *>(Data.data()); - Data = Data.substr(sizeof(CoverageMappingTURecord<T>)); - switch (TU->Version) { + uint32_t NRecords = endian::readNext<uint32_t, little, unaligned>(Buf); + uint32_t FilenamesSize = endian::readNext<uint32_t, little, unaligned>(Buf); + uint32_t CoverageSize = endian::readNext<uint32_t, little, unaligned>(Buf); + uint32_t Version = endian::readNext<uint32_t, little, unaligned>(Buf); + + switch (Version) { case CoverageMappingVersion1: break; default: return instrprof_error::unsupported_version; } - auto Version = CoverageMappingVersion(TU->Version); - // Get the function records. - auto FunctionRecords = - reinterpret_cast<const CoverageMappingFunctionRecord<T> *>(Data.data()); - if (Data.size() < - sizeof(CoverageMappingFunctionRecord<T>) * TU->FunctionRecordsSize) - return instrprof_error::malformed; - Data = Data.substr(sizeof(CoverageMappingFunctionRecord<T>) * - TU->FunctionRecordsSize); + // Skip past the function records, saving the start and end for later. + const char *FunBuf = Buf; + Buf += NRecords * (sizeof(T) + 2 * sizeof(uint32_t) + sizeof(uint64_t)); + const char *FunEnd = Buf; // Get the filenames. - if (Data.size() < TU->FilenamesSize) + if (Buf + FilenamesSize > End) return instrprof_error::malformed; - auto RawFilenames = Data.substr(0, TU->FilenamesSize); - Data = Data.substr(TU->FilenamesSize); size_t FilenamesBegin = Filenames.size(); - RawCoverageFilenamesReader Reader(RawFilenames, Filenames); + RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames); if (auto Err = Reader.read()) return Err; + Buf += FilenamesSize; - // Get the coverage mappings. - if (Data.size() < TU->CoverageMappingsSize) + // We'll read the coverage mapping records in the loop below. + const char *CovBuf = Buf; + Buf += CoverageSize; + const char *CovEnd = Buf; + if (Buf > End) return instrprof_error::malformed; - auto CoverageMappings = Data.substr(0, TU->CoverageMappingsSize); - Data = Data.substr(TU->CoverageMappingsSize); - for (unsigned I = 0; I < TU->FunctionRecordsSize; ++I) { - auto &MappingRecord = FunctionRecords[I]; + while (FunBuf < FunEnd) { + // Read the function information + T NamePtr = endian::readNext<T, little, unaligned>(FunBuf); + uint32_t NameSize = endian::readNext<uint32_t, little, unaligned>(FunBuf); + uint32_t DataSize = endian::readNext<uint32_t, little, unaligned>(FunBuf); + uint64_t FuncHash = endian::readNext<uint64_t, little, unaligned>(FunBuf); - // Get the coverage mapping. - if (CoverageMappings.size() < MappingRecord.CoverageMappingSize) + // Now use that to read the coverage data. + if (CovBuf + DataSize > CovEnd) return instrprof_error::malformed; - auto Mapping = - CoverageMappings.substr(0, MappingRecord.CoverageMappingSize); - CoverageMappings = - CoverageMappings.substr(MappingRecord.CoverageMappingSize); + auto Mapping = StringRef(CovBuf, DataSize); + CovBuf += DataSize; // Ignore this record if we already have a record that points to the same - // function name. - // This is useful to ignore the redundant records for the functions - // with ODR linkage. - if (!UniqueFunctionMappingData.insert(MappingRecord.FunctionNamePtr) - .second) + // function name. This is useful to ignore the redundant records for the + // functions with ODR linkage. + if (!UniqueFunctionMappingData.insert(NamePtr).second) continue; - StringRef FunctionName; - if (auto Err = - ProfileNames.get(MappingRecord.FunctionNamePtr, - MappingRecord.FunctionNameSize, FunctionName)) - return Err; + + // Finally, grab the name and create a record. + StringRef FuncName; + if (std::error_code EC = ProfileNames.get(NamePtr, NameSize, FuncName)) + return EC; Records.push_back(BinaryCoverageReader::ProfileMappingRecord( - Version, FunctionName, MappingRecord.FunctionHash, Mapping, + CoverageMappingVersion(Version), FuncName, FuncHash, Mapping, FilenamesBegin, Filenames.size() - FilenamesBegin)); } } |