//===-- InstrProfCorrelator.cpp -------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "llvm/ProfileData/InstrProfCorrelator.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/WithColor.h"
#include <optional>

#define DEBUG_TYPE "correlator"

using namespace llvm;

/// Get profile section.
static Expected<object::SectionRef>
getInstrProfSection(const object::ObjectFile &Obj, InstrProfSectKind IPSK) {
  // On COFF, the getInstrProfSectionName returns the section names may followed
  // by "$M". The linker removes the dollar and everything after it in the final
  // binary. Do the same to match.
  Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
  auto StripSuffix = [ObjFormat](StringRef N) {
    return ObjFormat == Triple::COFF ? N.split('$').first : N;
  };
  std::string ExpectedSectionName =
      getInstrProfSectionName(IPSK, ObjFormat,
                              /*AddSegmentInfo=*/false);
  ExpectedSectionName = StripSuffix(ExpectedSectionName);
  for (auto &Section : Obj.sections()) {
    if (auto SectionName = Section.getName())
      if (*SectionName == ExpectedSectionName)
        return Section;
  }
  return make_error<InstrProfError>(
      instrprof_error::unable_to_correlate_profile,
      "could not find section (" + Twine(ExpectedSectionName) + ")");
}

const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
const char *InstrProfCorrelator::CFGHashAttributeName = "CFG Hash";
const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters";
const char *InstrProfCorrelator::NumBitmapBitsAttributeName = "Num BitmapBits";

llvm::Expected<std::unique_ptr<InstrProfCorrelator::Context>>
InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
                                  object::ObjectFile &Obj,
                                  ProfCorrelatorKind FileKind) {
  auto C = std::make_unique<Context>();
  auto CountersSection = getInstrProfSection(Obj, IPSK_cnts);
  if (auto Err = CountersSection.takeError())
    return std::move(Err);
  Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
  if (FileKind == InstrProfCorrelator::BINARY) {
    auto DataSection = getInstrProfSection(Obj, IPSK_covdata);
    if (auto Err = DataSection.takeError())
      return std::move(Err);
    auto DataOrErr = DataSection->getContents();
    if (!DataOrErr)
      return DataOrErr.takeError();
    auto NameSection = getInstrProfSection(Obj, IPSK_covname);
    if (auto Err = NameSection.takeError())
      return std::move(Err);
    auto NameOrErr = NameSection->getContents();
    if (!NameOrErr)
      return NameOrErr.takeError();
    C->DataStart = DataOrErr->data();
    C->DataEnd = DataOrErr->data() + DataOrErr->size();
    C->NameStart = NameOrErr->data();
    C->NameSize = NameOrErr->size();

    if (ObjFormat == Triple::MachO) {
      std::string FullSectionName =
          getInstrProfSectionName(IPSK_covdata, ObjFormat);
      SmallVector<StringRef, 3> SegmentAndSection;
      StringRef(FullSectionName).split(SegmentAndSection, ',', 2);
      auto *MachO = static_cast<object::MachOObjectFile *>(&Obj);
      Error Err = Error::success();
      for (const object::MachOChainedFixupEntry &Entry :
           MachO->fixupTable(Err)) {
        if (Entry.isRebase() && Entry.segmentName() == SegmentAndSection[0] &&
            Entry.sectionName() == SegmentAndSection[1]) {
          C->MachOFixups[Entry.address() - DataSection->getAddress()] =
              Entry.pointerValue();
        }
      }
      if (Err)
        return std::move(Err);
    }
  }
  C->Buffer = std::move(Buffer);
  C->CountersSectionStart = CountersSection->getAddress();
  C->CountersSectionEnd = C->CountersSectionStart + CountersSection->getSize();

  auto BitmapSection = getInstrProfSection(Obj, IPSK_bitmap);
  if (auto E = BitmapSection.takeError()) {
    // It is not an error if NumBitmapBytes of each function is zero.
    consumeError(std::move(E));
    C->BitmapSectionStart = 0;
    C->BitmapSectionEnd = 0;
  } else {
    C->BitmapSectionStart = BitmapSection->getAddress();
    C->BitmapSectionEnd = C->BitmapSectionStart + BitmapSection->getSize();
  }
  // In COFF object file, there's a null byte at the beginning of both the
  // counter and bitmap sections which doesn't exist in raw profile.
  if (ObjFormat == Triple::COFF) {
    ++C->CountersSectionStart;
    if (C->BitmapSectionStart)
      ++C->BitmapSectionStart;
  }

  C->ShouldSwapBytes = Obj.isLittleEndian() != sys::IsLittleEndianHost;
  return Expected<std::unique_ptr<Context>>(std::move(C));
}

llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind,
                         const object::BuildIDFetcher *BIDFetcher,
                         const ArrayRef<object::BuildID> BIs) {
  // Might be overwritten from BuildIDFetcher.
  std::string EffectiveFilename = Filename.str();
  if (BIDFetcher) {
    if (BIs.empty())
      return make_error<InstrProfError>(
          instrprof_error::unable_to_correlate_profile,
          "unsupported profile binary correlation when there is no build ID "
          "in a profile");
    if (BIs.size() > 1)
      return make_error<InstrProfError>(
          instrprof_error::unable_to_correlate_profile,
          "unsupported profile binary correlation when there are multiple "
          "build IDs in a profile");

    Expected<std::string> Path = BIDFetcher->fetch(BIs.front());
    if (!Path) {
      // Propagate as InstrProf specific error type.
      consumeError(Path.takeError());
      return make_error<InstrProfError>(
          instrprof_error::unable_to_correlate_profile,
          "Missing build ID: " + llvm::toHex(BIs.front(),
                                             /*LowerCase=*/true));
    }
    EffectiveFilename = *Path;
  }

  if (FileKind == DEBUG_INFO) {
    auto DsymObjectsOrErr =
        object::MachOObjectFile::findDsymObjectMembers(EffectiveFilename);
    if (auto Err = DsymObjectsOrErr.takeError())
      return std::move(Err);
    if (!DsymObjectsOrErr->empty()) {
      // TODO: Enable profile correlation when there are multiple objects in a
      // dSYM bundle.
      if (DsymObjectsOrErr->size() > 1)
        return make_error<InstrProfError>(
            instrprof_error::unable_to_correlate_profile,
            "using multiple objects is not yet supported");
      EffectiveFilename = *DsymObjectsOrErr->begin();
    }
    auto BufferOrErr =
        errorOrToExpected(MemoryBuffer::getFile(EffectiveFilename));
    if (auto Err = BufferOrErr.takeError())
      return std::move(Err);

    return get(std::move(*BufferOrErr), FileKind);
  }
  if (FileKind == BINARY) {
    auto BufferOrErr =
        errorOrToExpected(MemoryBuffer::getFile(EffectiveFilename));
    if (auto Err = BufferOrErr.takeError())
      return std::move(Err);

    return get(std::move(*BufferOrErr), FileKind);
  }
  return make_error<InstrProfError>(
      instrprof_error::unable_to_correlate_profile,
      "unsupported correlation kind (only DWARF debug info and Binary format "
      "(ELF/COFF) are supported)");
}

llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer,
                         ProfCorrelatorKind FileKind) {
  auto BinOrErr = object::createBinary(*Buffer);
  if (auto Err = BinOrErr.takeError())
    return std::move(Err);

  if (auto *Obj = dyn_cast<object::ObjectFile>(BinOrErr->get())) {
    auto CtxOrErr = Context::get(std::move(Buffer), *Obj, FileKind);
    if (auto Err = CtxOrErr.takeError())
      return std::move(Err);
    auto T = Obj->makeTriple();
    if (T.isArch64Bit())
      return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj,
                                                    FileKind);
    if (T.isArch32Bit())
      return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj,
                                                    FileKind);
  }
  return make_error<InstrProfError>(
      instrprof_error::unable_to_correlate_profile, "not an object file");
}

std::optional<size_t> InstrProfCorrelator::getDataSize() const {
  if (auto *C = dyn_cast<InstrProfCorrelatorImpl<uint32_t>>(this))
    return C->getDataSize();
  if (auto *C = dyn_cast<InstrProfCorrelatorImpl<uint64_t>>(this))
    return C->getDataSize();
  return {};
}

