//===- CoverageMappingReader.cpp - Code coverage mapping reader -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains support for reading coverage mapping data for
// instrumentation based coverage.
//
//===----------------------------------------------------------------------===//

#include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/Error.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <vector>

using namespace llvm;
using namespace coverage;
using namespace object;

#define DEBUG_TYPE "coverage-mapping"

STATISTIC(CovMapNumRecords, "The # of coverage function records");
STATISTIC(CovMapNumUsedRecords, "The # of used coverage function records");

void CoverageMappingIterator::increment() {
  if (ReadErr != coveragemap_error::success)
    return;

  // Check if all the records were read or if an error occurred while reading
  // the next record.
  if (auto E = Reader->readNextRecord(Record))
    handleAllErrors(std::move(E), [&](const CoverageMapError &CME) {
      if (CME.get() == coveragemap_error::eof)
        *this = CoverageMappingIterator();
      else
        ReadErr = CME.get();
    });
}

Error RawCoverageReader::readULEB128(uint64_t &Result) {
  if (Data.empty())
    return make_error<CoverageMapError>(coveragemap_error::truncated);
  unsigned N = 0;
  Result = decodeULEB128(Data.bytes_begin(), &N);
  if (N > Data.size())
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  Data = Data.substr(N);
  return Error::success();
}

Error RawCoverageReader::readIntMax(uint64_t &Result, uint64_t MaxPlus1) {
  if (auto Err = readULEB128(Result))
    return Err;
  if (Result >= MaxPlus1)
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  return Error::success();
}

Error RawCoverageReader::readSize(uint64_t &Result) {
  if (auto Err = readULEB128(Result))
    return Err;
  if (Result > Data.size())
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  return Error::success();
}

Error RawCoverageReader::readString(StringRef &Result) {
  uint64_t Length;
  if (auto Err = readSize(Length))
    return Err;
  Result = Data.substr(0, Length);
  Data = Data.substr(Length);
  return Error::success();
}

Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
  uint64_t NumFilenames;
  if (auto Err = readSize(NumFilenames))
    return Err;
  if (!NumFilenames)
    return make_error<CoverageMapError>(coveragemap_error::malformed);

  if (Version < CovMapVersion::Version4)
    return readUncompressed(Version, NumFilenames);

  // The uncompressed length may exceed the size of the encoded filenames.
  // Skip size validation.
  uint64_t UncompressedLen;
  if (auto Err = readULEB128(UncompressedLen))
    return Err;

  uint64_t CompressedLen;
  if (auto Err = readSize(CompressedLen))
    return Err;

  if (CompressedLen > 0) {
    if (!compression::zlib::isAvailable())
      return make_error<CoverageMapError>(
          coveragemap_error::decompression_failed);

    // Allocate memory for the decompressed filenames.
    SmallVector<uint8_t, 0> StorageBuf;

    // Read compressed filenames.
    StringRef CompressedFilenames = Data.substr(0, CompressedLen);
    Data = Data.substr(CompressedLen);
    auto Err = compression::zlib::decompress(
        arrayRefFromStringRef(CompressedFilenames), StorageBuf,
        UncompressedLen);
    if (Err) {
      consumeError(std::move(Err));
      return make_error<CoverageMapError>(
          coveragemap_error::decompression_failed);
    }

    RawCoverageFilenamesReader Delegate(toStringRef(StorageBuf), Filenames,
                                        CompilationDir);
    return Delegate.readUncompressed(Version, NumFilenames);
  }

  return readUncompressed(Version, NumFilenames);
}

Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version,
                                                   uint64_t NumFilenames) {
  // Read uncompressed filenames.
  if (Version < CovMapVersion::Version6) {
    for (size_t I = 0; I < NumFilenames; ++I) {
      StringRef Filename;
      if (auto Err = readString(Filename))
        return Err;
      Filenames.push_back(Filename.str());
    }
  } else {
    StringRef CWD;
    if (auto Err = readString(CWD))
      return Err;
    Filenames.push_back(CWD.str());

    for (size_t I = 1; I < NumFilenames; ++I) {
      StringRef Filename;
      if (auto Err = readString(Filename))
        return Err;
      if (sys::path::is_absolute(Filename)) {
        Filenames.push_back(Filename.str());
      } else {
        SmallString<256> P;
        if (!CompilationDir.empty())
          P.assign(CompilationDir);
        else
          P.assign(CWD);
        llvm::sys::path::append(P, Filename);
        sys::path::remove_dots(P, /*remove_dot_dot=*/true);
        Filenames.push_back(static_cast<std::string>(P.str()));
      }
    }
  }
  return Error::success();
}

Error RawCoverageMappingReader::decodeCounter(unsigned Value, Counter &C) {
  auto Tag = Value & Counter::EncodingTagMask;
  switch (Tag) {
  case Counter::Zero:
    C = Counter::getZero();
    return Error::success();
  case Counter::CounterValueReference:
    C = Counter::getCounter(Value >> Counter::EncodingTagBits);
    return Error::success();
  default:
    break;
  }
  Tag -= Counter::Expression;
  switch (Tag) {
  case CounterExpression::Subtract:
  case CounterExpression::Add: {
    auto ID = Value >> Counter::EncodingTagBits;
    if (ID >= Expressions.size())
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    Expressions[ID].Kind = CounterExpression::ExprKind(Tag);
    C = Counter::getExpression(ID);
    break;
  }
  default:
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  }
  return Error::success();
}

