brintos

brintos / llvm-project-archived public Read only

0
0
Text · 55.1 KiB · 8ce0e9f Raw
1384 lines · cpp
1//===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains support for reading coverage mapping data for10// instrumentation based coverage.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/DenseMap.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/ADT/Statistic.h"19#include "llvm/ADT/StringRef.h"20#include "llvm/BinaryFormat/Wasm.h"21#include "llvm/Object/Archive.h"22#include "llvm/Object/Binary.h"23#include "llvm/Object/COFF.h"24#include "llvm/Object/Error.h"25#include "llvm/Object/MachOUniversal.h"26#include "llvm/Object/ObjectFile.h"27#include "llvm/Object/Wasm.h"28#include "llvm/ProfileData/InstrProf.h"29#include "llvm/Support/Casting.h"30#include "llvm/Support/Compression.h"31#include "llvm/Support/Debug.h"32#include "llvm/Support/Endian.h"33#include "llvm/Support/Error.h"34#include "llvm/Support/ErrorHandling.h"35#include "llvm/Support/LEB128.h"36#include "llvm/Support/Path.h"37#include "llvm/Support/raw_ostream.h"38#include "llvm/TargetParser/Triple.h"39#include <vector>40 41using namespace llvm;42using namespace coverage;43using namespace object;44 45#define DEBUG_TYPE "coverage-mapping"46 47STATISTIC(CovMapNumRecords, "The # of coverage function records");48STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");49 50void CoverageMappingIterator::increment() {51  if (ReadErr != coveragemap_error::success)52    return;53 54  // Check if all the records were read or if an error occurred while reading55  // the next record.56  if (auto E = Reader->readNextRecord(Record))57    handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {58      if (CME.get() == coveragemap_error::eof)59        *this = CoverageMappingIterator();60      else61        ReadErr = CME.get();62    });63}64 65Error RawCoverageReader::readULEB128(uint64_t &Result) {66  if (Data.empty())67    return make_error<CoverageMapError>(coveragemap_error::truncated);68  unsigned N = 0;69  Result = decodeULEB128(Data.bytes_begin(), &N);70  if (N > Data.size())71    return make_error<CoverageMapError>(coveragemap_error::malformed,72                                        "the size of ULEB128 is too big");73  Data = Data.substr(N);74  return Error::success();75}76 77Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {78  if (auto Err = readULEB128(Result))79    return Err;80  if (Result >= MaxPlus1)81    return make_error<CoverageMapError>(82        coveragemap_error::malformed,83        "the value of ULEB128 is greater than or equal to MaxPlus1");84  return Error::success();85}86 87Error RawCoverageReader::readSize(uint64_t &Result) {88  if (auto Err = readULEB128(Result))89    return Err;90  if (Result > Data.size())91    return make_error<CoverageMapError>(coveragemap_error::malformed,92                                        "the value of ULEB128 is too big");93  return Error::success();94}95 96Error RawCoverageReader::readString(StringRef &Result) {97  uint64_t Length;98  if (auto Err = readSize(Length))99    return Err;100  Result = Data.substr(0, Length);101  Data = Data.substr(Length);102  return Error::success();103}104 105Error RawCoverageFilenamesReader::read(CovMapVersion Version) {106  uint64_t NumFilenames;107  if (auto Err = readSize(NumFilenames))108    return Err;109  if (!NumFilenames)110    return make_error<CoverageMapError>(coveragemap_error::malformed,111                                        "number of filenames is zero");112 113  if (Version < CovMapVersion::Version4)114    return readUncompressed(Version, NumFilenames);115 116  // The uncompressed length may exceed the size of the encoded filenames.117  // Skip size validation.118  uint64_t UncompressedLen;119  if (auto Err = readULEB128(UncompressedLen))120    return Err;121 122  uint64_t CompressedLen;123  if (auto Err = readSize(CompressedLen))124    return Err;125 126  if (CompressedLen > 0) {127    if (!compression::zlib::isAvailable())128      return make_error<CoverageMapError>(129          coveragemap_error::decompression_failed);130 131    // Allocate memory for the decompressed filenames.132    SmallVector<uint8_t, 0> StorageBuf;133 134    // Read compressed filenames.135    StringRef CompressedFilenames = Data.substr(0, CompressedLen);136    Data = Data.substr(CompressedLen);137    auto Err = compression::zlib::decompress(138        arrayRefFromStringRef(CompressedFilenames), StorageBuf,139        UncompressedLen);140    if (Err) {141      consumeError(std::move(Err));142      return make_error<CoverageMapError>(143          coveragemap_error::decompression_failed);144    }145 146    RawCoverageFilenamesReader Delegate(toStringRef(StorageBuf), Filenames,147                                        CompilationDir);148    return Delegate.readUncompressed(Version, NumFilenames);149  }150 151  return readUncompressed(Version, NumFilenames);152}153 154Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,155                                                   uint64_t NumFilenames) {156  // Read uncompressed filenames.157  if (Version < CovMapVersion::Version6) {158    for (size_t I = 0; I < NumFilenames; ++I) {159      StringRef Filename;160      if (auto Err = readString(Filename))161        return Err;162      Filenames.push_back(Filename.str());163    }164  } else {165    StringRef CWD;166    if (auto Err = readString(CWD))167      return Err;168    Filenames.push_back(CWD.str());169 170    for (size_t I = 1; I < NumFilenames; ++I) {171      StringRef Filename;172      if (auto Err = readString(Filename))173        return Err;174      if (sys::path::is_absolute(Filename)) {175        Filenames.push_back(Filename.str());176      } else {177        SmallString<256> P;178        if (!CompilationDir.empty())179          P.assign(CompilationDir);180        else181          P.assign(CWD);182        llvm::sys::path::append(P, Filename);183        sys::path::remove_dots(P, /*remove_dot_dot=*/true);184        Filenames.push_back(static_cast<std::string>(P.str()));185      }186    }187  }188  return Error::success();189}190 191Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {192  auto Tag = Value & Counter::EncodingTagMask;193  switch (Tag) {194  case Counter::Zero:195    C = Counter::getZero();196    return Error::success();197  case Counter::CounterValueReference:198    C = Counter::getCounter(Value >> Counter::EncodingTagBits);199    return Error::success();200  default:201    break;202  }203  Tag -= Counter::Expression;204  switch (Tag) {205  case CounterExpression::Subtract:206  case CounterExpression::Add: {207    auto ID = Value >> Counter::EncodingTagBits;208    if (ID >= Expressions.size())209      return make_error<CoverageMapError>(coveragemap_error::malformed,210                                          "counter expression is invalid");211    Expressions[ID].Kind = CounterExpression::ExprKind(Tag);212    C = Counter::getExpression(ID);213    break;214  }215  default:216    return make_error<CoverageMapError>(coveragemap_error::malformed,217                                        "counter expression kind is invalid");218  }219  return Error::success();220}221 222Error RawCoverageMappingReader::readCounter(Counter &C) {223  uint64_t EncodedCounter;224  if (auto Err =225          readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))226    return Err;227  if (auto Err = decodeCounter(EncodedCounter, C))228    return Err;229  return Error::success();230}231 232static const unsigned EncodingExpansionRegionBit = 1233                                                   << Counter::EncodingTagBits;234 235/// Read the sub-array of regions for the given inferred file id.236/// \param NumFileIDs the number of file ids that are defined for this237/// function.238Error RawCoverageMappingReader::readMappingRegionsSubArray(239    std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,240    size_t NumFileIDs) {241  uint64_t NumRegions;242  if (auto Err = readSize(NumRegions))243    return Err;244  unsigned LineStart = 0;245  for (size_t I = 0; I < NumRegions; ++I) {246    Counter C, C2;247    uint64_t BIDX, NC;248    // They are stored as internal values plus 1 (min is -1)249    uint64_t ID1, TID1, FID1;250    mcdc::Parameters Params;251    CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;252 253    // Read the combined counter + region kind.254    uint64_t EncodedCounterAndRegion;255    if (auto Err = readIntMax(EncodedCounterAndRegion,256                              std::numeric_limits<unsigned>::max()))257      return Err;258    unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;259    uint64_t ExpandedFileID = 0;260 261    // If Tag does not represent a ZeroCounter, then it is understood to refer262    // to a counter or counter expression with region kind assumed to be263    // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the264    // referenced counter or counter expression (and nothing else).265    //266    // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,267    // then EncodedCounterAndRegion is interpreted to represent an268    // ExpansionRegion. In all other cases, EncodedCounterAndRegion is269    // interpreted to refer to a specific region kind, after which additional270    // fields may be read (e.g. BranchRegions have two encoded counters that271    // follow an encoded region kind value).272    if (Tag != Counter::Zero) {273      if (auto Err = decodeCounter(EncodedCounterAndRegion, C))274        return Err;275    } else {276      // Is it an expansion region?277      if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {278        Kind = CounterMappingRegion::ExpansionRegion;279        ExpandedFileID = EncodedCounterAndRegion >>280                         Counter::EncodingCounterTagAndExpansionRegionTagBits;281        if (ExpandedFileID >= NumFileIDs)282          return make_error<CoverageMapError>(coveragemap_error::malformed,283                                              "ExpandedFileID is invalid");284      } else {285        switch (EncodedCounterAndRegion >>286                Counter::EncodingCounterTagAndExpansionRegionTagBits) {287        case CounterMappingRegion::CodeRegion:288          // Don't do anything when we have a code region with a zero counter.289          break;290        case CounterMappingRegion::SkippedRegion:291          Kind = CounterMappingRegion::SkippedRegion;292          break;293        case CounterMappingRegion::BranchRegion:294          // For a Branch Region, read two successive counters.295          Kind = CounterMappingRegion::BranchRegion;296          if (auto Err = readCounter(C))297            return Err;298          if (auto Err = readCounter(C2))299            return Err;300          break;301        case CounterMappingRegion::MCDCBranchRegion:302          // For a MCDC Branch Region, read two successive counters and 3 IDs.303          Kind = CounterMappingRegion::MCDCBranchRegion;304          if (auto Err = readCounter(C))305            return Err;306          if (auto Err = readCounter(C2))307            return Err;308          if (auto Err = readIntMax(ID1, std::numeric_limits<int16_t>::max()))309            return Err;310          if (auto Err = readIntMax(TID1, std::numeric_limits<int16_t>::max()))311            return Err;312          if (auto Err = readIntMax(FID1, std::numeric_limits<int16_t>::max()))313            return Err;314          if (ID1 == 0)315            return make_error<CoverageMapError>(316                coveragemap_error::malformed,317                "MCDCConditionID shouldn't be zero");318          Params = mcdc::BranchParameters{319              static_cast<int16_t>(static_cast<int16_t>(ID1) - 1),320              {static_cast<int16_t>(static_cast<int16_t>(FID1) - 1),321               static_cast<int16_t>(static_cast<int16_t>(TID1) - 1)}};322          break;323        case CounterMappingRegion::MCDCDecisionRegion:324          Kind = CounterMappingRegion::MCDCDecisionRegion;325          if (auto Err = readIntMax(BIDX, std::numeric_limits<unsigned>::max()))326            return Err;327          if (auto Err = readIntMax(NC, std::numeric_limits<int16_t>::max()))328            return Err;329          Params = mcdc::DecisionParameters{static_cast<unsigned>(BIDX),330                                            static_cast<uint16_t>(NC)};331          break;332        default:333          return make_error<CoverageMapError>(coveragemap_error::malformed,334                                              "region kind is incorrect");335        }336      }337    }338 339    // Read the source range.340    uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;341    if (auto Err =342            readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))343      return Err;344    if (auto Err = readULEB128(ColumnStart))345      return Err;346    if (ColumnStart > std::numeric_limits<unsigned>::max())347      return make_error<CoverageMapError>(coveragemap_error::malformed,348                                          "start column is too big");349    if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))350      return Err;351    if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))352      return Err;353    LineStart += LineStartDelta;354 355    // If the high bit of ColumnEnd is set, this is a gap region.356    if (ColumnEnd & (1U << 31)) {357      Kind = CounterMappingRegion::GapRegion;358      ColumnEnd &= ~(1U << 31);359    }360 361    // Adjust the column locations for the empty regions that are supposed to362    // cover whole lines. Those regions should be encoded with the363    // column range (1 -> std::numeric_limits<unsigned>::max()), but because364    // the encoded std::numeric_limits<unsigned>::max() is several bytes long,365    // we set the column range to (0 -> 0) to ensure that the column start and366    // column end take up one byte each.367    // The std::numeric_limits<unsigned>::max() is used to represent a column368    // position at the end of the line without knowing the length of that line.369    if (ColumnStart == 0 && ColumnEnd == 0) {370      ColumnStart = 1;371      ColumnEnd = std::numeric_limits<unsigned>::max();372    }373 374    LLVM_DEBUG({375      dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"376             << ColumnStart << " -> " << (LineStart + NumLines) << ":"377             << ColumnEnd << ", ";378      if (Kind == CounterMappingRegion::ExpansionRegion)379        dbgs() << "Expands to file " << ExpandedFileID;380      else381        CounterMappingContext(Expressions).dump(C, dbgs());382      dbgs() << "\n";383    });384 385    auto CMR = CounterMappingRegion(386        C, C2, InferredFileID, ExpandedFileID, LineStart, ColumnStart,387        LineStart + NumLines, ColumnEnd, Kind, Params);388    if (CMR.startLoc() > CMR.endLoc())389      return make_error<CoverageMapError>(390          coveragemap_error::malformed,391          "counter mapping region locations are incorrect");392    MappingRegions.push_back(CMR);393  }394  return Error::success();395}396 397Error RawCoverageMappingReader::read() {398  // Read the virtual file mapping.399  SmallVector<unsigned, 8> VirtualFileMapping;400  uint64_t NumFileMappings;401  if (auto Err = readSize(NumFileMappings))402    return Err;403  for (size_t I = 0; I < NumFileMappings; ++I) {404    uint64_t FilenameIndex;405    if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))406      return Err;407    VirtualFileMapping.push_back(FilenameIndex);408  }409 410  // Construct the files using unique filenames and virtual file mapping.411  for (auto I : VirtualFileMapping) {412    Filenames.push_back(TranslationUnitFilenames[I]);413  }414 415  // Read the expressions.416  uint64_t NumExpressions;417  if (auto Err = readSize(NumExpressions))418    return Err;419  // Create an array of dummy expressions that get the proper counters420  // when the expressions are read, and the proper kinds when the counters421  // are decoded.422  Expressions.resize(423      NumExpressions,424      CounterExpression(CounterExpression::Subtract, Counter(), Counter()));425  for (size_t I = 0; I < NumExpressions; ++I) {426    if (auto Err = readCounter(Expressions[I].LHS))427      return Err;428    if (auto Err = readCounter(Expressions[I].RHS))429      return Err;430  }431 432  // Read the mapping regions sub-arrays.433  for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();434       InferredFileID < S; ++InferredFileID) {435    if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,436                                              VirtualFileMapping.size()))437      return Err;438  }439 440  // Set the counters for the expansion regions.441  // i.e. Counter of expansion region = counter of the first region442  // from the expanded file.443  // Perform multiple passes to correctly propagate the counters through444  // all the nested expansion regions.445  SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;446  FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);447  for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {448    for (auto &R : MappingRegions) {449      if (R.Kind != CounterMappingRegion::ExpansionRegion)450        continue;451      assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);452      FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;453    }454    for (auto &R : MappingRegions) {455      if (FileIDExpansionRegionMapping[R.FileID]) {456        FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;457        FileIDExpansionRegionMapping[R.FileID] = nullptr;458      }459    }460  }461 462  return Error::success();463}464 465Expected<bool> RawCoverageMappingDummyChecker::isDummy() {466  // A dummy coverage mapping data consists of just one region with zero count.467  uint64_t NumFileMappings;468  if (Error Err = readSize(NumFileMappings))469    return std::move(Err);470  if (NumFileMappings != 1)471    return false;472  // We don't expect any specific value for the filename index, just skip it.473  uint64_t FilenameIndex;474  if (Error Err =475          readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))476    return std::move(Err);477  uint64_t NumExpressions;478  if (Error Err = readSize(NumExpressions))479    return std::move(Err);480  if (NumExpressions != 0)481    return false;482  uint64_t NumRegions;483  if (Error Err = readSize(NumRegions))484    return std::move(Err);485  if (NumRegions != 1)486    return false;487  uint64_t EncodedCounterAndRegion;488  if (Error Err = readIntMax(EncodedCounterAndRegion,489                             std::numeric_limits<unsigned>::max()))490    return std::move(Err);491  unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;492  return Tag == Counter::Zero;493}494 495/// Determine if we should skip the first byte of the section content496static bool shouldSkipSectionFirstByte(SectionRef &Section) {497  const ObjectFile *Obj = Section.getObject();498  // If this is a linked PE/COFF file, then we have to skip over the null byte499  // that is allocated in the .lprfn$A section in the LLVM profiling runtime.500  // If the name section is .lprfcovnames, it doesn't have the null byte at the501  // beginning.502  if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())503    if (Expected<StringRef> NameOrErr = Section.getName())504      if (*NameOrErr != getInstrProfSectionName(IPSK_covname, Triple::COFF))505        return true;506  return false;507}508 509Error InstrProfSymtab::create(SectionRef &Section) {510  Expected<StringRef> DataOrErr = Section.getContents();511  if (!DataOrErr)512    return DataOrErr.takeError();513  Data = *DataOrErr;514  Address = Section.getAddress();515 516  if (shouldSkipSectionFirstByte(Section))517    Data = Data.substr(1);518 519  return Error::success();520}521 522StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) const {523  if (Pointer < Address)524    return StringRef();525  auto Offset = Pointer - Address;526  if (Offset + Size > Data.size())527    return StringRef();528  return Data.substr(Pointer - Address, Size);529}530 531// Check if the mapping data is a dummy, i.e. is emitted for an unused function.532static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {533  // The hash value of dummy mapping records is always zero.534  if (Hash)535    return false;536  return RawCoverageMappingDummyChecker(Mapping).isDummy();537}538 539/// A range of filename indices. Used to specify the location of a batch of540/// filenames in a vector-like container.541struct FilenameRange {542  unsigned StartingIndex;543  unsigned Length;544 545  FilenameRange(unsigned StartingIndex, unsigned Length)546      : StartingIndex(StartingIndex), Length(Length) {}547 548  void markInvalid() { Length = 0; }549  bool isInvalid() const { return Length == 0; }550};551 552namespace {553 554/// The interface to read coverage mapping function records for a module.555struct CovMapFuncRecordReader {556  virtual ~CovMapFuncRecordReader() = default;557 558  // Read a coverage header.559  //560  // \p CovBuf points to the buffer containing the \c CovHeader of the coverage561  // mapping data associated with the module.562  //563  // Returns a pointer to the next \c CovHeader if it exists, or to an address564  // greater than \p CovEnd if not.565  virtual Expected<const char *> readCoverageHeader(const char *CovBuf,566                                                    const char *CovBufEnd) = 0;567 568  // Read function records.569  //570  // \p FuncRecBuf points to the buffer containing a batch of function records.571  // \p FuncRecBufEnd points past the end of the batch of records.572  //573  // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames574  // associated with the function records. It is unused in Version4.575  //576  // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage577  // mappings associated with the function records. It is unused in Version4.578  virtual Error579  readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,580                      std::optional<FilenameRange> OutOfLineFileRange,581                      const char *OutOfLineMappingBuf,582                      const char *OutOfLineMappingBufEnd) = 0;583 584  template <class IntPtrT, llvm::endianness Endian>585  static Expected<std::unique_ptr<CovMapFuncRecordReader>>586  get(CovMapVersion Version, InstrProfSymtab &P,587      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,588      std::vector<std::string> &F);589};590 591// A class for reading coverage mapping function records for a module.592template <CovMapVersion Version, class IntPtrT, llvm::endianness Endian>593class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {594  using FuncRecordType =595      typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;596  using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;597 598  // Maps function's name references to the indexes of their records599  // in \c Records.600  DenseMap<NameRefType, size_t> FunctionRecords;601  InstrProfSymtab &ProfileNames;602  StringRef CompilationDir;603  std::vector<std::string> &Filenames;604  std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;605 606  // Maps a hash of the filenames in a TU to a \c FileRange. The range607  // specifies the location of the hashed filenames in \c Filenames.608  DenseMap<uint64_t, FilenameRange> FileRangeMap;609 610  // Add the record to the collection if we don't already have a record that611  // points to the same function name. This is useful to ignore the redundant612  // records for the functions with ODR linkage.613  // In addition, prefer records with real coverage mapping data to dummy614  // records, which were emitted for inline functions which were seen but615  // not used in the corresponding translation unit.616  Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,617                                     StringRef Mapping,618                                     FilenameRange FileRange) {619    ++CovMapNumRecords;620    uint64_t FuncHash = CFR->template getFuncHash<Endian>();621    NameRefType NameRef = CFR->template getFuncNameRef<Endian>();622    auto InsertResult =623        FunctionRecords.insert(std::make_pair(NameRef, Records.size()));624    if (InsertResult.second) {625      StringRef FuncName;626      if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))627        return Err;628      if (FuncName.empty())629        return make_error<InstrProfError>(instrprof_error::malformed,630                                          "function name is empty");631      ++CovMapNumUsedRecords;632      Records.emplace_back(Version, FuncName, FuncHash, Mapping,633                           FileRange.StartingIndex, FileRange.Length);634      return Error::success();635    }636    // Update the existing record if it's a dummy and the new record is real.637    size_t OldRecordIndex = InsertResult.first->second;638    BinaryCoverageReader::ProfileMappingRecord &OldRecord =639        Records[OldRecordIndex];640    Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(641        OldRecord.FunctionHash, OldRecord.CoverageMapping);642    if (Error Err = OldIsDummyExpected.takeError())643      return Err;644    if (!*OldIsDummyExpected)645      return Error::success();646    Expected<bool> NewIsDummyExpected =647        isCoverageMappingDummy(FuncHash, Mapping);648    if (Error Err = NewIsDummyExpected.takeError())649      return Err;650    if (*NewIsDummyExpected)651      return Error::success();652    ++CovMapNumUsedRecords;653    OldRecord.FunctionHash = FuncHash;654    OldRecord.CoverageMapping = Mapping;655    OldRecord.FilenamesBegin = FileRange.StartingIndex;656    OldRecord.FilenamesSize = FileRange.Length;657    return Error::success();658  }659 660public:661  VersionedCovMapFuncRecordReader(662      InstrProfSymtab &P,663      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,664      std::vector<std::string> &F)665      : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}666 667  ~VersionedCovMapFuncRecordReader() override = default;668 669  Expected<const char *> readCoverageHeader(const char *CovBuf,670                                            const char *CovBufEnd) override {671    using namespace support;672 673    if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)674      return make_error<CoverageMapError>(675          coveragemap_error::malformed,676          "coverage mapping header section is larger than buffer size");677    auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);678    uint32_t NRecords = CovHeader->getNRecords<Endian>();679    uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();680    uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();681    assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);682    CovBuf = reinterpret_cast<const char *>(CovHeader + 1);683 684    // Skip past the function records, saving the start and end for later.685    // This is a no-op in Version4 (function records are read after all headers686    // are read).687    const char *FuncRecBuf = nullptr;688    const char *FuncRecBufEnd = nullptr;689    if (Version < CovMapVersion::Version4)690      FuncRecBuf = CovBuf;691    CovBuf += NRecords * sizeof(FuncRecordType);692    if (Version < CovMapVersion::Version4)693      FuncRecBufEnd = CovBuf;694 695    // Get the filenames.696    if (CovBuf + FilenamesSize > CovBufEnd)697      return make_error<CoverageMapError>(698          coveragemap_error::malformed,699          "filenames section is larger than buffer size");700    size_t FilenamesBegin = Filenames.size();701    StringRef FilenameRegion(CovBuf, FilenamesSize);702    RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,703                                      CompilationDir);704    if (auto Err = Reader.read(Version))705      return std::move(Err);706    CovBuf += FilenamesSize;707    FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);708 709    if (Version >= CovMapVersion::Version4) {710      // Map a hash of the filenames region to the filename range associated711      // with this coverage header.712      int64_t FilenamesRef =713          llvm::IndexedInstrProf::ComputeHash(FilenameRegion);714      auto Insert =715          FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));716      if (!Insert.second) {717        // The same filenames ref was encountered twice. It's possible that718        // the associated filenames are the same.719        auto It = Filenames.begin();720        FilenameRange &OrigRange = Insert.first->getSecond();721        if (std::equal(It + OrigRange.StartingIndex,722                       It + OrigRange.StartingIndex + OrigRange.Length,723                       It + FileRange.StartingIndex,724                       It + FileRange.StartingIndex + FileRange.Length))725          // Map the new range to the original one.726          FileRange = OrigRange;727        else728          // This is a hash collision. Mark the filenames ref invalid.729          OrigRange.markInvalid();730      }731    }732 733    // We'll read the coverage mapping records in the loop below.734    // This is a no-op in Version4 (coverage mappings are not affixed to the735    // coverage header).736    const char *MappingBuf = CovBuf;737    if (Version >= CovMapVersion::Version4 && CoverageSize != 0)738      return make_error<CoverageMapError>(coveragemap_error::malformed,739                                          "coverage mapping size is not zero");740    CovBuf += CoverageSize;741    const char *MappingEnd = CovBuf;742 743    if (CovBuf > CovBufEnd)744      return make_error<CoverageMapError>(745          coveragemap_error::malformed,746          "function records section is larger than buffer size");747 748    if (Version < CovMapVersion::Version4) {749      // Read each function record.750      if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,751                                        MappingBuf, MappingEnd))752        return std::move(E);753    }754 755    // Each coverage map has an alignment of 8, so we need to adjust alignment756    // before reading the next map.757    CovBuf += offsetToAlignedAddr(CovBuf, Align(8));758 759    return CovBuf;760  }761 762  Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,763                            std::optional<FilenameRange> OutOfLineFileRange,764                            const char *OutOfLineMappingBuf,765                            const char *OutOfLineMappingBufEnd) override {766    auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);767    while ((const char *)CFR < FuncRecBufEnd) {768      // Validate the length of the coverage mapping for this function.769      const char *NextMappingBuf;770      const FuncRecordType *NextCFR;771      std::tie(NextMappingBuf, NextCFR) =772          CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);773      if (Version < CovMapVersion::Version4)774        if (NextMappingBuf > OutOfLineMappingBufEnd)775          return make_error<CoverageMapError>(776              coveragemap_error::malformed,777              "next mapping buffer is larger than buffer size");778 779      // Look up the set of filenames associated with this function record.780      std::optional<FilenameRange> FileRange;781      if (Version < CovMapVersion::Version4) {782        FileRange = OutOfLineFileRange;783      } else {784        uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();785        auto It = FileRangeMap.find(FilenamesRef);786        if (It == FileRangeMap.end())787          return make_error<CoverageMapError>(788              coveragemap_error::malformed,789              "no filename found for function with hash=0x" +790                  Twine::utohexstr(FilenamesRef));791        else792          FileRange = It->getSecond();793      }794 795      // Now, read the coverage data.796      if (FileRange && !FileRange->isInvalid()) {797        StringRef Mapping =798            CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);799        if (Version >= CovMapVersion::Version4 &&800            Mapping.data() + Mapping.size() > FuncRecBufEnd)801          return make_error<CoverageMapError>(802              coveragemap_error::malformed,803              "coverage mapping data is larger than buffer size");804        if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))805          return Err;806      }807 808      std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);809    }810    return Error::success();811  }812};813 814} // end anonymous namespace815 816template <class IntPtrT, llvm::endianness Endian>817Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(818    CovMapVersion Version, InstrProfSymtab &P,819    std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,820    std::vector<std::string> &F) {821  using namespace coverage;822 823  switch (Version) {824  case CovMapVersion::Version1:825    return std::make_unique<VersionedCovMapFuncRecordReader<826        CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);827  case CovMapVersion::Version2:828  case CovMapVersion::Version3:829  case CovMapVersion::Version4:830  case CovMapVersion::Version5:831  case CovMapVersion::Version6:832  case CovMapVersion::Version7:833    // Decompress the name data.834    if (Error E = P.create(P.getNameData()))835      return std::move(E);836    if (Version == CovMapVersion::Version2)837      return std::make_unique<VersionedCovMapFuncRecordReader<838          CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);839    else if (Version == CovMapVersion::Version3)840      return std::make_unique<VersionedCovMapFuncRecordReader<841          CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);842    else if (Version == CovMapVersion::Version4)843      return std::make_unique<VersionedCovMapFuncRecordReader<844          CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);845    else if (Version == CovMapVersion::Version5)846      return std::make_unique<VersionedCovMapFuncRecordReader<847          CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);848    else if (Version == CovMapVersion::Version6)849      return std::make_unique<VersionedCovMapFuncRecordReader<850          CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);851    else if (Version == CovMapVersion::Version7)852      return std::make_unique<VersionedCovMapFuncRecordReader<853          CovMapVersion::Version7, IntPtrT, Endian>>(P, R, D, F);854  }855  llvm_unreachable("Unsupported version");856}857 858template <typename T, llvm::endianness Endian>859static Error readCoverageMappingData(860    InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,861    std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,862    StringRef CompilationDir, std::vector<std::string> &Filenames) {863  using namespace coverage;864 865  // Read the records in the coverage data section.866  auto CovHeader =867      reinterpret_cast<const CovMapHeader *>(CovMap.data());868  CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();869  if (Version > CovMapVersion::CurrentVersion)870    return make_error<CoverageMapError>(coveragemap_error::unsupported_version);871  Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =872      CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,873                                             CompilationDir, Filenames);874  if (Error E = ReaderExpected.takeError())875    return E;876  auto Reader = std::move(ReaderExpected.get());877  const char *CovBuf = CovMap.data();878  const char *CovBufEnd = CovBuf + CovMap.size();879  const char *FuncRecBuf = FuncRecords.data();880  const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();881  while (CovBuf < CovBufEnd) {882    // Read the current coverage header & filename data.883    //884    // Prior to Version4, this also reads all function records affixed to the885    // header.886    //887    // Return a pointer to the next coverage header.888    auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);889    if (auto E = NextOrErr.takeError())890      return E;891    CovBuf = NextOrErr.get();892  }893  // In Version4, function records are not affixed to coverage headers. Read894  // the records from their dedicated section.895  if (Version >= CovMapVersion::Version4)896    return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,897                                       nullptr, nullptr);898  return Error::success();899}900 901Expected<std::unique_ptr<BinaryCoverageReader>>902BinaryCoverageReader::createCoverageReaderFromBuffer(903    StringRef Coverage, FuncRecordsStorage &&FuncRecords,904    CoverageMapCopyStorage &&CoverageMap,905    std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,906    llvm::endianness Endian, StringRef CompilationDir) {907  if (ProfileNamesPtr == nullptr)908    return make_error<CoverageMapError>(coveragemap_error::malformed,909                                        "Caller must provide ProfileNames");910  std::unique_ptr<BinaryCoverageReader> Reader(911      new BinaryCoverageReader(std::move(ProfileNamesPtr),912                               std::move(FuncRecords), std::move(CoverageMap)));913  InstrProfSymtab &ProfileNames = *Reader->ProfileNames;914  StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();915  if (BytesInAddress == 4 && Endian == llvm::endianness::little) {916    if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>(917            ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,918            CompilationDir, Reader->Filenames))919      return std::move(E);920  } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) {921    if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>(922            ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,923            CompilationDir, Reader->Filenames))924      return std::move(E);925  } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) {926    if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>(927            ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,928            CompilationDir, Reader->Filenames))929      return std::move(E);930  } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) {931    if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>(932            ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,933            CompilationDir, Reader->Filenames))934      return std::move(E);935  } else936    return make_error<CoverageMapError>(937        coveragemap_error::malformed,938        "not supported endianness or bytes in address");939  return std::move(Reader);940}941 942static Expected<std::unique_ptr<BinaryCoverageReader>>943loadTestingFormat(StringRef Data, StringRef CompilationDir) {944  uint8_t BytesInAddress = 8;945  llvm::endianness Endian = llvm::endianness::little;946 947  // Read the magic and version.948  Data = Data.substr(sizeof(TestingFormatMagic));949  if (Data.size() < sizeof(uint64_t))950    return make_error<CoverageMapError>(coveragemap_error::malformed,951                                        "the size of data is too small");952  auto TestingVersion = support::endian::byte_swap<uint64_t>(953      *reinterpret_cast<const uint64_t *>(Data.data()),954      llvm::endianness::little);955  Data = Data.substr(sizeof(uint64_t));956 957  // Read the ProfileNames data.958  if (Data.empty())959    return make_error<CoverageMapError>(coveragemap_error::truncated);960  unsigned N = 0;961  uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);962  if (N > Data.size())963    return make_error<CoverageMapError>(964        coveragemap_error::malformed,965        "the size of TestingFormatMagic is too big");966  Data = Data.substr(N);967  if (Data.empty())968    return make_error<CoverageMapError>(coveragemap_error::truncated);969  N = 0;970  uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);971  if (N > Data.size())972    return make_error<CoverageMapError>(coveragemap_error::malformed,973                                        "the size of ULEB128 is too big");974  Data = Data.substr(N);975  if (Data.size() < ProfileNamesSize)976    return make_error<CoverageMapError>(coveragemap_error::malformed,977                                        "the size of ProfileNames is too big");978  auto ProfileNames = std::make_unique<InstrProfSymtab>();979  if (Error E = ProfileNames->create(Data.substr(0, ProfileNamesSize), Address))980    return std::move(E);981  Data = Data.substr(ProfileNamesSize);982 983  // In Version2, the size of CoverageMapping is stored directly.984  uint64_t CoverageMappingSize;985  if (TestingVersion == uint64_t(TestingFormatVersion::Version2)) {986    N = 0;987    CoverageMappingSize = decodeULEB128(Data.bytes_begin(), &N);988    if (N > Data.size())989      return make_error<CoverageMapError>(coveragemap_error::malformed,990                                          "the size of ULEB128 is too big");991    Data = Data.substr(N);992    if (CoverageMappingSize < sizeof(CovMapHeader))993      return make_error<CoverageMapError>(994          coveragemap_error::malformed,995          "the size of CoverageMapping is teoo small");996  } else if (TestingVersion != uint64_t(TestingFormatVersion::Version1)) {997    return make_error<CoverageMapError>(coveragemap_error::unsupported_version);998  }999 1000  // Skip the padding bytes because coverage map data has an alignment of 8.1001  auto Pad = offsetToAlignedAddr(Data.data(), Align(8));1002  if (Data.size() < Pad)1003    return make_error<CoverageMapError>(coveragemap_error::malformed,1004                                        "insufficient padding");1005  Data = Data.substr(Pad);1006  if (Data.size() < sizeof(CovMapHeader))1007    return make_error<CoverageMapError>(1008        coveragemap_error::malformed,1009        "coverage mapping header section is larger than data size");1010  auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(1011      Data.substr(0, sizeof(CovMapHeader)).data());1012  auto Version =1013      CovMapVersion(CovHeader->getVersion<llvm::endianness::little>());1014 1015  // In Version1, the size of CoverageMapping is calculated.1016  if (TestingVersion == uint64_t(TestingFormatVersion::Version1)) {1017    if (Version < CovMapVersion::Version4) {1018      CoverageMappingSize = Data.size();1019    } else {1020      auto FilenamesSize =1021          CovHeader->getFilenamesSize<llvm::endianness::little>();1022      CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;1023    }1024  }1025 1026  auto CoverageMapping = Data.substr(0, CoverageMappingSize);1027  Data = Data.substr(CoverageMappingSize);1028 1029  // Read the CoverageRecords data.1030  if (Version < CovMapVersion::Version4) {1031    if (!Data.empty())1032      return make_error<CoverageMapError>(coveragemap_error::malformed,1033                                          "data is not empty");1034  } else {1035    // Skip the padding bytes because coverage records data has an alignment1036    // of 8.1037    Pad = offsetToAlignedAddr(Data.data(), Align(8));1038    if (Data.size() < Pad)1039      return make_error<CoverageMapError>(coveragemap_error::malformed,1040                                          "insufficient padding");1041    Data = Data.substr(Pad);1042  }1043  BinaryCoverageReader::FuncRecordsStorage CoverageRecords =1044      MemoryBuffer::getMemBuffer(Data);1045 1046  return BinaryCoverageReader::createCoverageReaderFromBuffer(1047      CoverageMapping, std::move(CoverageRecords), nullptr,1048      std::move(ProfileNames), BytesInAddress, Endian, CompilationDir);1049}1050 1051/// Find all sections that match \p IPSK name. There may be more than one if1052/// comdats are in use, e.g. for the __llvm_covfun section on ELF.1053static Expected<std::vector<SectionRef>>1054lookupSections(ObjectFile &OF, InstrProfSectKind IPSK) {1055  auto ObjFormat = OF.getTripleObjectFormat();1056  auto Name =1057      getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false);1058  // On COFF, the object file section name may end in "$M". This tells the1059  // linker to sort these sections between "$A" and "$Z". The linker removes the1060  // dollar and everything after it in the final binary. Do the same to match.1061  bool IsCOFF = isa<COFFObjectFile>(OF);1062  auto stripSuffix = [IsCOFF](StringRef N) {1063    return IsCOFF ? N.split('$').first : N;1064  };1065  Name = stripSuffix(Name);1066 1067  std::vector<SectionRef> Sections;1068  for (const auto &Section : OF.sections()) {1069    Expected<StringRef> NameOrErr = Section.getName();1070    if (!NameOrErr)1071      return NameOrErr.takeError();1072    if (stripSuffix(*NameOrErr) == Name) {1073      // Skip empty profile name section.1074      // COFF profile name section contains two null bytes indicating the1075      // start/end of the section. If its size is 2 bytes, it's empty.1076      if (IPSK == IPSK_name &&1077          (Section.getSize() == 0 || (IsCOFF && Section.getSize() == 2)))1078        continue;1079      Sections.push_back(Section);1080    }1081  }1082  if (Sections.empty())1083    return make_error<CoverageMapError>(coveragemap_error::no_data_found);1084  return Sections;1085}1086 1087/// Find a section that matches \p Name and is allocatable at runtime.1088///1089/// Returns the contents of the section and its start offset in the object file.1090static Expected<std::pair<StringRef, uint64_t>>1091lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK) {1092  // On Wasm, allocatable sections can live only in data segments.1093  if (auto *WOF = dyn_cast<WasmObjectFile>(&OF)) {1094    std::vector<const WasmSegment *> Segments;1095    auto ObjFormat = OF.getTripleObjectFormat();1096    auto Name =1097        getInstrProfSectionName(IPSK, ObjFormat, /*AddSegmentInfo=*/false);1098    for (const auto &DebugName : WOF->debugNames()) {1099      if (DebugName.Type != wasm::NameType::DATA_SEGMENT ||1100          DebugName.Name != Name)1101        continue;1102      if (DebugName.Index >= WOF->dataSegments().size())1103        return make_error<CoverageMapError>(coveragemap_error::malformed);1104      auto &Segment = WOF->dataSegments()[DebugName.Index];1105      Segments.push_back(&Segment);1106    }1107    if (Segments.empty())1108      return make_error<CoverageMapError>(coveragemap_error::no_data_found);1109    if (Segments.size() != 1)1110      return make_error<CoverageMapError>(coveragemap_error::malformed);1111 1112    const auto &Segment = *Segments.front();1113    auto &Data = Segment.Data;1114    StringRef Content(reinterpret_cast<const char *>(Data.Content.data()),1115                      Data.Content.size());1116    return std::make_pair(Content, Segment.SectionOffset);1117  }1118 1119  // On other object file types, delegate to lookupSections to find the section.1120  auto Sections = lookupSections(OF, IPSK);1121  if (!Sections)1122    return Sections.takeError();1123  if (Sections->size() != 1)1124    return make_error<CoverageMapError>(1125        coveragemap_error::malformed,1126        "the size of coverage mapping section is not one");1127  auto &Section = Sections->front();1128  auto ContentsOrErr = Section.getContents();1129  if (!ContentsOrErr)1130    return ContentsOrErr.takeError();1131  auto Content = *ContentsOrErr;1132  if (shouldSkipSectionFirstByte(Section))1133    Content = Content.drop_front(1);1134  return std::make_pair(Content, Section.getAddress());1135}1136 1137static Expected<std::unique_ptr<BinaryCoverageReader>>1138loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,1139                 StringRef CompilationDir = "",1140                 object::BuildIDRef *BinaryID = nullptr) {1141  std::unique_ptr<ObjectFile> OF;1142  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {1143    // If we have a universal binary, try to look up the object for the1144    // appropriate architecture.1145    auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);1146    if (!ObjectFileOrErr)1147      return ObjectFileOrErr.takeError();1148    OF = std::move(ObjectFileOrErr.get());1149  } else if (isa<ObjectFile>(Bin.get())) {1150    // For any other object file, upcast and take ownership.1151    OF.reset(cast<ObjectFile>(Bin.release()));1152    // If we've asked for a particular arch, make sure they match.1153    if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())1154      return errorCodeToError(object_error::arch_not_found);1155  } else1156    // We can only handle object files.1157    return make_error<CoverageMapError>(coveragemap_error::malformed,1158                                        "binary is not an object file");1159 1160  // The coverage uses native pointer sizes for the object it's written in.1161  uint8_t BytesInAddress = OF->getBytesInAddress();1162  llvm::endianness Endian =1163      OF->isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;1164 1165  // Look for the sections that we are interested in.1166  auto ProfileNames = std::make_unique<InstrProfSymtab>();1167  // If IPSK_name is not found, fallback to search for IPK_covname, which is1168  // used when binary correlation is enabled.1169  auto NamesSection = lookupAllocatableSection(*OF, IPSK_name);1170  if (auto E = NamesSection.takeError()) {1171    consumeError(std::move(E));1172    NamesSection = lookupAllocatableSection(*OF, IPSK_covname);1173    if (auto E = NamesSection.takeError())1174      return std::move(E);1175  }1176 1177  uint64_t NamesAddress;1178  StringRef NamesContent;1179  std::tie(NamesContent, NamesAddress) = *NamesSection;1180  if (Error E = ProfileNames->create(NamesContent, NamesAddress))1181    return std::move(E);1182 1183  auto CoverageSection = lookupSections(*OF, IPSK_covmap);1184  if (auto E = CoverageSection.takeError())1185    return std::move(E);1186  std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;1187  if (CoverageSectionRefs.size() != 1)1188    return make_error<CoverageMapError>(coveragemap_error::malformed,1189                                        "the size of name section is not one");1190  auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();1191  if (!CoverageMappingOrErr)1192    return CoverageMappingOrErr.takeError();1193  StringRef CoverageMapping = CoverageMappingOrErr.get();1194 1195  // If the coverage mapping section is not aligned to 8 bytes, copy it to a1196  // new buffer that is. Wasm format typically has unaligned section contents1197  // because it doesn't have a good way to insert padding bytes.1198  std::unique_ptr<MemoryBuffer> CoverageMapCopy;1199  if (!isAddrAligned(Align(8), CoverageMapping.data())) {1200    CoverageMapCopy = MemoryBuffer::getMemBufferCopy(CoverageMapping);1201    CoverageMapping = CoverageMapCopy->getBuffer();1202  }1203 1204  // Look for the coverage records section (Version4 only).1205  auto CoverageRecordsSections = lookupSections(*OF, IPSK_covfun);1206 1207  BinaryCoverageReader::FuncRecordsStorage FuncRecords;1208  if (auto E = CoverageRecordsSections.takeError()) {1209    consumeError(std::move(E));1210    FuncRecords = MemoryBuffer::getMemBuffer("");1211  } else {1212    // Compute the FuncRecordsBuffer of the buffer, taking into account the1213    // padding between each record, and making sure the first block is aligned1214    // in memory to maintain consistency between buffer address and size1215    // alignment.1216    const Align RecordAlignment(8);1217    uint64_t FuncRecordsSize = 0;1218    for (SectionRef Section : *CoverageRecordsSections) {1219      auto CoverageRecordsOrErr = Section.getContents();1220      if (!CoverageRecordsOrErr)1221        return CoverageRecordsOrErr.takeError();1222      FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);1223    }1224    auto WritableBuffer =1225        WritableMemoryBuffer::getNewUninitMemBuffer(FuncRecordsSize);1226    char *FuncRecordsBuffer = WritableBuffer->getBufferStart();1227    assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) &&1228           "Allocated memory is correctly aligned");1229 1230    for (SectionRef Section : *CoverageRecordsSections) {1231      auto CoverageRecordsOrErr = Section.getContents();1232      if (!CoverageRecordsOrErr)1233        return CoverageRecordsOrErr.takeError();1234      const auto &CoverageRecords = CoverageRecordsOrErr.get();1235      FuncRecordsBuffer = llvm::copy(CoverageRecords, FuncRecordsBuffer);1236      FuncRecordsBuffer =1237          std::fill_n(FuncRecordsBuffer,1238                      alignAddr(FuncRecordsBuffer, RecordAlignment) -1239                          (uintptr_t)FuncRecordsBuffer,1240                      '\0');1241    }1242    assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&1243           "consistent init");1244    FuncRecords = std::move(WritableBuffer);1245  }1246 1247  if (BinaryID)1248    *BinaryID = getBuildID(OF.get());1249 1250  return BinaryCoverageReader::createCoverageReaderFromBuffer(1251      CoverageMapping, std::move(FuncRecords), std::move(CoverageMapCopy),1252      std::move(ProfileNames), BytesInAddress, Endian, CompilationDir);1253}1254 1255/// Determine whether \p Arch is invalid or empty, given \p Bin.1256static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {1257  // If we have a universal binary and Arch doesn't identify any of its slices,1258  // it's user error.1259  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {1260    for (auto &ObjForArch : Universal->objects())1261      if (Arch == ObjForArch.getArchFlagName())1262        return false;1263    return true;1264  }1265  return false;1266}1267 1268Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>1269BinaryCoverageReader::create(1270    MemoryBufferRef ObjectBuffer, StringRef Arch,1271    SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,1272    StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {1273  std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;1274 1275  if (ObjectBuffer.getBuffer().size() > sizeof(TestingFormatMagic)) {1276    uint64_t Magic = support::endian::byte_swap<uint64_t>(1277        *reinterpret_cast<const uint64_t *>(ObjectBuffer.getBufferStart()),1278        llvm::endianness::little);1279    if (Magic == TestingFormatMagic) {1280      // This is a special format used for testing.1281      auto ReaderOrErr =1282          loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);1283      if (!ReaderOrErr)1284        return ReaderOrErr.takeError();1285      Readers.push_back(std::move(ReaderOrErr.get()));1286      return std::move(Readers);1287    }1288  }1289 1290  auto BinOrErr = createBinary(ObjectBuffer);1291  if (!BinOrErr)1292    return BinOrErr.takeError();1293  std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());1294 1295  if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))1296    return make_error<CoverageMapError>(1297        coveragemap_error::invalid_or_missing_arch_specifier);1298 1299  // MachO universal binaries which contain archives need to be treated as1300  // archives, not as regular binaries.1301  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {1302    for (auto &ObjForArch : Universal->objects()) {1303      // Skip slices within the universal binary which target the wrong arch.1304      std::string ObjArch = ObjForArch.getArchFlagName();1305      if (Arch != ObjArch)1306        continue;1307 1308      auto ArchiveOrErr = ObjForArch.getAsArchive();1309      if (!ArchiveOrErr) {1310        // If this is not an archive, try treating it as a regular object.1311        consumeError(ArchiveOrErr.takeError());1312        break;1313      }1314 1315      return BinaryCoverageReader::create(1316          ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,1317          CompilationDir, BinaryIDs);1318    }1319  }1320 1321  // Load coverage out of archive members.1322  if (auto *Ar = dyn_cast<Archive>(Bin.get())) {1323    Error Err = Error::success();1324    for (auto &Child : Ar->children(Err)) {1325      Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();1326      if (!ChildBufOrErr)1327        return ChildBufOrErr.takeError();1328 1329      auto ChildReadersOrErr = BinaryCoverageReader::create(1330          ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,1331          BinaryIDs);1332      if (!ChildReadersOrErr)1333        return ChildReadersOrErr.takeError();1334      for (auto &Reader : ChildReadersOrErr.get())1335        Readers.push_back(std::move(Reader));1336    }1337    if (Err)1338      return std::move(Err);1339 1340    // Thin archives reference object files outside of the archive file, i.e.1341    // files which reside in memory not owned by the caller. Transfer ownership1342    // to the caller.1343    if (Ar->isThin())1344      for (auto &Buffer : Ar->takeThinBuffers())1345        ObjectFileBuffers.push_back(std::move(Buffer));1346 1347    return std::move(Readers);1348  }1349 1350  object::BuildIDRef BinaryID;1351  auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,1352                                      BinaryIDs ? &BinaryID : nullptr);1353  if (!ReaderOrErr)1354    return ReaderOrErr.takeError();1355  Readers.push_back(std::move(ReaderOrErr.get()));1356  if (!BinaryID.empty())1357    BinaryIDs->push_back(BinaryID);1358  return std::move(Readers);1359}1360 1361Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {1362  if (CurrentRecord >= MappingRecords.size())1363    return make_error<CoverageMapError>(coveragemap_error::eof);1364 1365  FunctionsFilenames.clear();1366  Expressions.clear();1367  MappingRegions.clear();1368  auto &R = MappingRecords[CurrentRecord];1369  auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);1370  RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,1371                                  Expressions, MappingRegions);1372  if (auto Err = Reader.read())1373    return Err;1374 1375  Record.FunctionName = R.FunctionName;1376  Record.FunctionHash = R.FunctionHash;1377  Record.Filenames = FunctionsFilenames;1378  Record.Expressions = Expressions;1379  Record.MappingRegions = MappingRegions;1380 1381  ++CurrentRecord;1382  return Error::success();1383}1384