1edd7eaddSDimitry Andric //===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
23ca95b02SDimitry Andric //
33ca95b02SDimitry Andric //                     The LLVM Compiler Infrastructure
43ca95b02SDimitry Andric //
53ca95b02SDimitry Andric // This file is distributed under the University of Illinois Open Source
63ca95b02SDimitry Andric // License. See LICENSE.TXT for details.
73ca95b02SDimitry Andric //
83ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
93ca95b02SDimitry Andric //
103ca95b02SDimitry Andric // This file contains support for reading coverage mapping data for
113ca95b02SDimitry Andric // instrumentation based coverage.
123ca95b02SDimitry Andric //
133ca95b02SDimitry Andric //===----------------------------------------------------------------------===//
143ca95b02SDimitry Andric 
153ca95b02SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
167a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
173ca95b02SDimitry Andric #include "llvm/ADT/DenseMap.h"
187a7e6055SDimitry Andric #include "llvm/ADT/STLExtras.h"
197a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
207a7e6055SDimitry Andric #include "llvm/ADT/StringRef.h"
217a7e6055SDimitry Andric #include "llvm/ADT/Triple.h"
227a7e6055SDimitry Andric #include "llvm/Object/Binary.h"
237a7e6055SDimitry Andric #include "llvm/Object/Error.h"
243ca95b02SDimitry Andric #include "llvm/Object/MachOUniversal.h"
253ca95b02SDimitry Andric #include "llvm/Object/ObjectFile.h"
267a7e6055SDimitry Andric #include "llvm/ProfileData/InstrProf.h"
277a7e6055SDimitry Andric #include "llvm/Support/Casting.h"
283ca95b02SDimitry Andric #include "llvm/Support/Debug.h"
293ca95b02SDimitry Andric #include "llvm/Support/Endian.h"
307a7e6055SDimitry Andric #include "llvm/Support/Error.h"
317a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
323ca95b02SDimitry Andric #include "llvm/Support/LEB128.h"
333ca95b02SDimitry Andric #include "llvm/Support/MathExtras.h"
343ca95b02SDimitry Andric #include "llvm/Support/raw_ostream.h"
357a7e6055SDimitry Andric #include <vector>
363ca95b02SDimitry Andric 
373ca95b02SDimitry Andric using namespace llvm;
383ca95b02SDimitry Andric using namespace coverage;
393ca95b02SDimitry Andric using namespace object;
403ca95b02SDimitry Andric 
413ca95b02SDimitry Andric #define DEBUG_TYPE "coverage-mapping"
423ca95b02SDimitry Andric 
increment()433ca95b02SDimitry Andric void CoverageMappingIterator::increment() {
442cab237bSDimitry Andric   if (ReadErr != coveragemap_error::success)
452cab237bSDimitry Andric     return;
462cab237bSDimitry Andric 
473ca95b02SDimitry Andric   // Check if all the records were read or if an error occurred while reading
483ca95b02SDimitry Andric   // the next record.
492cab237bSDimitry Andric   if (auto E = Reader->readNextRecord(Record))
503ca95b02SDimitry Andric     handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
513ca95b02SDimitry Andric       if (CME.get() == coveragemap_error::eof)
523ca95b02SDimitry Andric         *this = CoverageMappingIterator();
533ca95b02SDimitry Andric       else
542cab237bSDimitry Andric         ReadErr = CME.get();
553ca95b02SDimitry Andric     });
563ca95b02SDimitry Andric }
573ca95b02SDimitry Andric 
readULEB128(uint64_t & Result)583ca95b02SDimitry Andric Error RawCoverageReader::readULEB128(uint64_t &Result) {
59edd7eaddSDimitry Andric   if (Data.empty())
603ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
613ca95b02SDimitry Andric   unsigned N = 0;
623ca95b02SDimitry Andric   Result = decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
633ca95b02SDimitry Andric   if (N > Data.size())
643ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
653ca95b02SDimitry Andric   Data = Data.substr(N);
663ca95b02SDimitry Andric   return Error::success();
673ca95b02SDimitry Andric }
683ca95b02SDimitry Andric 
readIntMax(uint64_t & Result,uint64_t MaxPlus1)693ca95b02SDimitry Andric Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
703ca95b02SDimitry Andric   if (auto Err = readULEB128(Result))
713ca95b02SDimitry Andric     return Err;
723ca95b02SDimitry Andric   if (Result >= MaxPlus1)
733ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
743ca95b02SDimitry Andric   return Error::success();
753ca95b02SDimitry Andric }
763ca95b02SDimitry Andric 
readSize(uint64_t & Result)773ca95b02SDimitry Andric Error RawCoverageReader::readSize(uint64_t &Result) {
783ca95b02SDimitry Andric   if (auto Err = readULEB128(Result))
793ca95b02SDimitry Andric     return Err;
803ca95b02SDimitry Andric   // Sanity check the number.
813ca95b02SDimitry Andric   if (Result > Data.size())
823ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
833ca95b02SDimitry Andric   return Error::success();
843ca95b02SDimitry Andric }
853ca95b02SDimitry Andric 
readString(StringRef & Result)863ca95b02SDimitry Andric Error RawCoverageReader::readString(StringRef &Result) {
873ca95b02SDimitry Andric   uint64_t Length;
883ca95b02SDimitry Andric   if (auto Err = readSize(Length))
893ca95b02SDimitry Andric     return Err;
903ca95b02SDimitry Andric   Result = Data.substr(0, Length);
913ca95b02SDimitry Andric   Data = Data.substr(Length);
923ca95b02SDimitry Andric   return Error::success();
933ca95b02SDimitry Andric }
943ca95b02SDimitry Andric 
read()953ca95b02SDimitry Andric Error RawCoverageFilenamesReader::read() {
963ca95b02SDimitry Andric   uint64_t NumFilenames;
973ca95b02SDimitry Andric   if (auto Err = readSize(NumFilenames))
983ca95b02SDimitry Andric     return Err;
993ca95b02SDimitry Andric   for (size_t I = 0; I < NumFilenames; ++I) {
1003ca95b02SDimitry Andric     StringRef Filename;
1013ca95b02SDimitry Andric     if (auto Err = readString(Filename))
1023ca95b02SDimitry Andric       return Err;
1033ca95b02SDimitry Andric     Filenames.push_back(Filename);
1043ca95b02SDimitry Andric   }
1053ca95b02SDimitry Andric   return Error::success();
1063ca95b02SDimitry Andric }
1073ca95b02SDimitry Andric 
decodeCounter(unsigned Value,Counter & C)1083ca95b02SDimitry Andric Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
1093ca95b02SDimitry Andric   auto Tag = Value & Counter::EncodingTagMask;
1103ca95b02SDimitry Andric   switch (Tag) {
1113ca95b02SDimitry Andric   case Counter::Zero:
1123ca95b02SDimitry Andric     C = Counter::getZero();
1133ca95b02SDimitry Andric     return Error::success();
1143ca95b02SDimitry Andric   case Counter::CounterValueReference:
1153ca95b02SDimitry Andric     C = Counter::getCounter(Value >> Counter::EncodingTagBits);
1163ca95b02SDimitry Andric     return Error::success();
1173ca95b02SDimitry Andric   default:
1183ca95b02SDimitry Andric     break;
1193ca95b02SDimitry Andric   }
1203ca95b02SDimitry Andric   Tag -= Counter::Expression;
1213ca95b02SDimitry Andric   switch (Tag) {
1223ca95b02SDimitry Andric   case CounterExpression::Subtract:
1233ca95b02SDimitry Andric   case CounterExpression::Add: {
1243ca95b02SDimitry Andric     auto ID = Value >> Counter::EncodingTagBits;
1253ca95b02SDimitry Andric     if (ID >= Expressions.size())
1263ca95b02SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed);
1273ca95b02SDimitry Andric     Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
1283ca95b02SDimitry Andric     C = Counter::getExpression(ID);
1293ca95b02SDimitry Andric     break;
1303ca95b02SDimitry Andric   }
1313ca95b02SDimitry Andric   default:
1323ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
1333ca95b02SDimitry Andric   }
1343ca95b02SDimitry Andric   return Error::success();
1353ca95b02SDimitry Andric }
1363ca95b02SDimitry Andric 
readCounter(Counter & C)1373ca95b02SDimitry Andric Error RawCoverageMappingReader::readCounter(Counter &C) {
1383ca95b02SDimitry Andric   uint64_t EncodedCounter;
1393ca95b02SDimitry Andric   if (auto Err =
1403ca95b02SDimitry Andric           readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
1413ca95b02SDimitry Andric     return Err;
1423ca95b02SDimitry Andric   if (auto Err = decodeCounter(EncodedCounter, C))
1433ca95b02SDimitry Andric     return Err;
1443ca95b02SDimitry Andric   return Error::success();
1453ca95b02SDimitry Andric }
1463ca95b02SDimitry Andric 
1473ca95b02SDimitry Andric static const unsigned EncodingExpansionRegionBit = 1
1483ca95b02SDimitry Andric                                                    << Counter::EncodingTagBits;
1493ca95b02SDimitry Andric 
150*4ba319b5SDimitry Andric /// Read the sub-array of regions for the given inferred file id.
1513ca95b02SDimitry Andric /// \param NumFileIDs the number of file ids that are defined for this
1523ca95b02SDimitry Andric /// function.
readMappingRegionsSubArray(std::vector<CounterMappingRegion> & MappingRegions,unsigned InferredFileID,size_t NumFileIDs)1533ca95b02SDimitry Andric Error RawCoverageMappingReader::readMappingRegionsSubArray(
1543ca95b02SDimitry Andric     std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
1553ca95b02SDimitry Andric     size_t NumFileIDs) {
1563ca95b02SDimitry Andric   uint64_t NumRegions;
1573ca95b02SDimitry Andric   if (auto Err = readSize(NumRegions))
1583ca95b02SDimitry Andric     return Err;
1593ca95b02SDimitry Andric   unsigned LineStart = 0;
1603ca95b02SDimitry Andric   for (size_t I = 0; I < NumRegions; ++I) {
1613ca95b02SDimitry Andric     Counter C;
1623ca95b02SDimitry Andric     CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;
1633ca95b02SDimitry Andric 
1643ca95b02SDimitry Andric     // Read the combined counter + region kind.
1653ca95b02SDimitry Andric     uint64_t EncodedCounterAndRegion;
1663ca95b02SDimitry Andric     if (auto Err = readIntMax(EncodedCounterAndRegion,
1673ca95b02SDimitry Andric                               std::numeric_limits<unsigned>::max()))
1683ca95b02SDimitry Andric       return Err;
1693ca95b02SDimitry Andric     unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
1703ca95b02SDimitry Andric     uint64_t ExpandedFileID = 0;
1713ca95b02SDimitry Andric     if (Tag != Counter::Zero) {
1723ca95b02SDimitry Andric       if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
1733ca95b02SDimitry Andric         return Err;
1743ca95b02SDimitry Andric     } else {
1753ca95b02SDimitry Andric       // Is it an expansion region?
1763ca95b02SDimitry Andric       if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
1773ca95b02SDimitry Andric         Kind = CounterMappingRegion::ExpansionRegion;
1783ca95b02SDimitry Andric         ExpandedFileID = EncodedCounterAndRegion >>
1793ca95b02SDimitry Andric                          Counter::EncodingCounterTagAndExpansionRegionTagBits;
1803ca95b02SDimitry Andric         if (ExpandedFileID >= NumFileIDs)
1813ca95b02SDimitry Andric           return make_error<CoverageMapError>(coveragemap_error::malformed);
1823ca95b02SDimitry Andric       } else {
1833ca95b02SDimitry Andric         switch (EncodedCounterAndRegion >>
1843ca95b02SDimitry Andric                 Counter::EncodingCounterTagAndExpansionRegionTagBits) {
1853ca95b02SDimitry Andric         case CounterMappingRegion::CodeRegion:
1863ca95b02SDimitry Andric           // Don't do anything when we have a code region with a zero counter.
1873ca95b02SDimitry Andric           break;
1883ca95b02SDimitry Andric         case CounterMappingRegion::SkippedRegion:
1893ca95b02SDimitry Andric           Kind = CounterMappingRegion::SkippedRegion;
1903ca95b02SDimitry Andric           break;
1913ca95b02SDimitry Andric         default:
1923ca95b02SDimitry Andric           return make_error<CoverageMapError>(coveragemap_error::malformed);
1933ca95b02SDimitry Andric         }
1943ca95b02SDimitry Andric       }
1953ca95b02SDimitry Andric     }
1963ca95b02SDimitry Andric 
1973ca95b02SDimitry Andric     // Read the source range.
1983ca95b02SDimitry Andric     uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
1993ca95b02SDimitry Andric     if (auto Err =
2003ca95b02SDimitry Andric             readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
2013ca95b02SDimitry Andric       return Err;
2023ca95b02SDimitry Andric     if (auto Err = readULEB128(ColumnStart))
2033ca95b02SDimitry Andric       return Err;
2043ca95b02SDimitry Andric     if (ColumnStart > std::numeric_limits<unsigned>::max())
2053ca95b02SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed);
2063ca95b02SDimitry Andric     if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
2073ca95b02SDimitry Andric       return Err;
2083ca95b02SDimitry Andric     if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
2093ca95b02SDimitry Andric       return Err;
2103ca95b02SDimitry Andric     LineStart += LineStartDelta;
2112cab237bSDimitry Andric 
2122cab237bSDimitry Andric     // If the high bit of ColumnEnd is set, this is a gap region.
2132cab237bSDimitry Andric     if (ColumnEnd & (1U << 31)) {
2142cab237bSDimitry Andric       Kind = CounterMappingRegion::GapRegion;
2152cab237bSDimitry Andric       ColumnEnd &= ~(1U << 31);
2162cab237bSDimitry Andric     }
2172cab237bSDimitry Andric 
2183ca95b02SDimitry Andric     // Adjust the column locations for the empty regions that are supposed to
2193ca95b02SDimitry Andric     // cover whole lines. Those regions should be encoded with the
2203ca95b02SDimitry Andric     // column range (1 -> std::numeric_limits<unsigned>::max()), but because
2213ca95b02SDimitry Andric     // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
2223ca95b02SDimitry Andric     // we set the column range to (0 -> 0) to ensure that the column start and
2233ca95b02SDimitry Andric     // column end take up one byte each.
2243ca95b02SDimitry Andric     // The std::numeric_limits<unsigned>::max() is used to represent a column
2253ca95b02SDimitry Andric     // position at the end of the line without knowing the length of that line.
2263ca95b02SDimitry Andric     if (ColumnStart == 0 && ColumnEnd == 0) {
2273ca95b02SDimitry Andric       ColumnStart = 1;
2283ca95b02SDimitry Andric       ColumnEnd = std::numeric_limits<unsigned>::max();
2293ca95b02SDimitry Andric     }
2303ca95b02SDimitry Andric 
231*4ba319b5SDimitry Andric     LLVM_DEBUG({
2323ca95b02SDimitry Andric       dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
2333ca95b02SDimitry Andric              << ColumnStart << " -> " << (LineStart + NumLines) << ":"
2343ca95b02SDimitry Andric              << ColumnEnd << ", ";
2353ca95b02SDimitry Andric       if (Kind == CounterMappingRegion::ExpansionRegion)
2363ca95b02SDimitry Andric         dbgs() << "Expands to file " << ExpandedFileID;
2373ca95b02SDimitry Andric       else
2383ca95b02SDimitry Andric         CounterMappingContext(Expressions).dump(C, dbgs());
2393ca95b02SDimitry Andric       dbgs() << "\n";
2403ca95b02SDimitry Andric     });
2413ca95b02SDimitry Andric 
2422cab237bSDimitry Andric     auto CMR = CounterMappingRegion(C, InferredFileID, ExpandedFileID,
2432cab237bSDimitry Andric                                     LineStart, ColumnStart,
2442cab237bSDimitry Andric                                     LineStart + NumLines, ColumnEnd, Kind);
2452cab237bSDimitry Andric     if (CMR.startLoc() > CMR.endLoc())
2462cab237bSDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed);
2472cab237bSDimitry Andric     MappingRegions.push_back(CMR);
2483ca95b02SDimitry Andric   }
2493ca95b02SDimitry Andric   return Error::success();
2503ca95b02SDimitry Andric }
2513ca95b02SDimitry Andric 
read()2523ca95b02SDimitry Andric Error RawCoverageMappingReader::read() {
2533ca95b02SDimitry Andric   // Read the virtual file mapping.
2547a7e6055SDimitry Andric   SmallVector<unsigned, 8> VirtualFileMapping;
2553ca95b02SDimitry Andric   uint64_t NumFileMappings;
2563ca95b02SDimitry Andric   if (auto Err = readSize(NumFileMappings))
2573ca95b02SDimitry Andric     return Err;
2583ca95b02SDimitry Andric   for (size_t I = 0; I < NumFileMappings; ++I) {
2593ca95b02SDimitry Andric     uint64_t FilenameIndex;
2603ca95b02SDimitry Andric     if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
2613ca95b02SDimitry Andric       return Err;
2623ca95b02SDimitry Andric     VirtualFileMapping.push_back(FilenameIndex);
2633ca95b02SDimitry Andric   }
2643ca95b02SDimitry Andric 
2653ca95b02SDimitry Andric   // Construct the files using unique filenames and virtual file mapping.
2663ca95b02SDimitry Andric   for (auto I : VirtualFileMapping) {
2673ca95b02SDimitry Andric     Filenames.push_back(TranslationUnitFilenames[I]);
2683ca95b02SDimitry Andric   }
2693ca95b02SDimitry Andric 
2703ca95b02SDimitry Andric   // Read the expressions.
2713ca95b02SDimitry Andric   uint64_t NumExpressions;
2723ca95b02SDimitry Andric   if (auto Err = readSize(NumExpressions))
2733ca95b02SDimitry Andric     return Err;
2743ca95b02SDimitry Andric   // Create an array of dummy expressions that get the proper counters
2753ca95b02SDimitry Andric   // when the expressions are read, and the proper kinds when the counters
2763ca95b02SDimitry Andric   // are decoded.
2773ca95b02SDimitry Andric   Expressions.resize(
2783ca95b02SDimitry Andric       NumExpressions,
2793ca95b02SDimitry Andric       CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
2803ca95b02SDimitry Andric   for (size_t I = 0; I < NumExpressions; ++I) {
2813ca95b02SDimitry Andric     if (auto Err = readCounter(Expressions[I].LHS))
2823ca95b02SDimitry Andric       return Err;
2833ca95b02SDimitry Andric     if (auto Err = readCounter(Expressions[I].RHS))
2843ca95b02SDimitry Andric       return Err;
2853ca95b02SDimitry Andric   }
2863ca95b02SDimitry Andric 
2873ca95b02SDimitry Andric   // Read the mapping regions sub-arrays.
2883ca95b02SDimitry Andric   for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
2893ca95b02SDimitry Andric        InferredFileID < S; ++InferredFileID) {
2903ca95b02SDimitry Andric     if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
2913ca95b02SDimitry Andric                                               VirtualFileMapping.size()))
2923ca95b02SDimitry Andric       return Err;
2933ca95b02SDimitry Andric   }
2943ca95b02SDimitry Andric 
2953ca95b02SDimitry Andric   // Set the counters for the expansion regions.
2963ca95b02SDimitry Andric   // i.e. Counter of expansion region = counter of the first region
2973ca95b02SDimitry Andric   // from the expanded file.
2983ca95b02SDimitry Andric   // Perform multiple passes to correctly propagate the counters through
2993ca95b02SDimitry Andric   // all the nested expansion regions.
3003ca95b02SDimitry Andric   SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
3013ca95b02SDimitry Andric   FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
3023ca95b02SDimitry Andric   for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
3033ca95b02SDimitry Andric     for (auto &R : MappingRegions) {
3043ca95b02SDimitry Andric       if (R.Kind != CounterMappingRegion::ExpansionRegion)
3053ca95b02SDimitry Andric         continue;
3063ca95b02SDimitry Andric       assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
3073ca95b02SDimitry Andric       FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
3083ca95b02SDimitry Andric     }
3093ca95b02SDimitry Andric     for (auto &R : MappingRegions) {
3103ca95b02SDimitry Andric       if (FileIDExpansionRegionMapping[R.FileID]) {
3113ca95b02SDimitry Andric         FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
3123ca95b02SDimitry Andric         FileIDExpansionRegionMapping[R.FileID] = nullptr;
3133ca95b02SDimitry Andric       }
3143ca95b02SDimitry Andric     }
3153ca95b02SDimitry Andric   }
3163ca95b02SDimitry Andric 
3173ca95b02SDimitry Andric   return Error::success();
3183ca95b02SDimitry Andric }
3193ca95b02SDimitry Andric 
isDummy()3203ca95b02SDimitry Andric Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
3213ca95b02SDimitry Andric   // A dummy coverage mapping data consists of just one region with zero count.
3223ca95b02SDimitry Andric   uint64_t NumFileMappings;
3233ca95b02SDimitry Andric   if (Error Err = readSize(NumFileMappings))
3243ca95b02SDimitry Andric     return std::move(Err);
3253ca95b02SDimitry Andric   if (NumFileMappings != 1)
3263ca95b02SDimitry Andric     return false;
3273ca95b02SDimitry Andric   // We don't expect any specific value for the filename index, just skip it.
3283ca95b02SDimitry Andric   uint64_t FilenameIndex;
3293ca95b02SDimitry Andric   if (Error Err =
3303ca95b02SDimitry Andric           readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
3313ca95b02SDimitry Andric     return std::move(Err);
3323ca95b02SDimitry Andric   uint64_t NumExpressions;
3333ca95b02SDimitry Andric   if (Error Err = readSize(NumExpressions))
3343ca95b02SDimitry Andric     return std::move(Err);
3353ca95b02SDimitry Andric   if (NumExpressions != 0)
3363ca95b02SDimitry Andric     return false;
3373ca95b02SDimitry Andric   uint64_t NumRegions;
3383ca95b02SDimitry Andric   if (Error Err = readSize(NumRegions))
3393ca95b02SDimitry Andric     return std::move(Err);
3403ca95b02SDimitry Andric   if (NumRegions != 1)
3413ca95b02SDimitry Andric     return false;
3423ca95b02SDimitry Andric   uint64_t EncodedCounterAndRegion;
3433ca95b02SDimitry Andric   if (Error Err = readIntMax(EncodedCounterAndRegion,
3443ca95b02SDimitry Andric                              std::numeric_limits<unsigned>::max()))
3453ca95b02SDimitry Andric     return std::move(Err);
3463ca95b02SDimitry Andric   unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
3473ca95b02SDimitry Andric   return Tag == Counter::Zero;
3483ca95b02SDimitry Andric }
3493ca95b02SDimitry Andric 
create(SectionRef & Section)3503ca95b02SDimitry Andric Error InstrProfSymtab::create(SectionRef &Section) {
3513ca95b02SDimitry Andric   if (auto EC = Section.getContents(Data))
3523ca95b02SDimitry Andric     return errorCodeToError(EC);
3533ca95b02SDimitry Andric   Address = Section.getAddress();
3543ca95b02SDimitry Andric   return Error::success();
3553ca95b02SDimitry Andric }
3563ca95b02SDimitry Andric 
getFuncName(uint64_t Pointer,size_t Size)3573ca95b02SDimitry Andric StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
3583ca95b02SDimitry Andric   if (Pointer < Address)
3593ca95b02SDimitry Andric     return StringRef();
3603ca95b02SDimitry Andric   auto Offset = Pointer - Address;
3613ca95b02SDimitry Andric   if (Offset + Size > Data.size())
3623ca95b02SDimitry Andric     return StringRef();
3633ca95b02SDimitry Andric   return Data.substr(Pointer - Address, Size);
3643ca95b02SDimitry Andric }
3653ca95b02SDimitry Andric 
3663ca95b02SDimitry Andric // Check if the mapping data is a dummy, i.e. is emitted for an unused function.
isCoverageMappingDummy(uint64_t Hash,StringRef Mapping)3673ca95b02SDimitry Andric static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
3683ca95b02SDimitry Andric   // The hash value of dummy mapping records is always zero.
3693ca95b02SDimitry Andric   if (Hash)
3703ca95b02SDimitry Andric     return false;
3713ca95b02SDimitry Andric   return RawCoverageMappingDummyChecker(Mapping).isDummy();
3723ca95b02SDimitry Andric }
3733ca95b02SDimitry Andric 
3743ca95b02SDimitry Andric namespace {
3757a7e6055SDimitry Andric 
3763ca95b02SDimitry Andric struct CovMapFuncRecordReader {
3777a7e6055SDimitry Andric   virtual ~CovMapFuncRecordReader() = default;
3787a7e6055SDimitry Andric 
3793ca95b02SDimitry Andric   // The interface to read coverage mapping function records for a module.
3803ca95b02SDimitry Andric   //
3813ca95b02SDimitry Andric   // \p Buf points to the buffer containing the \c CovHeader of the coverage
3823ca95b02SDimitry Andric   // mapping data associated with the module.
3833ca95b02SDimitry Andric   //
3843ca95b02SDimitry Andric   // Returns a pointer to the next \c CovHeader if it exists, or a pointer
3853ca95b02SDimitry Andric   // greater than \p End if not.
3863ca95b02SDimitry Andric   virtual Expected<const char *> readFunctionRecords(const char *Buf,
3873ca95b02SDimitry Andric                                                      const char *End) = 0;
3887a7e6055SDimitry Andric 
3893ca95b02SDimitry Andric   template <class IntPtrT, support::endianness Endian>
3903ca95b02SDimitry Andric   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
3917a7e6055SDimitry Andric   get(CovMapVersion Version, InstrProfSymtab &P,
3923ca95b02SDimitry Andric       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
3933ca95b02SDimitry Andric       std::vector<StringRef> &F);
3943ca95b02SDimitry Andric };
3953ca95b02SDimitry Andric 
3963ca95b02SDimitry Andric // A class for reading coverage mapping function records for a module.
3977a7e6055SDimitry Andric template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
3983ca95b02SDimitry Andric class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
399edd7eaddSDimitry Andric   using FuncRecordType =
400edd7eaddSDimitry Andric       typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
401edd7eaddSDimitry Andric   using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;
4023ca95b02SDimitry Andric 
4033ca95b02SDimitry Andric   // Maps function's name references to the indexes of their records
4043ca95b02SDimitry Andric   // in \c Records.
4057a7e6055SDimitry Andric   DenseMap<NameRefType, size_t> FunctionRecords;
4063ca95b02SDimitry Andric   InstrProfSymtab &ProfileNames;
4073ca95b02SDimitry Andric   std::vector<StringRef> &Filenames;
4083ca95b02SDimitry Andric   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
4093ca95b02SDimitry Andric 
4103ca95b02SDimitry Andric   // Add the record to the collection if we don't already have a record that
4113ca95b02SDimitry Andric   // points to the same function name. This is useful to ignore the redundant
4123ca95b02SDimitry Andric   // records for the functions with ODR linkage.
4133ca95b02SDimitry Andric   // In addition, prefer records with real coverage mapping data to dummy
4143ca95b02SDimitry Andric   // records, which were emitted for inline functions which were seen but
4153ca95b02SDimitry Andric   // not used in the corresponding translation unit.
insertFunctionRecordIfNeeded(const FuncRecordType * CFR,StringRef Mapping,size_t FilenamesBegin)4163ca95b02SDimitry Andric   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
4173ca95b02SDimitry Andric                                      StringRef Mapping, size_t FilenamesBegin) {
4183ca95b02SDimitry Andric     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
4193ca95b02SDimitry Andric     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
4203ca95b02SDimitry Andric     auto InsertResult =
4213ca95b02SDimitry Andric         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
4223ca95b02SDimitry Andric     if (InsertResult.second) {
4233ca95b02SDimitry Andric       StringRef FuncName;
4243ca95b02SDimitry Andric       if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
4253ca95b02SDimitry Andric         return Err;
426edd7eaddSDimitry Andric       if (FuncName.empty())
427edd7eaddSDimitry Andric         return make_error<InstrProfError>(instrprof_error::malformed);
4283ca95b02SDimitry Andric       Records.emplace_back(Version, FuncName, FuncHash, Mapping, FilenamesBegin,
4293ca95b02SDimitry Andric                            Filenames.size() - FilenamesBegin);
4303ca95b02SDimitry Andric       return Error::success();
4313ca95b02SDimitry Andric     }
4323ca95b02SDimitry Andric     // Update the existing record if it's a dummy and the new record is real.
4333ca95b02SDimitry Andric     size_t OldRecordIndex = InsertResult.first->second;
4343ca95b02SDimitry Andric     BinaryCoverageReader::ProfileMappingRecord &OldRecord =
4353ca95b02SDimitry Andric         Records[OldRecordIndex];
4363ca95b02SDimitry Andric     Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
4373ca95b02SDimitry Andric         OldRecord.FunctionHash, OldRecord.CoverageMapping);
4383ca95b02SDimitry Andric     if (Error Err = OldIsDummyExpected.takeError())
4393ca95b02SDimitry Andric       return Err;
4403ca95b02SDimitry Andric     if (!*OldIsDummyExpected)
4413ca95b02SDimitry Andric       return Error::success();
4423ca95b02SDimitry Andric     Expected<bool> NewIsDummyExpected =
4433ca95b02SDimitry Andric         isCoverageMappingDummy(FuncHash, Mapping);
4443ca95b02SDimitry Andric     if (Error Err = NewIsDummyExpected.takeError())
4453ca95b02SDimitry Andric       return Err;
4463ca95b02SDimitry Andric     if (*NewIsDummyExpected)
4473ca95b02SDimitry Andric       return Error::success();
4483ca95b02SDimitry Andric     OldRecord.FunctionHash = FuncHash;
4493ca95b02SDimitry Andric     OldRecord.CoverageMapping = Mapping;
4503ca95b02SDimitry Andric     OldRecord.FilenamesBegin = FilenamesBegin;
4513ca95b02SDimitry Andric     OldRecord.FilenamesSize = Filenames.size() - FilenamesBegin;
4523ca95b02SDimitry Andric     return Error::success();
4533ca95b02SDimitry Andric   }
4543ca95b02SDimitry Andric 
4553ca95b02SDimitry Andric public:
VersionedCovMapFuncRecordReader(InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,std::vector<StringRef> & F)4563ca95b02SDimitry Andric   VersionedCovMapFuncRecordReader(
4573ca95b02SDimitry Andric       InstrProfSymtab &P,
4583ca95b02SDimitry Andric       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
4593ca95b02SDimitry Andric       std::vector<StringRef> &F)
4603ca95b02SDimitry Andric       : ProfileNames(P), Filenames(F), Records(R) {}
4617a7e6055SDimitry Andric 
4627a7e6055SDimitry Andric   ~VersionedCovMapFuncRecordReader() override = default;
4633ca95b02SDimitry Andric 
readFunctionRecords(const char * Buf,const char * End)4643ca95b02SDimitry Andric   Expected<const char *> readFunctionRecords(const char *Buf,
4653ca95b02SDimitry Andric                                              const char *End) override {
4663ca95b02SDimitry Andric     using namespace support;
4677a7e6055SDimitry Andric 
4683ca95b02SDimitry Andric     if (Buf + sizeof(CovMapHeader) > End)
4693ca95b02SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed);
4707a7e6055SDimitry Andric     auto CovHeader = reinterpret_cast<const CovMapHeader *>(Buf);
4713ca95b02SDimitry Andric     uint32_t NRecords = CovHeader->getNRecords<Endian>();
4723ca95b02SDimitry Andric     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
4733ca95b02SDimitry Andric     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
4743ca95b02SDimitry Andric     assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
4753ca95b02SDimitry Andric     Buf = reinterpret_cast<const char *>(CovHeader + 1);
4763ca95b02SDimitry Andric 
4773ca95b02SDimitry Andric     // Skip past the function records, saving the start and end for later.
4783ca95b02SDimitry Andric     const char *FunBuf = Buf;
4793ca95b02SDimitry Andric     Buf += NRecords * sizeof(FuncRecordType);
4803ca95b02SDimitry Andric     const char *FunEnd = Buf;
4813ca95b02SDimitry Andric 
4823ca95b02SDimitry Andric     // Get the filenames.
4833ca95b02SDimitry Andric     if (Buf + FilenamesSize > End)
4843ca95b02SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed);
4853ca95b02SDimitry Andric     size_t FilenamesBegin = Filenames.size();
4863ca95b02SDimitry Andric     RawCoverageFilenamesReader Reader(StringRef(Buf, FilenamesSize), Filenames);
4873ca95b02SDimitry Andric     if (auto Err = Reader.read())
4883ca95b02SDimitry Andric       return std::move(Err);
4893ca95b02SDimitry Andric     Buf += FilenamesSize;
4903ca95b02SDimitry Andric 
4913ca95b02SDimitry Andric     // We'll read the coverage mapping records in the loop below.
4923ca95b02SDimitry Andric     const char *CovBuf = Buf;
4933ca95b02SDimitry Andric     Buf += CoverageSize;
4943ca95b02SDimitry Andric     const char *CovEnd = Buf;
4953ca95b02SDimitry Andric 
4963ca95b02SDimitry Andric     if (Buf > End)
4973ca95b02SDimitry Andric       return make_error<CoverageMapError>(coveragemap_error::malformed);
4983ca95b02SDimitry Andric     // Each coverage map has an alignment of 8, so we need to adjust alignment
4993ca95b02SDimitry Andric     // before reading the next map.
5003ca95b02SDimitry Andric     Buf += alignmentAdjustment(Buf, 8);
5013ca95b02SDimitry Andric 
5023ca95b02SDimitry Andric     auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf);
5033ca95b02SDimitry Andric     while ((const char *)CFR < FunEnd) {
5043ca95b02SDimitry Andric       // Read the function information
5053ca95b02SDimitry Andric       uint32_t DataSize = CFR->template getDataSize<Endian>();
5063ca95b02SDimitry Andric 
5073ca95b02SDimitry Andric       // Now use that to read the coverage data.
5083ca95b02SDimitry Andric       if (CovBuf + DataSize > CovEnd)
5093ca95b02SDimitry Andric         return make_error<CoverageMapError>(coveragemap_error::malformed);
5103ca95b02SDimitry Andric       auto Mapping = StringRef(CovBuf, DataSize);
5113ca95b02SDimitry Andric       CovBuf += DataSize;
5123ca95b02SDimitry Andric 
5133ca95b02SDimitry Andric       if (Error Err =
5143ca95b02SDimitry Andric               insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin))
5153ca95b02SDimitry Andric         return std::move(Err);
5163ca95b02SDimitry Andric       CFR++;
5173ca95b02SDimitry Andric     }
5183ca95b02SDimitry Andric     return Buf;
5193ca95b02SDimitry Andric   }
5203ca95b02SDimitry Andric };
5217a7e6055SDimitry Andric 
5223ca95b02SDimitry Andric } // end anonymous namespace
5233ca95b02SDimitry Andric 
5243ca95b02SDimitry Andric template <class IntPtrT, support::endianness Endian>
get(CovMapVersion Version,InstrProfSymtab & P,std::vector<BinaryCoverageReader::ProfileMappingRecord> & R,std::vector<StringRef> & F)5253ca95b02SDimitry Andric Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
5267a7e6055SDimitry Andric     CovMapVersion Version, InstrProfSymtab &P,
5273ca95b02SDimitry Andric     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
5283ca95b02SDimitry Andric     std::vector<StringRef> &F) {
5293ca95b02SDimitry Andric   using namespace coverage;
5307a7e6055SDimitry Andric 
5313ca95b02SDimitry Andric   switch (Version) {
5323ca95b02SDimitry Andric   case CovMapVersion::Version1:
5333ca95b02SDimitry Andric     return llvm::make_unique<VersionedCovMapFuncRecordReader<
5343ca95b02SDimitry Andric         CovMapVersion::Version1, IntPtrT, Endian>>(P, R, F);
5353ca95b02SDimitry Andric   case CovMapVersion::Version2:
5362cab237bSDimitry Andric   case CovMapVersion::Version3:
5373ca95b02SDimitry Andric     // Decompress the name data.
5383ca95b02SDimitry Andric     if (Error E = P.create(P.getNameData()))
5393ca95b02SDimitry Andric       return std::move(E);
5402cab237bSDimitry Andric     if (Version == CovMapVersion::Version2)
5413ca95b02SDimitry Andric       return llvm::make_unique<VersionedCovMapFuncRecordReader<
5423ca95b02SDimitry Andric           CovMapVersion::Version2, IntPtrT, Endian>>(P, R, F);
5432cab237bSDimitry Andric     else
5442cab237bSDimitry Andric       return llvm::make_unique<VersionedCovMapFuncRecordReader<
5452cab237bSDimitry Andric           CovMapVersion::Version3, IntPtrT, Endian>>(P, R, F);
5463ca95b02SDimitry Andric   }
5473ca95b02SDimitry Andric   llvm_unreachable("Unsupported version");
5483ca95b02SDimitry Andric }
5493ca95b02SDimitry Andric 
5503ca95b02SDimitry Andric template <typename T, support::endianness Endian>
readCoverageMappingData(InstrProfSymtab & ProfileNames,StringRef Data,std::vector<BinaryCoverageReader::ProfileMappingRecord> & Records,std::vector<StringRef> & Filenames)5513ca95b02SDimitry Andric static Error readCoverageMappingData(
5523ca95b02SDimitry Andric     InstrProfSymtab &ProfileNames, StringRef Data,
5533ca95b02SDimitry Andric     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
5543ca95b02SDimitry Andric     std::vector<StringRef> &Filenames) {
5553ca95b02SDimitry Andric   using namespace coverage;
5567a7e6055SDimitry Andric 
5573ca95b02SDimitry Andric   // Read the records in the coverage data section.
5583ca95b02SDimitry Andric   auto CovHeader =
5597a7e6055SDimitry Andric       reinterpret_cast<const CovMapHeader *>(Data.data());
5603ca95b02SDimitry Andric   CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
5617a7e6055SDimitry Andric   if (Version > CovMapVersion::CurrentVersion)
5623ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
5633ca95b02SDimitry Andric   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
5643ca95b02SDimitry Andric       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
5653ca95b02SDimitry Andric                                              Filenames);
5663ca95b02SDimitry Andric   if (Error E = ReaderExpected.takeError())
5673ca95b02SDimitry Andric     return E;
5683ca95b02SDimitry Andric   auto Reader = std::move(ReaderExpected.get());
5693ca95b02SDimitry Andric   for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) {
5703ca95b02SDimitry Andric     auto NextHeaderOrErr = Reader->readFunctionRecords(Buf, End);
5713ca95b02SDimitry Andric     if (auto E = NextHeaderOrErr.takeError())
5723ca95b02SDimitry Andric       return E;
5733ca95b02SDimitry Andric     Buf = NextHeaderOrErr.get();
5743ca95b02SDimitry Andric   }
5753ca95b02SDimitry Andric   return Error::success();
5763ca95b02SDimitry Andric }
5777a7e6055SDimitry Andric 
5783ca95b02SDimitry Andric static const char *TestingFormatMagic = "llvmcovmtestdata";
5793ca95b02SDimitry Andric 
loadTestingFormat(StringRef Data,InstrProfSymtab & ProfileNames,StringRef & CoverageMapping,uint8_t & BytesInAddress,support::endianness & Endian)5803ca95b02SDimitry Andric static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames,
5813ca95b02SDimitry Andric                                StringRef &CoverageMapping,
5823ca95b02SDimitry Andric                                uint8_t &BytesInAddress,
5833ca95b02SDimitry Andric                                support::endianness &Endian) {
5843ca95b02SDimitry Andric   BytesInAddress = 8;
5853ca95b02SDimitry Andric   Endian = support::endianness::little;
5863ca95b02SDimitry Andric 
5873ca95b02SDimitry Andric   Data = Data.substr(StringRef(TestingFormatMagic).size());
588edd7eaddSDimitry Andric   if (Data.empty())
5893ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
5903ca95b02SDimitry Andric   unsigned N = 0;
5913ca95b02SDimitry Andric   auto ProfileNamesSize =
5923ca95b02SDimitry Andric       decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
5933ca95b02SDimitry Andric   if (N > Data.size())
5943ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
5953ca95b02SDimitry Andric   Data = Data.substr(N);
596edd7eaddSDimitry Andric   if (Data.empty())
5973ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
5983ca95b02SDimitry Andric   N = 0;
5993ca95b02SDimitry Andric   uint64_t Address =
6003ca95b02SDimitry Andric       decodeULEB128(reinterpret_cast<const uint8_t *>(Data.data()), &N);
6013ca95b02SDimitry Andric   if (N > Data.size())
6023ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
6033ca95b02SDimitry Andric   Data = Data.substr(N);
6043ca95b02SDimitry Andric   if (Data.size() < ProfileNamesSize)
6053ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
6063ca95b02SDimitry Andric   if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
6073ca95b02SDimitry Andric     return E;
6083ca95b02SDimitry Andric   CoverageMapping = Data.substr(ProfileNamesSize);
6093ca95b02SDimitry Andric   // Skip the padding bytes because coverage map data has an alignment of 8.
610edd7eaddSDimitry Andric   if (CoverageMapping.empty())
6113ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::truncated);
6123ca95b02SDimitry Andric   size_t Pad = alignmentAdjustment(CoverageMapping.data(), 8);
6133ca95b02SDimitry Andric   if (CoverageMapping.size() < Pad)
6143ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
6153ca95b02SDimitry Andric   CoverageMapping = CoverageMapping.substr(Pad);
6163ca95b02SDimitry Andric   return Error::success();
6173ca95b02SDimitry Andric }
6183ca95b02SDimitry Andric 
lookupSection(ObjectFile & OF,StringRef Name)6193ca95b02SDimitry Andric static Expected<SectionRef> lookupSection(ObjectFile &OF, StringRef Name) {
6203ca95b02SDimitry Andric   StringRef FoundName;
6213ca95b02SDimitry Andric   for (const auto &Section : OF.sections()) {
6223ca95b02SDimitry Andric     if (auto EC = Section.getName(FoundName))
6233ca95b02SDimitry Andric       return errorCodeToError(EC);
6243ca95b02SDimitry Andric     if (FoundName == Name)
6253ca95b02SDimitry Andric       return Section;
6263ca95b02SDimitry Andric   }
6273ca95b02SDimitry Andric   return make_error<CoverageMapError>(coveragemap_error::no_data_found);
6283ca95b02SDimitry Andric }
6293ca95b02SDimitry Andric 
loadBinaryFormat(MemoryBufferRef ObjectBuffer,InstrProfSymtab & ProfileNames,StringRef & CoverageMapping,uint8_t & BytesInAddress,support::endianness & Endian,StringRef Arch)6303ca95b02SDimitry Andric static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer,
6313ca95b02SDimitry Andric                               InstrProfSymtab &ProfileNames,
6323ca95b02SDimitry Andric                               StringRef &CoverageMapping,
6333ca95b02SDimitry Andric                               uint8_t &BytesInAddress,
6343ca95b02SDimitry Andric                               support::endianness &Endian, StringRef Arch) {
6357a7e6055SDimitry Andric   auto BinOrErr = createBinary(ObjectBuffer);
6363ca95b02SDimitry Andric   if (!BinOrErr)
6373ca95b02SDimitry Andric     return BinOrErr.takeError();
6383ca95b02SDimitry Andric   auto Bin = std::move(BinOrErr.get());
6393ca95b02SDimitry Andric   std::unique_ptr<ObjectFile> OF;
6407a7e6055SDimitry Andric   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
6413ca95b02SDimitry Andric     // If we have a universal binary, try to look up the object for the
6423ca95b02SDimitry Andric     // appropriate architecture.
6433ca95b02SDimitry Andric     auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
6443ca95b02SDimitry Andric     if (!ObjectFileOrErr)
6453ca95b02SDimitry Andric       return ObjectFileOrErr.takeError();
6463ca95b02SDimitry Andric     OF = std::move(ObjectFileOrErr.get());
6477a7e6055SDimitry Andric   } else if (isa<ObjectFile>(Bin.get())) {
6483ca95b02SDimitry Andric     // For any other object file, upcast and take ownership.
6497a7e6055SDimitry Andric     OF.reset(cast<ObjectFile>(Bin.release()));
6503ca95b02SDimitry Andric     // If we've asked for a particular arch, make sure they match.
6513ca95b02SDimitry Andric     if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
6523ca95b02SDimitry Andric       return errorCodeToError(object_error::arch_not_found);
6533ca95b02SDimitry Andric   } else
6543ca95b02SDimitry Andric     // We can only handle object files.
6553ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
6563ca95b02SDimitry Andric 
6573ca95b02SDimitry Andric   // The coverage uses native pointer sizes for the object it's written in.
6583ca95b02SDimitry Andric   BytesInAddress = OF->getBytesInAddress();
6593ca95b02SDimitry Andric   Endian = OF->isLittleEndian() ? support::endianness::little
6603ca95b02SDimitry Andric                                 : support::endianness::big;
6613ca95b02SDimitry Andric 
6623ca95b02SDimitry Andric   // Look for the sections that we are interested in.
6637a7e6055SDimitry Andric   auto ObjFormat = OF->getTripleObjectFormat();
6647a7e6055SDimitry Andric   auto NamesSection =
6657a7e6055SDimitry Andric       lookupSection(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
6667a7e6055SDimitry Andric                                                  /*AddSegmentInfo=*/false));
6673ca95b02SDimitry Andric   if (auto E = NamesSection.takeError())
6683ca95b02SDimitry Andric     return E;
6693ca95b02SDimitry Andric   auto CoverageSection =
6707a7e6055SDimitry Andric       lookupSection(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
6717a7e6055SDimitry Andric                                                  /*AddSegmentInfo=*/false));
6723ca95b02SDimitry Andric   if (auto E = CoverageSection.takeError())
6733ca95b02SDimitry Andric     return E;
6743ca95b02SDimitry Andric 
6753ca95b02SDimitry Andric   // Get the contents of the given sections.
6763ca95b02SDimitry Andric   if (auto EC = CoverageSection->getContents(CoverageMapping))
6773ca95b02SDimitry Andric     return errorCodeToError(EC);
6783ca95b02SDimitry Andric   if (Error E = ProfileNames.create(*NamesSection))
6793ca95b02SDimitry Andric     return E;
6803ca95b02SDimitry Andric 
6813ca95b02SDimitry Andric   return Error::success();
6823ca95b02SDimitry Andric }
6833ca95b02SDimitry Andric 
6843ca95b02SDimitry Andric Expected<std::unique_ptr<BinaryCoverageReader>>
create(std::unique_ptr<MemoryBuffer> & ObjectBuffer,StringRef Arch)6853ca95b02SDimitry Andric BinaryCoverageReader::create(std::unique_ptr<MemoryBuffer> &ObjectBuffer,
6863ca95b02SDimitry Andric                              StringRef Arch) {
6873ca95b02SDimitry Andric   std::unique_ptr<BinaryCoverageReader> Reader(new BinaryCoverageReader());
6883ca95b02SDimitry Andric 
6893ca95b02SDimitry Andric   StringRef Coverage;
6903ca95b02SDimitry Andric   uint8_t BytesInAddress;
6913ca95b02SDimitry Andric   support::endianness Endian;
692d88c1a5aSDimitry Andric   Error E = Error::success();
6933ca95b02SDimitry Andric   consumeError(std::move(E));
6943ca95b02SDimitry Andric   if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
6953ca95b02SDimitry Andric     // This is a special format used for testing.
6963ca95b02SDimitry Andric     E = loadTestingFormat(ObjectBuffer->getBuffer(), Reader->ProfileNames,
6973ca95b02SDimitry Andric                           Coverage, BytesInAddress, Endian);
6983ca95b02SDimitry Andric   else
6993ca95b02SDimitry Andric     E = loadBinaryFormat(ObjectBuffer->getMemBufferRef(), Reader->ProfileNames,
7003ca95b02SDimitry Andric                          Coverage, BytesInAddress, Endian, Arch);
7013ca95b02SDimitry Andric   if (E)
7023ca95b02SDimitry Andric     return std::move(E);
7033ca95b02SDimitry Andric 
7043ca95b02SDimitry Andric   if (BytesInAddress == 4 && Endian == support::endianness::little)
7053ca95b02SDimitry Andric     E = readCoverageMappingData<uint32_t, support::endianness::little>(
7063ca95b02SDimitry Andric         Reader->ProfileNames, Coverage, Reader->MappingRecords,
7073ca95b02SDimitry Andric         Reader->Filenames);
7083ca95b02SDimitry Andric   else if (BytesInAddress == 4 && Endian == support::endianness::big)
7093ca95b02SDimitry Andric     E = readCoverageMappingData<uint32_t, support::endianness::big>(
7103ca95b02SDimitry Andric         Reader->ProfileNames, Coverage, Reader->MappingRecords,
7113ca95b02SDimitry Andric         Reader->Filenames);
7123ca95b02SDimitry Andric   else if (BytesInAddress == 8 && Endian == support::endianness::little)
7133ca95b02SDimitry Andric     E = readCoverageMappingData<uint64_t, support::endianness::little>(
7143ca95b02SDimitry Andric         Reader->ProfileNames, Coverage, Reader->MappingRecords,
7153ca95b02SDimitry Andric         Reader->Filenames);
7163ca95b02SDimitry Andric   else if (BytesInAddress == 8 && Endian == support::endianness::big)
7173ca95b02SDimitry Andric     E = readCoverageMappingData<uint64_t, support::endianness::big>(
7183ca95b02SDimitry Andric         Reader->ProfileNames, Coverage, Reader->MappingRecords,
7193ca95b02SDimitry Andric         Reader->Filenames);
7203ca95b02SDimitry Andric   else
7213ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::malformed);
7223ca95b02SDimitry Andric   if (E)
7233ca95b02SDimitry Andric     return std::move(E);
7243ca95b02SDimitry Andric   return std::move(Reader);
7253ca95b02SDimitry Andric }
7263ca95b02SDimitry Andric 
readNextRecord(CoverageMappingRecord & Record)7273ca95b02SDimitry Andric Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
7283ca95b02SDimitry Andric   if (CurrentRecord >= MappingRecords.size())
7293ca95b02SDimitry Andric     return make_error<CoverageMapError>(coveragemap_error::eof);
7303ca95b02SDimitry Andric 
7313ca95b02SDimitry Andric   FunctionsFilenames.clear();
7323ca95b02SDimitry Andric   Expressions.clear();
7333ca95b02SDimitry Andric   MappingRegions.clear();
7343ca95b02SDimitry Andric   auto &R = MappingRecords[CurrentRecord];
7353ca95b02SDimitry Andric   RawCoverageMappingReader Reader(
7363ca95b02SDimitry Andric       R.CoverageMapping,
7373ca95b02SDimitry Andric       makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
7383ca95b02SDimitry Andric       FunctionsFilenames, Expressions, MappingRegions);
7393ca95b02SDimitry Andric   if (auto Err = Reader.read())
7403ca95b02SDimitry Andric     return Err;
7413ca95b02SDimitry Andric 
7423ca95b02SDimitry Andric   Record.FunctionName = R.FunctionName;
7433ca95b02SDimitry Andric   Record.FunctionHash = R.FunctionHash;
7443ca95b02SDimitry Andric   Record.Filenames = FunctionsFilenames;
7453ca95b02SDimitry Andric   Record.Expressions = Expressions;
7463ca95b02SDimitry Andric   Record.MappingRegions = MappingRegions;
7473ca95b02SDimitry Andric 
7483ca95b02SDimitry Andric   ++CurrentRecord;
7493ca95b02SDimitry Andric   return Error::success();
7503ca95b02SDimitry Andric }
751