Error RawCoverageMappingReader::readCounter(Counter &C) {
  uint64_t EncodedCounter;
  if (auto Err =
          readIntMax(EncodedCounter, std::numeric_limits<unsigned>::max()))
    return Err;
  if (auto Err = decodeCounter(EncodedCounter, C))
    return Err;
  return Error::success();
}

static const unsigned EncodingExpansionRegionBit = 1
                                                   << Counter::EncodingTagBits;

/// Read the sub-array of regions for the given inferred file id.
/// \param NumFileIDs the number of file ids that are defined for this
/// function.
Error RawCoverageMappingReader::readMappingRegionsSubArray(
    std::vector<CounterMappingRegion> &MappingRegions, unsigned InferredFileID,
    size_t NumFileIDs) {
  uint64_t NumRegions;
  if (auto Err = readSize(NumRegions))
    return Err;
  unsigned LineStart = 0;
  for (size_t I = 0; I < NumRegions; ++I) {
    Counter C, C2;
    CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion;

    // Read the combined counter + region kind.
    uint64_t EncodedCounterAndRegion;
    if (auto Err = readIntMax(EncodedCounterAndRegion,
                              std::numeric_limits<unsigned>::max()))
      return Err;
    unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
    uint64_t ExpandedFileID = 0;

    // If Tag does not represent a ZeroCounter, then it is understood to refer
    // to a counter or counter expression with region kind assumed to be
    // "CodeRegion". In that case, EncodedCounterAndRegion actually encodes the
    // referenced counter or counter expression (and nothing else).
    //
    // If Tag represents a ZeroCounter and EncodingExpansionRegionBit is set,
    // then EncodedCounterAndRegion is interpreted to represent an
    // ExpansionRegion. In all other cases, EncodedCounterAndRegion is
    // interpreted to refer to a specific region kind, after which additional
    // fields may be read (e.g. BranchRegions have two encoded counters that
    // follow an encoded region kind value).
    if (Tag != Counter::Zero) {
      if (auto Err = decodeCounter(EncodedCounterAndRegion, C))
        return Err;
    } else {
      // Is it an expansion region?
      if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
        Kind = CounterMappingRegion::ExpansionRegion;
        ExpandedFileID = EncodedCounterAndRegion >>
                         Counter::EncodingCounterTagAndExpansionRegionTagBits;
        if (ExpandedFileID >= NumFileIDs)
          return make_error<CoverageMapError>(coveragemap_error::malformed);
      } else {
        switch (EncodedCounterAndRegion >>
                Counter::EncodingCounterTagAndExpansionRegionTagBits) {
        case CounterMappingRegion::CodeRegion:
          // Don't do anything when we have a code region with a zero counter.
          break;
        case CounterMappingRegion::SkippedRegion:
          Kind = CounterMappingRegion::SkippedRegion;
          break;
        case CounterMappingRegion::BranchRegion:
          // For a Branch Region, read two successive counters.
          Kind = CounterMappingRegion::BranchRegion;
          if (auto Err = readCounter(C))
            return Err;
          if (auto Err = readCounter(C2))
            return Err;
          break;
        default:
          return make_error<CoverageMapError>(coveragemap_error::malformed);
        }
      }
    }

    // Read the source range.
    uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
    if (auto Err =
            readIntMax(LineStartDelta, std::numeric_limits<unsigned>::max()))
      return Err;
    if (auto Err = readULEB128(ColumnStart))
      return Err;
    if (ColumnStart > std::numeric_limits<unsigned>::max())
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    if (auto Err = readIntMax(NumLines, std::numeric_limits<unsigned>::max()))
      return Err;
    if (auto Err = readIntMax(ColumnEnd, std::numeric_limits<unsigned>::max()))
      return Err;
    LineStart += LineStartDelta;

    // If the high bit of ColumnEnd is set, this is a gap region.
    if (ColumnEnd & (1U << 31)) {
      Kind = CounterMappingRegion::GapRegion;
      ColumnEnd &= ~(1U << 31);
    }

    // Adjust the column locations for the empty regions that are supposed to
    // cover whole lines. Those regions should be encoded with the
    // column range (1 -> std::numeric_limits<unsigned>::max()), but because
    // the encoded std::numeric_limits<unsigned>::max() is several bytes long,
    // we set the column range to (0 -> 0) to ensure that the column start and
    // column end take up one byte each.
    // The std::numeric_limits<unsigned>::max() is used to represent a column
    // position at the end of the line without knowing the length of that line.
    if (ColumnStart == 0 && ColumnEnd == 0) {
      ColumnStart = 1;
      ColumnEnd = std::numeric_limits<unsigned>::max();
    }

    LLVM_DEBUG({
      dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":"
             << ColumnStart << " -> " << (LineStart + NumLines) << ":"
             << ColumnEnd << ", ";
      if (Kind == CounterMappingRegion::ExpansionRegion)
        dbgs() << "Expands to file " << ExpandedFileID;
      else
        CounterMappingContext(Expressions).dump(C, dbgs());
      dbgs() << "\n";
    });

    auto CMR = CounterMappingRegion(C, C2, InferredFileID, ExpandedFileID,
                                    LineStart, ColumnStart,
                                    LineStart + NumLines, ColumnEnd, Kind);
    if (CMR.startLoc() > CMR.endLoc())
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    MappingRegions.push_back(CMR);
  }
  return Error::success();
}