namespace llvm {

template <>
InstrProfCorrelatorImpl<uint32_t>::InstrProfCorrelatorImpl(
    std::unique_ptr<InstrProfCorrelator::Context> Ctx)
    : InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_32Bit,
                              std::move(Ctx)) {}
template <>
InstrProfCorrelatorImpl<uint64_t>::InstrProfCorrelatorImpl(
    std::unique_ptr<InstrProfCorrelator::Context> Ctx)
    : InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_64Bit,
                              std::move(Ctx)) {}
template <>
bool InstrProfCorrelatorImpl<uint32_t>::classof(const InstrProfCorrelator *C) {
  return C->getKind() == InstrProfCorrelatorKind::CK_32Bit;
}
template <>
bool InstrProfCorrelatorImpl<uint64_t>::classof(const InstrProfCorrelator *C) {
  return C->getKind() == InstrProfCorrelatorKind::CK_64Bit;
}

} // end namespace llvm

template <class IntPtrT>
llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
InstrProfCorrelatorImpl<IntPtrT>::get(
    std::unique_ptr<InstrProfCorrelator::Context> Ctx,
    const object::ObjectFile &Obj, ProfCorrelatorKind FileKind) {
  if (FileKind == DEBUG_INFO) {
    if (Obj.isELF() || Obj.isMachO()) {
      auto DICtx = DWARFContext::create(Obj);
      return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(
          std::move(DICtx), std::move(Ctx));
    }
    return make_error<InstrProfError>(
        instrprof_error::unable_to_correlate_profile,
        "unsupported debug info format (only DWARF is supported)");
  }
  if (Obj.isELF() || Obj.isCOFF() || Obj.isMachO())
    return std::make_unique<BinaryInstrProfCorrelator<IntPtrT>>(std::move(Ctx));
  return make_error<InstrProfError>(
      instrprof_error::unable_to_correlate_profile,
      "unsupported binary format (only ELF, COFF, and Mach-O are supported)");
}

template <class IntPtrT>
Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData(int MaxWarnings) {
  assert(Data.empty() && Names.empty() && NamesVec.empty());
  correlateProfileDataImpl(MaxWarnings);
  if (this->Data.empty())
    return make_error<InstrProfError>(
        instrprof_error::unable_to_correlate_profile,
        "could not find any profile data metadata in correlated file");
  Error Result = correlateProfileNameImpl();
  this->CounterOffsets.clear();
  this->BitmapOffsets.clear();
  this->NamesVec.clear();
  return Result;
}

template <> struct yaml::MappingTraits<InstrProfCorrelator::CorrelationData> {
  static void mapping(yaml::IO &io,
                      InstrProfCorrelator::CorrelationData &Data) {
    io.mapRequired("Probes", Data.Probes);
  }
};

template <> struct yaml::MappingTraits<InstrProfCorrelator::Probe> {
  static void mapping(yaml::IO &io, InstrProfCorrelator::Probe &P) {
    io.mapRequired("Function Name", P.FunctionName);
    io.mapOptional("Linkage Name", P.LinkageName);
    io.mapRequired("CFG Hash", P.CFGHash);
    io.mapRequired("Counter Offset", P.CounterOffset);
    io.mapRequired("Num Counters", P.NumCounters);
    io.mapRequired("Bitmap Offset", P.BitmapOffset);
    io.mapRequired("Num BitmapBytes", P.NumBitmapBytes);
    io.mapOptional("File", P.FilePath);
    io.mapOptional("Line", P.LineNumber);
  }
};

template <> struct yaml::SequenceElementTraits<InstrProfCorrelator::Probe> {
  static const bool flow = false;
};

template <class IntPtrT>
Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(int MaxWarnings,
                                                 raw_ostream &OS) {
  InstrProfCorrelator::CorrelationData Data;
  correlateProfileDataImpl(MaxWarnings, &Data);
  if (Data.Probes.empty())
    return make_error<InstrProfError>(
        instrprof_error::unable_to_correlate_profile,
        "could not find any profile data metadata in debug info");
  yaml::Output YamlOS(OS);
  YamlOS << Data;
  return Error::success();
}