Error RawCoverageMappingReader::read() {
  // Read the virtual file mapping.
  SmallVector<unsigned, 8> VirtualFileMapping;
  uint64_t NumFileMappings;
  if (auto Err = readSize(NumFileMappings))
    return Err;
  for (size_t I = 0; I < NumFileMappings; ++I) {
    uint64_t FilenameIndex;
    if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
      return Err;
    VirtualFileMapping.push_back(FilenameIndex);
  }

  // Construct the files using unique filenames and virtual file mapping.
  for (auto I : VirtualFileMapping) {
    Filenames.push_back(TranslationUnitFilenames[I]);
  }

  // Read the expressions.
  uint64_t NumExpressions;
  if (auto Err = readSize(NumExpressions))
    return Err;
  // Create an array of dummy expressions that get the proper counters
  // when the expressions are read, and the proper kinds when the counters
  // are decoded.
  Expressions.resize(
      NumExpressions,
      CounterExpression(CounterExpression::Subtract, Counter(), Counter()));
  for (size_t I = 0; I < NumExpressions; ++I) {
    if (auto Err = readCounter(Expressions[I].LHS))
      return Err;
    if (auto Err = readCounter(Expressions[I].RHS))
      return Err;
  }

  // Read the mapping regions sub-arrays.
  for (unsigned InferredFileID = 0, S = VirtualFileMapping.size();
       InferredFileID < S; ++InferredFileID) {
    if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
                                              VirtualFileMapping.size()))
      return Err;
  }

  // Set the counters for the expansion regions.
  // i.e. Counter of expansion region = counter of the first region
  // from the expanded file.
  // Perform multiple passes to correctly propagate the counters through
  // all the nested expansion regions.
  SmallVector<CounterMappingRegion *, 8> FileIDExpansionRegionMapping;
  FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr);
  for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) {
    for (auto &R : MappingRegions) {
      if (R.Kind != CounterMappingRegion::ExpansionRegion)
        continue;
      assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
      FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
    }
    for (auto &R : MappingRegions) {
      if (FileIDExpansionRegionMapping[R.FileID]) {
        FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
        FileIDExpansionRegionMapping[R.FileID] = nullptr;
      }
    }
  }

  return Error::success();
}

Expected<bool> RawCoverageMappingDummyChecker::isDummy() {
  // A dummy coverage mapping data consists of just one region with zero count.
  uint64_t NumFileMappings;
  if (Error Err = readSize(NumFileMappings))
    return std::move(Err);
  if (NumFileMappings != 1)
    return false;
  // We don't expect any specific value for the filename index, just skip it.
  uint64_t FilenameIndex;
  if (Error Err =
          readIntMax(FilenameIndex, std::numeric_limits<unsigned>::max()))
    return std::move(Err);
  uint64_t NumExpressions;
  if (Error Err = readSize(NumExpressions))
    return std::move(Err);
  if (NumExpressions != 0)
    return false;
  uint64_t NumRegions;
  if (Error Err = readSize(NumRegions))
    return std::move(Err);
  if (NumRegions != 1)
    return false;
  uint64_t EncodedCounterAndRegion;
  if (Error Err = readIntMax(EncodedCounterAndRegion,
                             std::numeric_limits<unsigned>::max()))
    return std::move(Err);
  unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask;
  return Tag == Counter::Zero;
}

Error InstrProfSymtab::create(SectionRef &Section) {
  Expected<StringRef> DataOrErr = Section.getContents();
  if (!DataOrErr)
    return DataOrErr.takeError();
  Data = *DataOrErr;
  Address = Section.getAddress();

  // If this is a linked PE/COFF file, then we have to skip over the null byte
  // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
  const ObjectFile *Obj = Section.getObject();
  if (isa<COFFObjectFile>(Obj) && !Obj->isRelocatableObject())
    Data = Data.drop_front(1);

  return Error::success();
}

StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
  if (Pointer < Address)
    return StringRef();
  auto Offset = Pointer - Address;
  if (Offset + Size > Data.size())
    return StringRef();
  return Data.substr(Pointer - Address, Size);
}

// Check if the mapping data is a dummy, i.e. is emitted for an unused function.
static Expected<bool> isCoverageMappingDummy(uint64_t Hash, StringRef Mapping) {
  // The hash value of dummy mapping records is always zero.
  if (Hash)
    return false;
  return RawCoverageMappingDummyChecker(Mapping).isDummy();
}

/// A range of filename indices. Used to specify the location of a batch of
/// filenames in a vector-like container.
struct FilenameRange {
  unsigned StartingIndex;
  unsigned Length;

  FilenameRange(unsigned StartingIndex, unsigned Length)
      : StartingIndex(StartingIndex), Length(Length) {}

  void markInvalid() { Length = 0; }
  bool isInvalid() const { return Length == 0; }
};

namespace {

/// The interface to read coverage mapping function records for a module.
struct CovMapFuncRecordReader {
  virtual ~CovMapFuncRecordReader() = default;

  // Read a coverage header.
  //
  // \p CovBuf points to the buffer containing the \c CovHeader of the coverage
  // mapping data associated with the module.
  //
  // Returns a pointer to the next \c CovHeader if it exists, or to an address
  // greater than \p CovEnd if not.
  virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
                                                    const char *CovBufEnd) = 0;

  // Read function records.
  //
  // \p FuncRecBuf points to the buffer containing a batch of function records.
  // \p FuncRecBufEnd points past the end of the batch of records.
  //
  // Prior to Version4, \p OutOfLineFileRange points to a sequence of filenames
  // associated with the function records. It is unused in Version4.
  //
  // Prior to Version4, \p OutOfLineMappingBuf points to a sequence of coverage
  // mappings associated with the function records. It is unused in Version4.
  virtual Error
  readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
                      std::optional<FilenameRange> OutOfLineFileRange,
                      const char *OutOfLineMappingBuf,
                      const char *OutOfLineMappingBufEnd) = 0;

  template <class IntPtrT, support::endianness Endian>
  static Expected<std::unique_ptr<CovMapFuncRecordReader>>
  get(CovMapVersion Version, InstrProfSymtab &P,
      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
      std::vector<std::string> &F);
};

// A class for reading coverage mapping function records for a module.
template <CovMapVersion Version, class IntPtrT, support::endianness Endian>
class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
  using FuncRecordType =
      typename CovMapTraits<Version, IntPtrT>::CovMapFuncRecordType;
  using NameRefType = typename CovMapTraits<Version, IntPtrT>::NameRefType;

  // Maps function's name references to the indexes of their records
  // in \c Records.
  DenseMap<NameRefType, size_t> FunctionRecords;
  InstrProfSymtab &ProfileNames;
  StringRef CompilationDir;
  std::vector<std::string> &Filenames;
  std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;

  // Maps a hash of the filenames in a TU to a \c FileRange. The range
  // specifies the location of the hashed filenames in \c Filenames.
  DenseMap<uint64_t, FilenameRange> FileRangeMap;

  // Add the record to the collection if we don't already have a record that
  // points to the same function name. This is useful to ignore the redundant
  // records for the functions with ODR linkage.
  // In addition, prefer records with real coverage mapping data to dummy
  // records, which were emitted for inline functions which were seen but
  // not used in the corresponding translation unit.
  Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
                                     StringRef Mapping,
                                     FilenameRange FileRange) {
    ++CovMapNumRecords;
    uint64_t FuncHash = CFR->template getFuncHash<Endian>();
    NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
    auto InsertResult =
        FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
    if (InsertResult.second) {
      StringRef FuncName;
      if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
        return Err;
      if (FuncName.empty())
        return make_error<InstrProfError>(instrprof_error::malformed,
                                          "function name is empty");
      ++CovMapNumUsedRecords;
      Records.emplace_back(Version, FuncName, FuncHash, Mapping,
                           FileRange.StartingIndex, FileRange.Length);
      return Error::success();
    }
    // Update the existing record if it's a dummy and the new record is real.
    size_t OldRecordIndex = InsertResult.first->second;
    BinaryCoverageReader::ProfileMappingRecord &OldRecord =
        Records[OldRecordIndex];
    Expected<bool> OldIsDummyExpected = isCoverageMappingDummy(
        OldRecord.FunctionHash, OldRecord.CoverageMapping);
    if (Error Err = OldIsDummyExpected.takeError())
      return Err;
    if (!*OldIsDummyExpected)
      return Error::success();
    Expected<bool> NewIsDummyExpected =
        isCoverageMappingDummy(FuncHash, Mapping);
    if (Error Err = NewIsDummyExpected.takeError())
      return Err;
    if (*NewIsDummyExpected)
      return Error::success();
    ++CovMapNumUsedRecords;
    OldRecord.FunctionHash = FuncHash;
    OldRecord.CoverageMapping = Mapping;
    OldRecord.FilenamesBegin = FileRange.StartingIndex;
    OldRecord.FilenamesSize = FileRange.Length;
    return Error::success();
  }