template <class IntPtrT>
void InstrProfCorrelatorImpl<IntPtrT>::addDataProbe(
    uint64_t NameRef, uint64_t CFGHash, IntPtrT CounterOffset,
    IntPtrT BitmapOffset, IntPtrT FunctionPtr, uint32_t NumCounters,
    uint32_t NumBitmapBytes) {
  // Check if a probe was already added for this counter offset.
  if (NumCounters && !CounterOffsets.insert(CounterOffset).second)
    return;
  // Check if a probe was already added for this bitmap offset.
  if (NumBitmapBytes && !BitmapOffsets.insert(BitmapOffset).second)
    return;
  Data.push_back({
      maybeSwap<uint64_t>(NameRef),
      maybeSwap<uint64_t>(CFGHash),
      // In this mode, CounterPtr actually stores the section relative address
      // of the counter.
      maybeSwap<IntPtrT>(CounterOffset),
      /*UniformCounterPtr=*/maybeSwap<IntPtrT>(0),
      maybeSwap<IntPtrT>(BitmapOffset),
      maybeSwap<IntPtrT>(FunctionPtr),
      // TODO: Value profiling is not yet supported.
      /*ValuesPtr=*/maybeSwap<IntPtrT>(0),
      maybeSwap<uint32_t>(NumCounters),
      /*NumValueSites=*/{maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
      /*OffloadDeviceWaveSize=*/maybeSwap<uint16_t>(0),
      maybeSwap<uint32_t>(NumBitmapBytes),
  });
}

template <class IntPtrT>
std::optional<uint64_t>
DwarfInstrProfCorrelator<IntPtrT>::getLocation(const DWARFDie &Die) const {
  auto Locations = Die.getLocations(dwarf::DW_AT_location);
  if (!Locations) {
    consumeError(Locations.takeError());
    return {};
  }
  auto &DU = *Die.getDwarfUnit();
  auto AddressSize = DU.getAddressByteSize();
  for (auto &Location : *Locations) {
    DataExtractor Data(Location.Expr, DICtx->isLittleEndian());
    DWARFExpression Expr(Data, AddressSize);
    for (auto &Op : Expr) {
      if (Op.getCode() == dwarf::DW_OP_addr)
        return Op.getRawOperand(0);
      if (Op.getCode() == dwarf::DW_OP_addrx) {
        uint64_t Index = Op.getRawOperand(0);
        if (auto SA = DU.getAddrOffsetSectionItem(Index))
          return SA->Address;
      }
    }
  }
  return {};
}

template <class IntPtrT>
bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die,
                                                     StringRef Prefix) {
  const auto &ParentDie = Die.getParent();
  if (!Die.isValid() || !ParentDie.isValid() || Die.isNULL())
    return false;
  if (Die.getTag() != dwarf::DW_TAG_variable)
    return false;
  if (!ParentDie.isSubprogramDIE())
    return false;
  if (!Die.hasChildren())
    return false;
  if (const char *Name = Die.getName(DINameKind::ShortName))
    return StringRef(Name).starts_with(Prefix);
  return false;
}