public:
  VersionedCovMapFuncRecordReader(
      InstrProfSymtab &P,
      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
      std::vector<std::string> &F)
      : ProfileNames(P), CompilationDir(D), Filenames(F), Records(R) {}

  ~VersionedCovMapFuncRecordReader() override = default;

  Expected<const char *> readCoverageHeader(const char *CovBuf,
                                            const char *CovBufEnd) override {
    using namespace support;

    if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    auto CovHeader = reinterpret_cast<const CovMapHeader *>(CovBuf);
    uint32_t NRecords = CovHeader->getNRecords<Endian>();
    uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
    uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
    assert((CovMapVersion)CovHeader->getVersion<Endian>() == Version);
    CovBuf = reinterpret_cast<const char *>(CovHeader + 1);

    // Skip past the function records, saving the start and end for later.
    // This is a no-op in Version4 (function records are read after all headers
    // are read).
    const char *FuncRecBuf = nullptr;
    const char *FuncRecBufEnd = nullptr;
    if (Version < CovMapVersion::Version4)
      FuncRecBuf = CovBuf;
    CovBuf += NRecords * sizeof(FuncRecordType);
    if (Version < CovMapVersion::Version4)
      FuncRecBufEnd = CovBuf;

    // Get the filenames.
    if (CovBuf + FilenamesSize > CovBufEnd)
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    size_t FilenamesBegin = Filenames.size();
    StringRef FilenameRegion(CovBuf, FilenamesSize);
    RawCoverageFilenamesReader Reader(FilenameRegion, Filenames,
                                      CompilationDir);
    if (auto Err = Reader.read(Version))
      return std::move(Err);
    CovBuf += FilenamesSize;
    FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);

    if (Version >= CovMapVersion::Version4) {
      // Map a hash of the filenames region to the filename range associated
      // with this coverage header.
      int64_t FilenamesRef =
          llvm::IndexedInstrProf::ComputeHash(FilenameRegion);
      auto Insert =
          FileRangeMap.insert(std::make_pair(FilenamesRef, FileRange));
      if (!Insert.second) {
        // The same filenames ref was encountered twice. It's possible that
        // the associated filenames are the same.
        auto It = Filenames.begin();
        FilenameRange &OrigRange = Insert.first->getSecond();
        if (std::equal(It + OrigRange.StartingIndex,
                       It + OrigRange.StartingIndex + OrigRange.Length,
                       It + FileRange.StartingIndex,
                       It + FileRange.StartingIndex + FileRange.Length))
          // Map the new range to the original one.
          FileRange = OrigRange;
        else
          // This is a hash collision. Mark the filenames ref invalid.
          OrigRange.markInvalid();
      }
    }

    // We'll read the coverage mapping records in the loop below.
    // This is a no-op in Version4 (coverage mappings are not affixed to the
    // coverage header).
    const char *MappingBuf = CovBuf;
    if (Version >= CovMapVersion::Version4 && CoverageSize != 0)
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    CovBuf += CoverageSize;
    const char *MappingEnd = CovBuf;

    if (CovBuf > CovBufEnd)
      return make_error<CoverageMapError>(coveragemap_error::malformed);

    if (Version < CovMapVersion::Version4) {
      // Read each function record.
      if (Error E = readFunctionRecords(FuncRecBuf, FuncRecBufEnd, FileRange,
                                        MappingBuf, MappingEnd))
        return std::move(E);
    }

    // Each coverage map has an alignment of 8, so we need to adjust alignment
    // before reading the next map.
    CovBuf += offsetToAlignedAddr(CovBuf, Align(8));

    return CovBuf;
  }

  Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
                            std::optional<FilenameRange> OutOfLineFileRange,
                            const char *OutOfLineMappingBuf,
                            const char *OutOfLineMappingBufEnd) override {
    auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
    while ((const char *)CFR < FuncRecBufEnd) {
      // Validate the length of the coverage mapping for this function.
      const char *NextMappingBuf;
      const FuncRecordType *NextCFR;
      std::tie(NextMappingBuf, NextCFR) =
          CFR->template advanceByOne<Endian>(OutOfLineMappingBuf);
      if (Version < CovMapVersion::Version4)
        if (NextMappingBuf > OutOfLineMappingBufEnd)
          return make_error<CoverageMapError>(coveragemap_error::malformed);

      // Look up the set of filenames associated with this function record.
      std::optional<FilenameRange> FileRange;
      if (Version < CovMapVersion::Version4) {
        FileRange = OutOfLineFileRange;
      } else {
        uint64_t FilenamesRef = CFR->template getFilenamesRef<Endian>();
        auto It = FileRangeMap.find(FilenamesRef);
        if (It == FileRangeMap.end())
          return make_error<CoverageMapError>(coveragemap_error::malformed);
        else
          FileRange = It->getSecond();
      }

      // Now, read the coverage data.
      if (FileRange && !FileRange->isInvalid()) {
        StringRef Mapping =
            CFR->template getCoverageMapping<Endian>(OutOfLineMappingBuf);
        if (Version >= CovMapVersion::Version4 &&
            Mapping.data() + Mapping.size() > FuncRecBufEnd)
          return make_error<CoverageMapError>(coveragemap_error::malformed);
        if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
          return Err;
      }

      std::tie(OutOfLineMappingBuf, CFR) = std::tie(NextMappingBuf, NextCFR);
    }
    return Error::success();
  }
};

} // end anonymous namespace

template <class IntPtrT, support::endianness Endian>
Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
    CovMapVersion Version, InstrProfSymtab &P,
    std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
    std::vector<std::string> &F) {
  using namespace coverage;

  switch (Version) {
  case CovMapVersion::Version1:
    return std::make_unique<VersionedCovMapFuncRecordReader<
        CovMapVersion::Version1, IntPtrT, Endian>>(P, R, D, F);
  case CovMapVersion::Version2:
  case CovMapVersion::Version3:
  case CovMapVersion::Version4:
  case CovMapVersion::Version5:
  case CovMapVersion::Version6:
    // Decompress the name data.
    if (Error E = P.create(P.getNameData()))
      return std::move(E);
    if (Version == CovMapVersion::Version2)
      return std::make_unique<VersionedCovMapFuncRecordReader<
          CovMapVersion::Version2, IntPtrT, Endian>>(P, R, D, F);
    else if (Version == CovMapVersion::Version3)
      return std::make_unique<VersionedCovMapFuncRecordReader<
          CovMapVersion::Version3, IntPtrT, Endian>>(P, R, D, F);
    else if (Version == CovMapVersion::Version4)
      return std::make_unique<VersionedCovMapFuncRecordReader<
          CovMapVersion::Version4, IntPtrT, Endian>>(P, R, D, F);
    else if (Version == CovMapVersion::Version5)
      return std::make_unique<VersionedCovMapFuncRecordReader<
          CovMapVersion::Version5, IntPtrT, Endian>>(P, R, D, F);
    else if (Version == CovMapVersion::Version6)
      return std::make_unique<VersionedCovMapFuncRecordReader<
          CovMapVersion::Version6, IntPtrT, Endian>>(P, R, D, F);
  }
  llvm_unreachable("Unsupported version");
}

template <typename T, support::endianness Endian>
static Error readCoverageMappingData(
    InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
    std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
    StringRef CompilationDir, std::vector<std::string> &Filenames) {
  using namespace coverage;

  // Read the records in the coverage data section.
  auto CovHeader =
      reinterpret_cast<const CovMapHeader *>(CovMap.data());
  CovMapVersion Version = (CovMapVersion)CovHeader->getVersion<Endian>();
  if (Version > CovMapVersion::CurrentVersion)
    return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
  Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
      CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
                                             CompilationDir, Filenames);
  if (Error E = ReaderExpected.takeError())
    return E;
  auto Reader = std::move(ReaderExpected.get());
  const char *CovBuf = CovMap.data();
  const char *CovBufEnd = CovBuf + CovMap.size();
  const char *FuncRecBuf = FuncRecords.data();
  const char *FuncRecBufEnd = FuncRecords.data() + FuncRecords.size();
  while (CovBuf < CovBufEnd) {
    // Read the current coverage header & filename data.
    //
    // Prior to Version4, this also reads all function records affixed to the
    // header.
    //
    // Return a pointer to the next coverage header.
    auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
    if (auto E = NextOrErr.takeError())
      return E;
    CovBuf = NextOrErr.get();
  }
  // In Version4, function records are not affixed to coverage headers. Read
  // the records from their dedicated section.
  if (Version >= CovMapVersion::Version4)
    return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
                                       nullptr, nullptr);
  return Error::success();
}

static const char *TestingFormatMagic = "llvmcovmtestdata";

Expected<std::unique_ptr<BinaryCoverageReader>>
BinaryCoverageReader::createCoverageReaderFromBuffer(
    StringRef Coverage, FuncRecordsStorage &&FuncRecords,
    InstrProfSymtab &&ProfileNames, uint8_t BytesInAddress,
    support::endianness Endian, StringRef CompilationDir) {
  std::unique_ptr<BinaryCoverageReader> Reader(
      new BinaryCoverageReader(std::move(FuncRecords)));
  Reader->ProfileNames = std::move(ProfileNames);
  StringRef FuncRecordsRef = Reader->FuncRecords->getBuffer();
  if (BytesInAddress == 4 && Endian == support::endianness::little) {
    if (Error E =
            readCoverageMappingData<uint32_t, support::endianness::little>(
                Reader->ProfileNames, Coverage, FuncRecordsRef,
                Reader->MappingRecords, CompilationDir, Reader->Filenames))
      return std::move(E);
  } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
    if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
            Reader->ProfileNames, Coverage, FuncRecordsRef,
            Reader->MappingRecords, CompilationDir, Reader->Filenames))
      return std::move(E);
  } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
    if (Error E =
            readCoverageMappingData<uint64_t, support::endianness::little>(
                Reader->ProfileNames, Coverage, FuncRecordsRef,
                Reader->MappingRecords, CompilationDir, Reader->Filenames))
      return std::move(E);
  } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
    if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
            Reader->ProfileNames, Coverage, FuncRecordsRef,
            Reader->MappingRecords, CompilationDir, Reader->Filenames))
      return std::move(E);
  } else
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  return std::move(Reader);
}

static Expected<std::unique_ptr<BinaryCoverageReader>>
loadTestingFormat(StringRef Data, StringRef CompilationDir) {
  uint8_t BytesInAddress = 8;
  support::endianness Endian = support::endianness::little;

  Data = Data.substr(StringRef(TestingFormatMagic).size());
  if (Data.empty())
    return make_error<CoverageMapError>(coveragemap_error::truncated);
  unsigned N = 0;
  uint64_t ProfileNamesSize = decodeULEB128(Data.bytes_begin(), &N);
  if (N > Data.size())
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  Data = Data.substr(N);
  if (Data.empty())
    return make_error<CoverageMapError>(coveragemap_error::truncated);
  N = 0;
  uint64_t Address = decodeULEB128(Data.bytes_begin(), &N);
  if (N > Data.size())
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  Data = Data.substr(N);
  if (Data.size() < ProfileNamesSize)
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  InstrProfSymtab ProfileNames;
  if (Error E = ProfileNames.create(Data.substr(0, ProfileNamesSize), Address))
    return std::move(E);
  Data = Data.substr(ProfileNamesSize);
  // Skip the padding bytes because coverage map data has an alignment of 8.
  size_t Pad = offsetToAlignedAddr(Data.data(), Align(8));
  if (Data.size() < Pad)
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  Data = Data.substr(Pad);
  if (Data.size() < sizeof(CovMapHeader))
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  auto const *CovHeader = reinterpret_cast<const CovMapHeader *>(
      Data.substr(0, sizeof(CovMapHeader)).data());
  CovMapVersion Version =
      (CovMapVersion)CovHeader->getVersion<support::endianness::little>();
  StringRef CoverageMapping;
  BinaryCoverageReader::FuncRecordsStorage CoverageRecords;
  if (Version < CovMapVersion::Version4) {
    CoverageMapping = Data;
    if (CoverageMapping.empty())
      return make_error<CoverageMapError>(coveragemap_error::truncated);
    CoverageRecords = MemoryBuffer::getMemBuffer("");
  } else {
    uint32_t FilenamesSize =
        CovHeader->getFilenamesSize<support::endianness::little>();
    uint32_t CoverageMappingSize = sizeof(CovMapHeader) + FilenamesSize;
    CoverageMapping = Data.substr(0, CoverageMappingSize);
    if (CoverageMapping.empty())
      return make_error<CoverageMapError>(coveragemap_error::truncated);
    Data = Data.substr(CoverageMappingSize);
    // Skip the padding bytes because coverage records data has an alignment
    // of 8.
    Pad = offsetToAlignedAddr(Data.data(), Align(8));
    if (Data.size() < Pad)
      return make_error<CoverageMapError>(coveragemap_error::malformed);
    CoverageRecords = MemoryBuffer::getMemBuffer(Data.substr(Pad));
    if (CoverageRecords->getBufferSize() == 0)
      return make_error<CoverageMapError>(coveragemap_error::truncated);
  }
  return BinaryCoverageReader::createCoverageReaderFromBuffer(
      CoverageMapping, std::move(CoverageRecords), std::move(ProfileNames),
      BytesInAddress, Endian, CompilationDir);
}