template <class IntPtrT>
std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
DwarfInstrProfCorrelator<IntPtrT>::addCountersToDataProbe(
    const DWARFDie &Die, const bool UnlimitedWarnings,
    int &NumSuppressedWarnings) {
  std::optional<const char *> FunctionName;
  std::optional<uint64_t> CFGHash;
  std::optional<uint64_t> CounterPtr = getLocation(Die);
  auto FnDie = Die.getParent();
  auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc));
  std::optional<uint64_t> NumCounters;
  for (const DWARFDie &Child : Die.children()) {
    if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
      continue;
    auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
    auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
    if (!AnnotationFormName || !AnnotationFormValue)
      continue;
    auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
    if (auto Err = AnnotationNameOrErr.takeError()) {
      consumeError(std::move(Err));
      continue;
    }
    StringRef AnnotationName = *AnnotationNameOrErr;
    if (AnnotationName == InstrProfCorrelator::FunctionNameAttributeName) {
      if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName))
        consumeError(std::move(EC));
    } else if (AnnotationName == InstrProfCorrelator::CFGHashAttributeName) {
      CFGHash = AnnotationFormValue->getAsUnsignedConstant();
    } else if (AnnotationName ==
               InstrProfCorrelator::NumCountersAttributeName) {
      NumCounters = AnnotationFormValue->getAsUnsignedConstant();
    }
  }
  // If there is no function and no counter, assume it was dead-stripped
  if (!FunctionPtr && !CounterPtr)
    return std::nullopt;
  if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
    if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
      WithColor::warning() << "Incomplete DIE for function " << FunctionName
                           << ": CFGHash=" << CFGHash
                           << "  CounterPtr=" << CounterPtr
                           << "  NumCounters=" << NumCounters << "\n";
      LLVM_DEBUG(Die.dump(dbgs()));
    }
    return std::nullopt;
  }
  uint64_t CountersStart = this->Ctx->CountersSectionStart;
  uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
  if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
    if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
      WithColor::warning() << format(
          "CounterPtr out of range for function %s: Actual=0x%x "
          "Expected=[0x%x, 0x%x)\n",
          *FunctionName, *CounterPtr, CountersStart, CountersEnd);
      LLVM_DEBUG(Die.dump(dbgs()));
    }
    return std::nullopt;
  }
  if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) {
    WithColor::warning() << format("Could not find address of function %s\n",
                                   *FunctionName);
    LLVM_DEBUG(Die.dump(dbgs()));
  }
  // In debug info correlation mode, the CounterPtr is an absolute address
  // of the counter, but it's expected to be relative later when iterating
  // Data.
  IntPtrT CounterOffset = *CounterPtr - CountersStart;
  InstrProfCorrelator::Probe P = {};
  P.FunctionName = *FunctionName;
  if (const char *Name = FnDie.getName(DINameKind::LinkageName))
    P.LinkageName = Name;
  P.CFGHash = *CFGHash;
  P.CounterOffset = CounterOffset;
  P.NumCounters = *NumCounters;
  auto FilePath = FnDie.getDeclFile(
      DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
  if (!FilePath.empty())
    P.FilePath = FilePath;
  if (auto LineNumber = FnDie.getDeclLine())
    P.LineNumber = LineNumber;

  return std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>(
      {P, FunctionPtr.value_or(0)});
}

template <class IntPtrT>
std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>
DwarfInstrProfCorrelator<IntPtrT>::addBitmapToDataProbe(
    const DWARFDie &Die, const bool UnlimitedWarnings,
    int &NumSuppressedWarnings) {
  std::optional<const char *> FunctionName;
  std::optional<uint64_t> BitmapPtr = getLocation(Die);
  uint64_t NumBitmapBytes;
  for (const DWARFDie &Child : Die.children()) {
    if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
      continue;
    auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
    auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
    if (!AnnotationFormName || !AnnotationFormValue)
      continue;
    auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
    if (auto Err = AnnotationNameOrErr.takeError()) {
      consumeError(std::move(Err));
      continue;
    }
    StringRef AnnotationName = *AnnotationNameOrErr;
    if (AnnotationName == InstrProfCorrelator::FunctionNameAttributeName) {
      if (auto EC = AnnotationFormValue->getAsCString().moveInto(FunctionName))
        consumeError(std::move(EC));
    } else if (AnnotationName ==
               InstrProfCorrelator::NumBitmapBitsAttributeName) {
      std::optional<uint64_t> NumBitmapBits =
          AnnotationFormValue->getAsUnsignedConstant();
      NumBitmapBytes = alignTo(*NumBitmapBits, CHAR_BIT) / CHAR_BIT;
    }
  }
  if (!FunctionName || !BitmapPtr || !NumBitmapBytes) {
    if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
      WithColor::warning() << "Incomplete DIE for function " << FunctionName
                           << "  BitmapPtr=" << BitmapPtr
                           << "  NumBitmapBytes=" << NumBitmapBytes << "\n";
      LLVM_DEBUG(Die.dump(dbgs()));
    }
    return std::nullopt;
  }
  uint64_t BitmapStart = this->Ctx->BitmapSectionStart;
  uint64_t BitmapEnd = this->Ctx->BitmapSectionEnd;
  if (!BitmapStart && !BitmapEnd && NumBitmapBytes) {
    auto E = make_error<InstrProfError>(
        instrprof_error::unable_to_correlate_profile,
        "could not find profile bitmap section in correlated file");
    return std::nullopt;
  }
  if (*BitmapPtr < BitmapStart || (*BitmapPtr >= BitmapEnd && NumBitmapBytes)) {
    if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
      WithColor::warning() << format(
          "BitmapPtr out of range for function %s: Actual=0x%x "
          "Expected=[0x%x, 0x%x)\n",
          *FunctionName, *BitmapPtr, BitmapStart, BitmapEnd);
      LLVM_DEBUG(Die.dump(dbgs()));
    }
    return std::nullopt;
  }
  // In debug info correlation mode, the BitmapPtr is an absolute address of
  // the bitmap, but it's expected to be relative later when iterating Data.
  IntPtrT BitmapOffset = *BitmapPtr - BitmapStart;
  InstrProfCorrelator::Probe P = {};
  P.FunctionName = *FunctionName;
  P.BitmapOffset = BitmapOffset;
  P.NumBitmapBytes = NumBitmapBytes;

  return std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>>({P, 0});
}

template <class IntPtrT>
void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
    int MaxWarnings, InstrProfCorrelator::CorrelationData *Data) {
  // Map from FunctionName string to (Probe, FunctionPtr) pair.
  // We use it to collect data from all functions Counter and Bitmap DIEs.
  MapVector<std::string, std::pair<InstrProfCorrelator::Probe, IntPtrT>,
            StringMap<unsigned>>
      Probes;
  bool UnlimitedWarnings = (MaxWarnings == 0);
  // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
  int NumSuppressedWarnings = -MaxWarnings;

  auto MaybeAddProbe = [&](DWARFDie Die) {
    std::optional<std::pair<InstrProfCorrelator::Probe, IntPtrT>> ProbeData;
    if (isDIEOfProbe(Die, getInstrProfCountersVarPrefix()))
      ProbeData =
          addCountersToDataProbe(Die, UnlimitedWarnings, NumSuppressedWarnings);
    else if (isDIEOfProbe(Die, getInstrProfBitmapVarPrefix()))
      ProbeData =
          addBitmapToDataProbe(Die, UnlimitedWarnings, NumSuppressedWarnings);
    if (!ProbeData)
      return;
    auto [Probe, FunctionPtr] = *ProbeData;

    auto [It, Inserted] =
        Probes.try_emplace(Probe.FunctionName, Probe, FunctionPtr);
    if (!Inserted) {
      auto &P = It->second.first;
      if (isDIEOfProbe(Die, getInstrProfCountersVarPrefix())) {
        P.LinkageName = Probe.LinkageName;
        P.CFGHash = Probe.CFGHash;
        P.CounterOffset = Probe.CounterOffset;
        P.NumCounters = Probe.NumCounters;
        P.FilePath = Probe.FilePath;
        P.LineNumber = Probe.LineNumber;
      } else {
        P.BitmapOffset = Probe.BitmapOffset;
        P.NumBitmapBytes = Probe.NumBitmapBytes;
      }
    }
  };
  for (auto &CU : DICtx->normal_units())
    for (const auto &Entry : CU->dies())
      MaybeAddProbe(DWARFDie(CU.get(), &Entry));
  for (auto &CU : DICtx->dwo_units())
    for (const auto &Entry : CU->dies())
      MaybeAddProbe(DWARFDie(CU.get(), &Entry));

  for (const auto &[FunctionName, ProbeData] : Probes) {
    const auto &[Probe, FunctionPtr] = ProbeData;
    if (Data)
      Data->Probes.push_back(Probe);
    else {
      this->NamesVec.push_back(FunctionName);
      uint64_t NameRef = IndexedInstrProf::ComputeHash(FunctionName);
      this->addDataProbe(NameRef, Probe.CFGHash, Probe.CounterOffset,
                         Probe.BitmapOffset, FunctionPtr, Probe.NumCounters,
                         Probe.NumBitmapBytes);
    }
  }
  if (!UnlimitedWarnings && NumSuppressedWarnings > 0)
    WithColor::warning() << format("Suppressed %d additional warnings\n",
                                   NumSuppressedWarnings);
}