/// Find all sections that match \p Name. There may be more than one if comdats
/// are in use, e.g. for the __llvm_covfun section on ELF.
static Expected<std::vector<SectionRef>> lookupSections(ObjectFile &OF,
                                                        StringRef Name) {
  // On COFF, the object file section name may end in "$M". This tells the
  // linker to sort these sections between "$A" and "$Z". The linker removes the
  // dollar and everything after it in the final binary. Do the same to match.
  bool IsCOFF = isa<COFFObjectFile>(OF);
  auto stripSuffix = [IsCOFF](StringRef N) {
    return IsCOFF ? N.split('$').first : N;
  };
  Name = stripSuffix(Name);

  std::vector<SectionRef> Sections;
  for (const auto &Section : OF.sections()) {
    Expected<StringRef> NameOrErr = Section.getName();
    if (!NameOrErr)
      return NameOrErr.takeError();
    if (stripSuffix(*NameOrErr) == Name)
      Sections.push_back(Section);
  }
  if (Sections.empty())
    return make_error<CoverageMapError>(coveragemap_error::no_data_found);
  return Sections;
}

static Expected<std::unique_ptr<BinaryCoverageReader>>
loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
                 StringRef CompilationDir = "",
                 std::optional<object::BuildIDRef> *BinaryID = nullptr) {
  std::unique_ptr<ObjectFile> OF;
  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
    // If we have a universal binary, try to look up the object for the
    // appropriate architecture.
    auto ObjectFileOrErr = Universal->getMachOObjectForArch(Arch);
    if (!ObjectFileOrErr)
      return ObjectFileOrErr.takeError();
    OF = std::move(ObjectFileOrErr.get());
  } else if (isa<ObjectFile>(Bin.get())) {
    // For any other object file, upcast and take ownership.
    OF.reset(cast<ObjectFile>(Bin.release()));
    // If we've asked for a particular arch, make sure they match.
    if (!Arch.empty() && OF->getArch() != Triple(Arch).getArch())
      return errorCodeToError(object_error::arch_not_found);
  } else
    // We can only handle object files.
    return make_error<CoverageMapError>(coveragemap_error::malformed);

  // The coverage uses native pointer sizes for the object it's written in.
  uint8_t BytesInAddress = OF->getBytesInAddress();
  support::endianness Endian = OF->isLittleEndian()
                                   ? support::endianness::little
                                   : support::endianness::big;

  // Look for the sections that we are interested in.
  auto ObjFormat = OF->getTripleObjectFormat();
  auto NamesSection =
      lookupSections(*OF, getInstrProfSectionName(IPSK_name, ObjFormat,
                                                 /*AddSegmentInfo=*/false));
  if (auto E = NamesSection.takeError())
    return std::move(E);
  auto CoverageSection =
      lookupSections(*OF, getInstrProfSectionName(IPSK_covmap, ObjFormat,
                                                  /*AddSegmentInfo=*/false));
  if (auto E = CoverageSection.takeError())
    return std::move(E);
  std::vector<SectionRef> CoverageSectionRefs = *CoverageSection;
  if (CoverageSectionRefs.size() != 1)
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  auto CoverageMappingOrErr = CoverageSectionRefs.back().getContents();
  if (!CoverageMappingOrErr)
    return CoverageMappingOrErr.takeError();
  StringRef CoverageMapping = CoverageMappingOrErr.get();

  InstrProfSymtab ProfileNames;
  std::vector<SectionRef> NamesSectionRefs = *NamesSection;
  if (NamesSectionRefs.size() != 1)
    return make_error<CoverageMapError>(coveragemap_error::malformed);
  if (Error E = ProfileNames.create(NamesSectionRefs.back()))
    return std::move(E);

  // Look for the coverage records section (Version4 only).
  auto CoverageRecordsSections =
      lookupSections(*OF, getInstrProfSectionName(IPSK_covfun, ObjFormat,
                                                  /*AddSegmentInfo=*/false));

  BinaryCoverageReader::FuncRecordsStorage FuncRecords;
  if (auto E = CoverageRecordsSections.takeError()) {
    consumeError(std::move(E));
    FuncRecords = MemoryBuffer::getMemBuffer("");
  } else {
    // Compute the FuncRecordsBuffer of the buffer, taking into account the
    // padding between each record, and making sure the first block is aligned
    // in memory to maintain consistency between buffer address and size
    // alignment.
    const Align RecordAlignment(8);
    uint64_t FuncRecordsSize = 0;
    for (SectionRef Section : *CoverageRecordsSections) {
      auto CoverageRecordsOrErr = Section.getContents();
      if (!CoverageRecordsOrErr)
        return CoverageRecordsOrErr.takeError();
      FuncRecordsSize += alignTo(CoverageRecordsOrErr->size(), RecordAlignment);
    }
    auto WritableBuffer =
        WritableMemoryBuffer::getNewUninitMemBuffer(FuncRecordsSize);
    char *FuncRecordsBuffer = WritableBuffer->getBufferStart();
    assert(isAddrAligned(RecordAlignment, FuncRecordsBuffer) &&
           "Allocated memory is correctly aligned");

    for (SectionRef Section : *CoverageRecordsSections) {
      auto CoverageRecordsOrErr = Section.getContents();
      if (!CoverageRecordsOrErr)
        return CoverageRecordsOrErr.takeError();
      const auto &CoverageRecords = CoverageRecordsOrErr.get();
      FuncRecordsBuffer = std::copy(CoverageRecords.begin(),
                                    CoverageRecords.end(), FuncRecordsBuffer);
      FuncRecordsBuffer =
          std::fill_n(FuncRecordsBuffer,
                      alignAddr(FuncRecordsBuffer, RecordAlignment) -
                          (uintptr_t)FuncRecordsBuffer,
                      '\0');
    }
    assert(FuncRecordsBuffer == WritableBuffer->getBufferEnd() &&
           "consistent init");
    FuncRecords = std::move(WritableBuffer);
  }

  if (BinaryID)
    *BinaryID = getBuildID(OF.get());

  return BinaryCoverageReader::createCoverageReaderFromBuffer(
      CoverageMapping, std::move(FuncRecords), std::move(ProfileNames),
      BytesInAddress, Endian, CompilationDir);
}

/// Determine whether \p Arch is invalid or empty, given \p Bin.
static bool isArchSpecifierInvalidOrMissing(Binary *Bin, StringRef Arch) {
  // If we have a universal binary and Arch doesn't identify any of its slices,
  // it's user error.
  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin)) {
    for (auto &ObjForArch : Universal->objects())
      if (Arch == ObjForArch.getArchFlagName())
        return false;
    return true;
  }
  return false;
}

Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
BinaryCoverageReader::create(
    MemoryBufferRef ObjectBuffer, StringRef Arch,
    SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
    StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {
  std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;

  if (ObjectBuffer.getBuffer().startswith(TestingFormatMagic)) {
    // This is a special format used for testing.
    auto ReaderOrErr =
        loadTestingFormat(ObjectBuffer.getBuffer(), CompilationDir);
    if (!ReaderOrErr)
      return ReaderOrErr.takeError();
    Readers.push_back(std::move(ReaderOrErr.get()));
    return std::move(Readers);
  }

  auto BinOrErr = createBinary(ObjectBuffer);
  if (!BinOrErr)
    return BinOrErr.takeError();
  std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());

  if (isArchSpecifierInvalidOrMissing(Bin.get(), Arch))
    return make_error<CoverageMapError>(
        coveragemap_error::invalid_or_missing_arch_specifier);

  // MachO universal binaries which contain archives need to be treated as
  // archives, not as regular binaries.
  if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
    for (auto &ObjForArch : Universal->objects()) {
      // Skip slices within the universal binary which target the wrong arch.
      std::string ObjArch = ObjForArch.getArchFlagName();
      if (Arch != ObjArch)
        continue;

      auto ArchiveOrErr = ObjForArch.getAsArchive();
      if (!ArchiveOrErr) {
        // If this is not an archive, try treating it as a regular object.
        consumeError(ArchiveOrErr.takeError());
        break;
      }

      return BinaryCoverageReader::create(
          ArchiveOrErr.get()->getMemoryBufferRef(), Arch, ObjectFileBuffers,
          CompilationDir, BinaryIDs);
    }
  }

  // Load coverage out of archive members.
  if (auto *Ar = dyn_cast<Archive>(Bin.get())) {
    Error Err = Error::success();
    for (auto &Child : Ar->children(Err)) {
      Expected<MemoryBufferRef> ChildBufOrErr = Child.getMemoryBufferRef();
      if (!ChildBufOrErr)
        return ChildBufOrErr.takeError();

      auto ChildReadersOrErr = BinaryCoverageReader::create(
          ChildBufOrErr.get(), Arch, ObjectFileBuffers, CompilationDir,
          BinaryIDs);
      if (!ChildReadersOrErr)
        return ChildReadersOrErr.takeError();
      for (auto &Reader : ChildReadersOrErr.get())
        Readers.push_back(std::move(Reader));
    }
    if (Err)
      return std::move(Err);

    // Thin archives reference object files outside of the archive file, i.e.
    // files which reside in memory not owned by the caller. Transfer ownership
    // to the caller.
    if (Ar->isThin())
      for (auto &Buffer : Ar->takeThinBuffers())
        ObjectFileBuffers.push_back(std::move(Buffer));

    return std::move(Readers);
  }

  std::optional<object::BuildIDRef> BinaryID;
  auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,
                                      BinaryIDs ? &BinaryID : nullptr);
  if (!ReaderOrErr)
    return ReaderOrErr.takeError();
  Readers.push_back(std::move(ReaderOrErr.get()));
  if (BinaryID)
    BinaryIDs->push_back(*BinaryID);
  return std::move(Readers);
}

Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) {
  if (CurrentRecord >= MappingRecords.size())
    return make_error<CoverageMapError>(coveragemap_error::eof);

  FunctionsFilenames.clear();
  Expressions.clear();
  MappingRegions.clear();
  auto &R = MappingRecords[CurrentRecord];
  auto F = ArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
  RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
                                  Expressions, MappingRegions);
  if (auto Err = Reader.read())
    return Err;

  Record.FunctionName = R.FunctionName;
  Record.FunctionHash = R.FunctionHash;
  Record.Filenames = FunctionsFilenames;
  Record.Expressions = Expressions;
  Record.MappingRegions = MappingRegions;

  ++CurrentRecord;
  return Error::success();
}