template <class IntPtrT>
Error DwarfInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
  if (this->NamesVec.empty()) {
    return make_error<InstrProfError>(
        instrprof_error::unable_to_correlate_profile,
        "could not find any profile name metadata in debug info");
  }
  auto Result =
      collectGlobalObjectNameStrings(this->NamesVec,
                                     /*doCompression=*/false, this->Names);
  return Result;
}

template <class IntPtrT>
void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
    int MaxWarnings, InstrProfCorrelator::CorrelationData *CorrelateData) {
  using RawProfData = RawInstrProf::ProfileData<IntPtrT>;
  bool UnlimitedWarnings = (MaxWarnings == 0);
  // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
  int NumSuppressedWarnings = -MaxWarnings;

  const RawProfData *DataStart = (const RawProfData *)this->Ctx->DataStart;
  const RawProfData *DataEnd = (const RawProfData *)this->Ctx->DataEnd;
  // We need to use < here because the last data record may have no padding.
  for (const RawProfData *I = DataStart; I < DataEnd; ++I) {
    uint64_t CounterPtr = this->template maybeSwap<IntPtrT>(I->CounterPtr);
    uint64_t CountersStart = this->Ctx->CountersSectionStart;
    uint64_t CountersEnd = this->Ctx->CountersSectionEnd;

    uint64_t BitmapPtr = this->template maybeSwap<IntPtrT>(I->BitmapPtr);
    uint64_t BitmapStart = this->Ctx->BitmapSectionStart;
    uint64_t BitmapEnd = this->Ctx->BitmapSectionEnd;
    if (!BitmapStart && !BitmapEnd && I->NumBitmapBytes) {
      auto E = make_error<InstrProfError>(
          instrprof_error::unable_to_correlate_profile,
          "could not find profile bitmap section in correlated file");
      return;
    }
    if (!this->Ctx->MachOFixups.empty()) {
      auto GetPtrByOffset = [&](uint64_t Offset, uint64_t &Ptr) {
        auto It = this->Ctx->MachOFixups.find(Offset);
        if (It != this->Ctx->MachOFixups.end()) {
          Ptr = It->second;
        } else if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
          WithColor::warning() << format(
              "Mach-O fixup not found for covdata offset 0x%llx\n", Offset);
        }
      };
      uint64_t CounterOffset = (uint64_t)&I->CounterPtr - (uint64_t)DataStart;
      uint64_t BitmapOffset = (uint64_t)&I->BitmapPtr - (uint64_t)DataStart;
      GetPtrByOffset(CounterOffset, CounterPtr);
      GetPtrByOffset(BitmapOffset, BitmapPtr);
    }
    if (CounterPtr < CountersStart || CounterPtr >= CountersEnd) {
      if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
        WithColor::warning()
            << format("CounterPtr out of range for function: Actual=0x%x "
                      "Expected=[0x%x, 0x%x) at data offset=0x%x\n",
                      CounterPtr, CountersStart, CountersEnd,
                      (I - DataStart) * sizeof(RawProfData));
      }
    }
    if (I->NumBitmapBytes &&
        (BitmapPtr < BitmapStart || BitmapPtr >= BitmapEnd)) {
      if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
        WithColor::warning()
            << format("BitmapPtr out of range for function: Actual=0x%x "
                      "Expected=[0x%x, 0x%x) at data offset=0x%x\n",
                      BitmapPtr, BitmapStart, BitmapEnd,
                      (I - DataStart) * sizeof(RawProfData));
      }
    }
    // In binary correlation mode, CounterPtr and BitmapPtr are absolute
    // addresses, but they're expected to be relative later when iterating Data.
    IntPtrT CounterOffset = CounterPtr - CountersStart;
    IntPtrT BitmapOffset = BitmapPtr - BitmapStart;
    this->addDataProbe(I->NameRef, I->FuncHash, CounterOffset, BitmapOffset,
                       I->FunctionPointer, I->NumCounters, I->NumBitmapBytes);
  }
}

template <class IntPtrT>
Error BinaryInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
  if (this->Ctx->NameSize == 0) {
    return make_error<InstrProfError>(
        instrprof_error::unable_to_correlate_profile,
        "could not find any profile data metadata in object file");
  }
  this->Names.append(this->Ctx->NameStart, this->Ctx->NameSize);
  return Error::success();
}
