//===- bolt/Rewrite/DWARFRewriter.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 "bolt/Rewrite/DWARFRewriter.h"
#include "bolt/Core/BinaryContext.h"
#include "bolt/Core/BinaryFunction.h"
#include "bolt/Core/DIEBuilder.h"
#include "bolt/Core/DebugData.h"
#include "bolt/Core/DynoStats.h"
#include "bolt/Core/ParallelUtilities.h"
#include "bolt/Rewrite/RewriteInstance.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <iterator>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#undef DEBUG_TYPE
#define DEBUG_TYPE "bolt"

static void printDie(const DWARFDie &DIE) {
  DIDumpOptions DumpOpts;
  DumpOpts.ShowForm = true;
  DumpOpts.Verbose = true;
  DumpOpts.ChildRecurseDepth = 0;
  DumpOpts.ShowChildren = false;
  DIE.dump(dbgs(), 0, DumpOpts);
}

/// Lazily parse DWARF DIE and print it out.
LLVM_ATTRIBUTE_UNUSED
static void printDie(DWARFUnit &DU, uint64_t DIEOffset) {
  uint64_t OriginalOffsets = DIEOffset;
  uint64_t NextCUOffset = DU.getNextUnitOffset();
  DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();
  DWARFDebugInfoEntry DIEEntry;
  if (DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset, 0)) {
    if (const DWARFAbbreviationDeclaration *AbbrDecl =
            DIEEntry.getAbbreviationDeclarationPtr()) {
      DWARFDie DDie(&DU, &DIEEntry);
      printDie(DDie);
    } else {
      dbgs() << "Failed to extract abbreviation for"
             << Twine::utohexstr(OriginalOffsets) << "\n";
    }
  } else {
    dbgs() << "Failed to extract DIE for " << Twine::utohexstr(OriginalOffsets)
           << " \n";
  }
}

using namespace bolt;

/// Take a set of DWARF address ranges corresponding to the input binary and
/// translate them to a set of address ranges in the output binary.
static DebugAddressRangesVector
translateInputToOutputRanges(const BinaryFunction &BF,
                             const DWARFAddressRangesVector &InputRanges) {
  DebugAddressRangesVector OutputRanges;

  // If the function hasn't changed return the same ranges.
  if (!BF.isEmitted()) {
    OutputRanges.resize(InputRanges.size());
    llvm::transform(InputRanges, OutputRanges.begin(),
                    [](const DWARFAddressRange &Range) {
                      return DebugAddressRange(Range.LowPC, Range.HighPC);
                    });
    return OutputRanges;
  }

  for (const DWARFAddressRange &Range : InputRanges)
    llvm::append_range(OutputRanges, BF.translateInputToOutputRange(
                                         {Range.LowPC, Range.HighPC}));

  // Post-processing pass to sort and merge ranges.
  llvm::sort(OutputRanges);
  DebugAddressRangesVector MergedRanges;
  uint64_t PrevHighPC = 0;
  for (const DebugAddressRange &Range : OutputRanges) {
    if (Range.LowPC <= PrevHighPC) {
      MergedRanges.back().HighPC =
          std::max(MergedRanges.back().HighPC, Range.HighPC);
    } else {
      MergedRanges.emplace_back(Range.LowPC, Range.HighPC);
    }
    PrevHighPC = MergedRanges.back().HighPC;
  }

  return MergedRanges;
}

/// Similar to translateInputToOutputRanges() but operates on location lists.
static DebugLocationsVector
translateInputToOutputLocationList(const BinaryFunction &BF,
                                   const DebugLocationsVector &InputLL) {
  DebugLocationsVector OutputLL;

  // If the function hasn't changed - there's nothing to update.
  if (!BF.isEmitted())
    return InputLL;

  for (const DebugLocationEntry &Entry : InputLL) {
    DebugAddressRangesVector OutRanges =
        BF.translateInputToOutputRange({Entry.LowPC, Entry.HighPC});
    if (!OutRanges.empty() && !OutputLL.empty()) {
      if (OutRanges.front().LowPC == OutputLL.back().HighPC &&
          Entry.Expr == OutputLL.back().Expr) {
        OutputLL.back().HighPC =
            std::max(OutputLL.back().HighPC, OutRanges.front().HighPC);
        OutRanges.erase(OutRanges.begin());
      }
    }
    llvm::transform(OutRanges, std::back_inserter(OutputLL),
                    [&Entry](const DebugAddressRange &R) {
                      return DebugLocationEntry{R.LowPC, R.HighPC, Entry.Expr};
                    });
  }

  // Sort and merge adjacent entries with identical locations.
  llvm::stable_sort(
      OutputLL, [](const DebugLocationEntry &A, const DebugLocationEntry &B) {
        return A.LowPC < B.LowPC;
      });
  DebugLocationsVector MergedLL;
  uint64_t PrevHighPC = 0;
  const SmallVectorImpl<uint8_t> *PrevExpr = nullptr;
  for (const DebugLocationEntry &Entry : OutputLL) {
    if (Entry.LowPC <= PrevHighPC && *PrevExpr == Entry.Expr) {
      MergedLL.back().HighPC = std::max(Entry.HighPC, MergedLL.back().HighPC);
    } else {
      const uint64_t Begin = std::max(Entry.LowPC, PrevHighPC);
      const uint64_t End = std::max(Begin, Entry.HighPC);
      MergedLL.emplace_back(DebugLocationEntry{Begin, End, Entry.Expr});
    }
    PrevHighPC = MergedLL.back().HighPC;
    PrevExpr = &MergedLL.back().Expr;
  }

  return MergedLL;
}

using namespace dwarf_linker;
using namespace dwarf_linker::classic;

namespace llvm {
namespace bolt {
/// Emits debug information into .debug_info or .debug_types section.
class DIEStreamer : public DwarfStreamer {
  DIEBuilder *DIEBldr;
  DWARFRewriter &Rewriter;

private:
  /// Emit the compilation unit header for \p Unit in the debug_info
  /// section.
  ///
  /// A Dwarf 4 section header is encoded as:
  ///  uint32_t   Unit length (omitting this field)
  ///  uint16_t   Version
  ///  uint32_t   Abbreviation table offset
  ///  uint8_t    Address size
  /// Leading to a total of 11 bytes.
  ///
  /// A Dwarf 5 section header is encoded as:
  ///  uint32_t   Unit length (omitting this field)
  ///  uint16_t   Version
  ///  uint8_t    Unit type
  ///  uint8_t    Address size
  ///  uint32_t   Abbreviation table offset
  /// Leading to a total of 12 bytes.
  void emitCompileUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
                             unsigned DwarfVersion) {

    AsmPrinter &Asm = getAsmPrinter();
    switchToDebugInfoSection(DwarfVersion);

    emitCommonHeader(Unit, UnitDIE, DwarfVersion);

    if (DwarfVersion >= 5 &&
        Unit.getUnitType() != dwarf::UnitType::DW_UT_compile) {
      std::optional<uint64_t> DWOId = Unit.getDWOId();
      assert(DWOId &&
             "DWOId does not exist and this is not a DW_UT_compile Unit");
      Asm.emitInt64(*DWOId);
    }
  }

  void emitCommonHeader(DWARFUnit &Unit, DIE &UnitDIE, uint16_t Version) {
    dwarf::UnitType UT = dwarf::UnitType(Unit.getUnitType());
    llvm::AsmPrinter &Asm = getAsmPrinter();

    // Emit size of content not including length itself
    Asm.emitInt32(Unit.getHeaderSize() + UnitDIE.getSize() - 4);
    Asm.emitInt16(Version);

    // DWARF v5 reorders the address size and adds a unit type.
    if (Version >= 5) {
      Asm.emitInt8(UT);
      Asm.emitInt8(Asm.MAI->getCodePointerSize());
    }

    Asm.emitInt32(0);
    if (Version <= 4) {
      Asm.emitInt8(Asm.MAI->getCodePointerSize());
    }
  }

  void emitTypeUnitHeader(DWARFUnit &Unit, DIE &UnitDIE,
                          unsigned DwarfVersion) {
    AsmPrinter &Asm = getAsmPrinter();
    const uint64_t TypeSignature = cast<DWARFTypeUnit>(Unit).getTypeHash();
    DIE *TypeDIE = DIEBldr->getTypeDIE(Unit);
    const DIEBuilder::DWARFUnitInfo &UI = DIEBldr->getUnitInfoByDwarfUnit(Unit);
    Rewriter.addGDBTypeUnitEntry(
        {UI.UnitOffset, TypeSignature, TypeDIE->getOffset()});
    if (Unit.getVersion() < 5) {
      // Switch the section to .debug_types section.
      std::unique_ptr<MCStreamer> &MS = Asm.OutStreamer;
      llvm::MCContext &MC = Asm.OutContext;
      const llvm::MCObjectFileInfo *MOFI = MC.getObjectFileInfo();

      MS->switchSection(MOFI->getDwarfTypesSection(0));
      MC.setDwarfVersion(DwarfVersion);
    } else
      switchToDebugInfoSection(DwarfVersion);

    emitCommonHeader(Unit, UnitDIE, DwarfVersion);
    Asm.OutStreamer->emitIntValue(TypeSignature, sizeof(TypeSignature));
    Asm.emitDwarfLengthOrOffset(TypeDIE ? TypeDIE->getOffset() : 0);
  }

  void emitUnitHeader(DWARFUnit &Unit, DIE &UnitDIE) {
    if (Unit.isTypeUnit())
      emitTypeUnitHeader(Unit, UnitDIE, Unit.getVersion());
    else
      emitCompileUnitHeader(Unit, UnitDIE, Unit.getVersion());
  }

  void emitDIE(DIE &Die) override {
    AsmPrinter &Asm = getAsmPrinter();
    Asm.emitDwarfDIE(Die);
  }

public:
  DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter,
              DWARFLinkerBase::OutputFileType OutFileType,
              raw_pwrite_stream &OutFile,
              DWARFLinkerBase::MessageHandlerTy Warning)
      : DwarfStreamer(OutFileType, OutFile, Warning), DIEBldr(DIEBldr),
        Rewriter(Rewriter){};

  using DwarfStreamer::emitCompileUnitHeader;

  void emitUnit(DWARFUnit &Unit, DIE &UnitDIE) {
    emitUnitHeader(Unit, UnitDIE);
    emitDIE(UnitDIE);
  }
};

/// Finds attributes FormValue and Offset.
///
/// \param DIE die to look up in.
/// \param Attrs finds the first attribute that matches and extracts it.
/// \return an optional AttrInfo with DWARFFormValue and Offset.
std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
                                          std::vector<dwarf::Attribute> Attrs) {
  for (dwarf::Attribute &Attr : Attrs)
    if (std::optional<AttrInfo> Info = findAttributeInfo(DIE, Attr))
      return Info;
  return std::nullopt;
}

} // namespace bolt
} // namespace llvm

using namespace llvm;
using namespace llvm::support::endian;
using namespace object;
using namespace bolt;

namespace opts {

extern cl::OptionCategory BoltCategory;
extern cl::opt<unsigned> Verbosity;
extern cl::opt<std::string> OutputFilename;

static cl::opt<bool> KeepARanges(
    "keep-aranges",
    cl::desc(
        "keep or generate .debug_aranges section if .gdb_index is written"),
    cl::Hidden, cl::cat(BoltCategory));

static cl::opt<bool>
DeterministicDebugInfo("deterministic-debuginfo",
  cl::desc("disables parallel execution of tasks that may produce "
           "nondeterministic debug info"),
  cl::init(true),
  cl::cat(BoltCategory));

static cl::opt<std::string> DwarfOutputPath(
    "dwarf-output-path",
    cl::desc("Path to where .dwo files or dwp file will be written out to."),
    cl::init(""), cl::cat(BoltCategory));

static cl::opt<bool>
    WriteDWP("write-dwp",
             cl::desc("output a single dwarf package file (dwp) instead of "
                      "multiple non-relocatable dwarf object files (dwo)."),
             cl::init(false), cl::cat(BoltCategory));

static cl::opt<bool> CreateDebugNames(
    "create-debug-names-section",
    cl::desc("Creates .debug_names section, if the input binary doesn't have "
             "it already, for DWARF5 CU/TUs."),
    cl::init(false), cl::cat(BoltCategory));

static cl::opt<bool>
    DebugSkeletonCu("debug-skeleton-cu",
                    cl::desc("prints out offsetrs for abbrev and debu_info of "
                             "Skeleton CUs that get patched."),
                    cl::ZeroOrMore, cl::Hidden, cl::init(false),
                    cl::cat(BoltCategory));

static cl::opt<unsigned> BatchSize(
    "cu-processing-batch-size",
    cl::desc(
        "Specifies the size of batches for processing CUs. Higher number has "
        "better performance, but more memory usage. Default value is 1."),
    cl::Hidden, cl::init(1), cl::cat(BoltCategory));

static cl::opt<bool> AlwaysConvertToRanges(
    "always-convert-to-ranges",
    cl::desc("This option is for testing purposes only. It forces BOLT to "
             "convert low_pc/high_pc to ranges always."),
    cl::ReallyHidden, cl::init(false), cl::cat(BoltCategory));

extern cl::opt<std::string> CompDirOverride;
} // namespace opts

/// If DW_AT_low_pc exists sets LowPC and returns true.
static bool getLowPC(const DIE &Die, const DWARFUnit &DU, uint64_t &LowPC,
                     uint64_t &SectionIndex) {
  DIEValue DvalLowPc = Die.findAttribute(dwarf::DW_AT_low_pc);
  if (!DvalLowPc)
    return false;

  dwarf::Form Form = DvalLowPc.getForm();
  bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
  uint64_t LowPcValue = DvalLowPc.getDIEInteger().getValue();
  if (Form == dwarf::DW_FORM_GNU_addr_index || Form == dwarf::DW_FORM_addrx ||
      AddrOffset) {

    uint32_t Index = AddrOffset ? (LowPcValue >> 32) : LowPcValue;
    std::optional<object::SectionedAddress> SA =
        DU.getAddrOffsetSectionItem(Index);
    if (!SA)
      return false;
    if (AddrOffset)
      SA->Address += (LowPcValue & 0xffffffff);

    LowPC = SA->Address;
    SectionIndex = SA->SectionIndex;
  } else {
    LowPC = LowPcValue;
    SectionIndex = 0;
  }
  return true;
}

/// If DW_AT_high_pc exists sets HighPC and returns true.
static bool getHighPC(const DIE &Die, const uint64_t LowPC, uint64_t &HighPC) {
  DIEValue DvalHighPc = Die.findAttribute(dwarf::DW_AT_high_pc);
  if (!DvalHighPc)
    return false;
  if (DvalHighPc.getForm() == dwarf::DW_FORM_addr)
    HighPC = DvalHighPc.getDIEInteger().getValue();
  else
    HighPC = LowPC + DvalHighPc.getDIEInteger().getValue();
  return true;
}

/// If DW_AT_low_pc and DW_AT_high_pc exist sets LowPC and HighPC and returns
/// true.
static bool getLowAndHighPC(const DIE &Die, const DWARFUnit &DU,
                            uint64_t &LowPC, uint64_t &HighPC,
                            uint64_t &SectionIndex) {
  uint64_t TempLowPC = LowPC;
  uint64_t TempHighPC = HighPC;
  uint64_t TempSectionIndex = SectionIndex;
  if (getLowPC(Die, DU, TempLowPC, TempSectionIndex) &&
      getHighPC(Die, TempLowPC, TempHighPC)) {
    LowPC = TempLowPC;
    HighPC = TempHighPC;
    SectionIndex = TempSectionIndex;
    return true;
  }
  return false;
}

static Expected<llvm::DWARFAddressRangesVector>
getDIEAddressRanges(const DIE &Die, DWARFUnit &DU) {
  uint64_t LowPC, HighPC, Index;
  if (getLowAndHighPC(Die, DU, LowPC, HighPC, Index))
    return DWARFAddressRangesVector{{LowPC, HighPC, Index}};
  if (DIEValue Dval = Die.findAttribute(dwarf::DW_AT_ranges)) {
    if (Dval.getForm() == dwarf::DW_FORM_rnglistx)
      return DU.findRnglistFromIndex(Dval.getDIEInteger().getValue());

    return DU.findRnglistFromOffset(Dval.getDIEInteger().getValue());
  }

  return DWARFAddressRangesVector();
}

static std::optional<uint64_t> getAsAddress(const DWARFUnit &DU,
                                            const DIEValue &AttrVal) {
  DWARFFormValue::ValueType Value(AttrVal.getDIEInteger().getValue());
  if (std::optional<object::SectionedAddress> SA =
          DWARFFormValue::getAsSectionedAddress(Value, AttrVal.getForm(), &DU))
    return SA->Address;
  return std::nullopt;
}

/// Returns DWO Name to be used. Handles case where user specifies output DWO
/// directory, and there are duplicate names. Assumes DWO ID is unique.
static std::string
getDWOName(llvm::DWARFUnit &CU,
           std::unordered_map<std::string, uint32_t> &NameToIndexMap) {
  std::optional<uint64_t> DWOId = CU.getDWOId();
  assert(DWOId && "DWO ID not found.");
  (void)DWOId;

  std::string DWOName = dwarf::toString(
      CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
      "");
  assert(!DWOName.empty() &&
         "DW_AT_dwo_name/DW_AT_GNU_dwo_name does not exists.");
  if (!opts::DwarfOutputPath.empty()) {
    DWOName = std::string(sys::path::filename(DWOName));
    auto Iter = NameToIndexMap.find(DWOName);
    if (Iter == NameToIndexMap.end())
      Iter = NameToIndexMap.insert({DWOName, 0}).first;
    DWOName.append(std::to_string(Iter->second));
    ++Iter->second;
  }
  DWOName.append(".dwo");
  return DWOName;
}

static std::unique_ptr<DIEStreamer>
createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
                  StringRef Swift5ReflectionSegmentName, DIEBuilder &DIEBldr,
                  DWARFRewriter &Rewriter) {

  std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
      &DIEBldr, Rewriter, DWARFLinkerBase::OutputFileType::Object, OutFile,
      [&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
  Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);
  if (Err)
    errs()
        << "BOLT-WARNING: [internal-dwarf-error]: Could not init DIEStreamer!"
        << toString(std::move(Err)) << "\n";
  return Streamer;
}

static DWARFRewriter::UnitMeta
emitUnit(DIEBuilder &DIEBldr, DIEStreamer &Streamer, DWARFUnit &Unit) {
  DIE *UnitDIE = DIEBldr.getUnitDIEbyUnit(Unit);
  const DIEBuilder::DWARFUnitInfo &U = DIEBldr.getUnitInfoByDwarfUnit(Unit);
  Streamer.emitUnit(Unit, *UnitDIE);
  uint64_t TypeHash = 0;
  if (DWARFTypeUnit *DTU = dyn_cast_or_null<DWARFTypeUnit>(&Unit))
    TypeHash = DTU->getTypeHash();
  return {U.UnitOffset, U.UnitLength, TypeHash};
}

static void emitDWOBuilder(const std::string &DWOName,
                           DIEBuilder &DWODIEBuilder, DWARFRewriter &Rewriter,
                           DWARFUnit &SplitCU, DWARFUnit &CU,
                           DWARFRewriter::DWPState &State,
                           DebugLocWriter &LocWriter) {
  // Populate debug_info and debug_abbrev for current dwo into StringRef.
  DWODIEBuilder.generateAbbrevs();
  DWODIEBuilder.finish();

  SmallVector<char, 20> OutBuffer;
  std::shared_ptr<raw_svector_ostream> ObjOS =
      std::make_shared<raw_svector_ostream>(OutBuffer);
  const object::ObjectFile *File = SplitCU.getContext().getDWARFObj().getFile();
  auto TheTriple = std::make_unique<Triple>(File->makeTriple());
  std::unique_ptr<DIEStreamer> Streamer = createDIEStreamer(
      *TheTriple, *ObjOS, "DwoStreamerInitAug2", DWODIEBuilder, Rewriter);
  DWARFRewriter::UnitMetaVectorType TUMetaVector;
  DWARFRewriter::UnitMeta CUMI = {0, 0, 0};
  if (SplitCU.getContext().getMaxDWOVersion() >= 5) {
    for (std::unique_ptr<llvm::DWARFUnit> &CU :
         SplitCU.getContext().dwo_info_section_units()) {
      if (!CU->isTypeUnit())
        continue;
      DWARFRewriter::UnitMeta MI =
          emitUnit(DWODIEBuilder, *Streamer, *CU.get());
      TUMetaVector.emplace_back(MI);
    }
    CUMI = emitUnit(DWODIEBuilder, *Streamer, SplitCU);
  } else {
    for (std::unique_ptr<llvm::DWARFUnit> &CU :
         SplitCU.getContext().dwo_compile_units())
      emitUnit(DWODIEBuilder, *Streamer, *CU.get());

    // emit debug_types sections for dwarf4
    for (DWARFUnit *CU : DWODIEBuilder.getDWARF4TUVector()) {
      DWARFRewriter::UnitMeta MI = emitUnit(DWODIEBuilder, *Streamer, *CU);
      TUMetaVector.emplace_back(MI);
    }
  }

  Streamer->emitAbbrevs(DWODIEBuilder.getAbbrevs(),
                        SplitCU.getContext().getMaxVersion());
  Streamer->finish();

  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
      MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
  std::unique_ptr<object::ObjectFile> Obj = cantFail(
      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
      "error creating in-memory object");

  DWARFRewriter::OverriddenSectionsMap OverriddenSections;
  for (const SectionRef &Secs : Obj->sections()) {
    StringRef Contents = cantFail(Secs.getContents());
    StringRef Name = cantFail(Secs.getName());
    DWARFSectionKind Kind =
        StringSwitch<DWARFSectionKind>(Name)
            .Case(".debug_abbrev", DWARFSectionKind::DW_SECT_ABBREV)
            .Case(".debug_info", DWARFSectionKind::DW_SECT_INFO)
            .Case(".debug_types", DWARFSectionKind::DW_SECT_EXT_TYPES)
            .Default(DWARFSectionKind::DW_SECT_EXT_unknown);
    if (Kind == DWARFSectionKind::DW_SECT_EXT_unknown)
      continue;
    OverriddenSections[Kind] = Contents;
  }
  if (opts::WriteDWP)
    Rewriter.updateDWP(CU, OverriddenSections, CUMI, TUMetaVector, State,
                       LocWriter);
  else
    Rewriter.writeDWOFiles(CU, OverriddenSections, DWOName, LocWriter);
}

void DWARFRewriter::addStringHelper(DIEBuilder &DIEBldr, DIE &Die,
                                    const DWARFUnit &Unit,
                                    DIEValue &DIEAttrInfo, StringRef Str) {
  uint32_t NewOffset = StrWriter->addString(Str);
  if (Unit.getVersion() >= 5) {
    StrOffstsWriter->updateAddressMap(DIEAttrInfo.getDIEInteger().getValue(),
                                      NewOffset);
    return;
  }
  DIEBldr.replaceValue(&Die, DIEAttrInfo.getAttribute(), DIEAttrInfo.getForm(),
                       DIEInteger(NewOffset));
}

using DWARFUnitVec = std::vector<DWARFUnit *>;
using CUPartitionVector = std::vector<DWARFUnitVec>;
/// Partitions CUs in to buckets. Bucket size is controlled by
/// cu-processing-batch-size. All the CUs that have cross CU reference reference
/// as a source are put in to the same initial bucket.
static CUPartitionVector partitionCUs(DWARFContext &DwCtx) {
  CUPartitionVector Vec(2);
  unsigned Counter = 0;
  const DWARFDebugAbbrev *Abbr = DwCtx.getDebugAbbrev();
  for (std::unique_ptr<DWARFUnit> &CU : DwCtx.compile_units()) {
    Expected<const DWARFAbbreviationDeclarationSet *> AbbrDeclSet =
        Abbr->getAbbreviationDeclarationSet(CU->getAbbreviationsOffset());
    if (!AbbrDeclSet) {
      consumeError(AbbrDeclSet.takeError());
      return Vec;
    }
    bool CrossCURefFound = false;
    for (const DWARFAbbreviationDeclaration &Decl : *AbbrDeclSet.get()) {
      for (const DWARFAbbreviationDeclaration::AttributeSpec &Attr :
           Decl.attributes()) {
        if (Attr.Form == dwarf::DW_FORM_ref_addr) {
          CrossCURefFound = true;
          break;
        }
      }
      if (CrossCURefFound)
        break;
    }
    if (CrossCURefFound) {
      Vec[0].push_back(CU.get());
    } else {
      ++Counter;
      Vec.back().push_back(CU.get());
    }
    if (Counter % opts::BatchSize == 0 && !Vec.back().empty())
      Vec.push_back({});
  }
  return Vec;
}

void DWARFRewriter::updateDebugInfo() {
  ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
  if (!DebugInfo)
    return;

  ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
  StrWriter = std::make_unique<DebugStrWriter>(BC);

  StrOffstsWriter = std::make_unique<DebugStrOffsetsWriter>();

  if (!opts::DeterministicDebugInfo) {
    opts::DeterministicDebugInfo = true;
    errs() << "BOLT-WARNING: --deterministic-debuginfo is being deprecated\n";
  }

  if (BC.isDWARF5Used()) {
    AddrWriter = std::make_unique<DebugAddrWriterDwarf5>(&BC);
    RangeListsSectionWriter = std::make_unique<DebugRangeListsSectionWriter>();
    DebugRangeListsSectionWriter::setAddressWriter(AddrWriter.get());
  } else {
    AddrWriter = std::make_unique<DebugAddrWriter>(&BC);
  }

  if (BC.isDWARFLegacyUsed())
    LegacyRangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();

  DebugLoclistWriter::setAddressWriter(AddrWriter.get());

  uint32_t CUIndex = 0;
  std::mutex AccessMutex;
  // Needs to be invoked in the same order as CUs are processed.
  auto createRangeLocList = [&](DWARFUnit &CU) -> DebugLocWriter * {
    std::lock_guard<std::mutex> Lock(AccessMutex);
    const uint16_t DwarfVersion = CU.getVersion();
    if (DwarfVersion >= 5) {
      LocListWritersByCU[CUIndex] =
          std::make_unique<DebugLoclistWriter>(CU, DwarfVersion, false);

      if (std::optional<uint64_t> DWOId = CU.getDWOId()) {
        assert(RangeListsWritersByCU.count(*DWOId) == 0 &&
               "RangeLists writer for DWO unit already exists.");
        auto RangeListsSectionWriter =
            std::make_unique<DebugRangeListsSectionWriter>();
        RangeListsSectionWriter->initSection(CU);
        RangeListsWritersByCU[*DWOId] = std::move(RangeListsSectionWriter);
      }

    } else {
      LocListWritersByCU[CUIndex] = std::make_unique<DebugLocWriter>();
    }
    return LocListWritersByCU[CUIndex++].get();
  };

  // Unordered maps to handle name collision if output DWO directory is
  // specified.
  std::unordered_map<std::string, uint32_t> NameToIndexMap;

  auto updateDWONameCompDir = [&](DWARFUnit &Unit, DIEBuilder &DIEBldr,
                                  DIE &UnitDIE) -> std::string {
    DIEValue DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_dwo_name);
    if (!DWONameAttrInfo)
      DWONameAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_GNU_dwo_name);
    assert(DWONameAttrInfo && "DW_AT_dwo_name is not in Skeleton CU.");
    std::string ObjectName;

    {
      std::lock_guard<std::mutex> Lock(AccessMutex);
      ObjectName = getDWOName(Unit, NameToIndexMap);
    }
    addStringHelper(DIEBldr, UnitDIE, Unit, DWONameAttrInfo,
                    ObjectName.c_str());

    DIEValue CompDirAttrInfo = UnitDIE.findAttribute(dwarf::DW_AT_comp_dir);
    assert(CompDirAttrInfo && "DW_AT_comp_dir is not in Skeleton CU.");

    if (!opts::DwarfOutputPath.empty()) {
      if (!sys::fs::exists(opts::DwarfOutputPath))
        sys::fs::create_directory(opts::DwarfOutputPath);
      addStringHelper(DIEBldr, UnitDIE, Unit, CompDirAttrInfo,
                      opts::DwarfOutputPath.c_str());
    }
    return ObjectName;
  };

  DWARF5AcceleratorTable DebugNamesTable(opts::CreateDebugNames, BC,
                                         *StrWriter);
  DWPState State;
  if (opts::WriteDWP)
    initDWPState(State);
  auto processUnitDIE = [&](DWARFUnit *Unit, DIEBuilder *DIEBlder) {
    // Check if the unit is a skeleton and we need special updates for it and
    // its matching split/DWO CU.
    std::optional<DWARFUnit *> SplitCU;
    std::optional<uint64_t> RangesBase;
    std::optional<uint64_t> DWOId = Unit->getDWOId();
    if (DWOId)
      SplitCU = BC.getDWOCU(*DWOId);
    DebugLocWriter *DebugLocWriter = createRangeLocList(*Unit);
    DebugRangesSectionWriter *RangesSectionWriter =
        Unit->getVersion() >= 5 ? RangeListsSectionWriter.get()
                                : LegacyRangesSectionWriter.get();
    // Skipping CUs that failed to load.
    if (SplitCU) {
      DIEBuilder DWODIEBuilder(BC, &(*SplitCU)->getContext(), DebugNamesTable,
                               Unit);
      DWODIEBuilder.buildDWOUnit(**SplitCU);
      std::string DWOName = updateDWONameCompDir(
          *Unit, *DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));

      DebugLoclistWriter DebugLocDWoWriter(*Unit, Unit->getVersion(), true);
      DebugRangesSectionWriter *TempRangesSectionWriter = RangesSectionWriter;
      if (Unit->getVersion() >= 5) {
        TempRangesSectionWriter = RangeListsWritersByCU[*DWOId].get();
      } else {
        RangesBase = RangesSectionWriter->getSectionOffset();
        setDwoRangesBase(*DWOId, *RangesBase);
      }

      updateUnitDebugInfo(*(*SplitCU), DWODIEBuilder, DebugLocDWoWriter,
                          *TempRangesSectionWriter);
      DebugLocDWoWriter.finalize(DWODIEBuilder,
                                 *DWODIEBuilder.getUnitDIEbyUnit(**SplitCU));
      if (Unit->getVersion() >= 5)
        TempRangesSectionWriter->finalizeSection();

      emitDWOBuilder(DWOName, DWODIEBuilder, *this, **SplitCU, *Unit, State,
                     DebugLocDWoWriter);
    }

    if (Unit->getVersion() >= 5) {
      RangesBase = RangesSectionWriter->getSectionOffset() +
                   getDWARF5RngListLocListHeaderSize();
      RangesSectionWriter->initSection(*Unit);
      StrOffstsWriter->finalizeSection(*Unit, *DIEBlder);
    }

    updateUnitDebugInfo(*Unit, *DIEBlder, *DebugLocWriter, *RangesSectionWriter,
                        RangesBase);
    DebugLocWriter->finalize(*DIEBlder, *DIEBlder->getUnitDIEbyUnit(*Unit));
    if (Unit->getVersion() >= 5)
      RangesSectionWriter->finalizeSection();
    AddrWriter->update(*DIEBlder, *Unit);
  };

  DIEBuilder DIEBlder(BC, BC.DwCtx.get(), DebugNamesTable);
  DIEBlder.buildTypeUnits(StrOffstsWriter.get());
  SmallVector<char, 20> OutBuffer;
  std::unique_ptr<raw_svector_ostream> ObjOS =
      std::make_unique<raw_svector_ostream>(OutBuffer);
  const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
  auto TheTriple = std::make_unique<Triple>(File->makeTriple());
  std::unique_ptr<DIEStreamer> Streamer =
      createDIEStreamer(*TheTriple, *ObjOS, "TypeStreamer", DIEBlder, *this);
  CUOffsetMap OffsetMap = finalizeTypeSections(DIEBlder, *Streamer);

  const bool SingleThreadedMode =
      opts::NoThreads || opts::DeterministicDebugInfo;
  if (!SingleThreadedMode)
    DIEBlder.buildCompileUnits();
  if (SingleThreadedMode) {
    CUPartitionVector PartVec = partitionCUs(*BC.DwCtx);
    for (std::vector<DWARFUnit *> &Vec : PartVec) {
      DIEBlder.buildCompileUnits(Vec);
      for (DWARFUnit *CU : DIEBlder.getProcessedCUs())
        processUnitDIE(CU, &DIEBlder);
      finalizeCompileUnits(DIEBlder, *Streamer, OffsetMap,
                           DIEBlder.getProcessedCUs());
    }
  } else {
    // Update unit debug info in parallel
    ThreadPoolInterface &ThreadPool = ParallelUtilities::getThreadPool();
    for (std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units())
      ThreadPool.async(processUnitDIE, CU.get(), &DIEBlder);
    ThreadPool.wait();
  }

  DebugNamesTable.emitAccelTable();

  if (opts::WriteDWP)
    finalizeDWP(State);

  finalizeDebugSections(DIEBlder, DebugNamesTable, *Streamer, *ObjOS,
                        OffsetMap);
  updateGdbIndexSection(OffsetMap, CUIndex);
}

void DWARFRewriter::updateUnitDebugInfo(
    DWARFUnit &Unit, DIEBuilder &DIEBldr, DebugLocWriter &DebugLocWriter,
    DebugRangesSectionWriter &RangesSectionWriter,
    std::optional<uint64_t> RangesBase) {
  // Cache debug ranges so that the offset for identical ranges could be reused.
  std::map<DebugAddressRangesVector, uint64_t> CachedRanges;

  uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize();
  uint64_t NextCUOffset = Unit.getNextUnitOffset();
  const std::vector<std::unique_ptr<DIEBuilder::DIEInfo>> &DIs =
      DIEBldr.getDIEsByUnit(Unit);

  // Either updates or normalizes DW_AT_range to DW_AT_low_pc and DW_AT_high_pc.
  auto updateLowPCHighPC = [&](DIE *Die, const DIEValue &LowPCVal,
                               const DIEValue &HighPCVal, uint64_t LowPC,
                               const uint64_t HighPC) {
    dwarf::Attribute AttrLowPC = dwarf::DW_AT_low_pc;
    dwarf::Form FormLowPC = dwarf::DW_FORM_addr;
    dwarf::Attribute AttrHighPC = dwarf::DW_AT_high_pc;
    dwarf::Form FormHighPC = dwarf::DW_FORM_data4;
    const uint32_t Size = HighPC - LowPC;
    // Whatever was generated is not low_pc/high_pc, so will reset to
    // default for size 1.
    if (!LowPCVal || !HighPCVal) {
      if (Unit.getVersion() >= 5)
        FormLowPC = dwarf::DW_FORM_addrx;
      else if (Unit.isDWOUnit())
        FormLowPC = dwarf::DW_FORM_GNU_addr_index;
    } else {
      AttrLowPC = LowPCVal.getAttribute();
      FormLowPC = LowPCVal.getForm();
      AttrHighPC = HighPCVal.getAttribute();
      FormHighPC = HighPCVal.getForm();
    }

    if (FormLowPC == dwarf::DW_FORM_addrx ||
        FormLowPC == dwarf::DW_FORM_GNU_addr_index)
      LowPC = AddrWriter->getIndexFromAddress(LowPC, Unit);

    if (LowPCVal)
      DIEBldr.replaceValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
    else
      DIEBldr.addValue(Die, AttrLowPC, FormLowPC, DIEInteger(LowPC));
    if (HighPCVal) {
      DIEBldr.replaceValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
    } else {
      DIEBldr.deleteValue(Die, dwarf::DW_AT_ranges);
      DIEBldr.addValue(Die, AttrHighPC, FormHighPC, DIEInteger(Size));
    }
  };

  for (const std::unique_ptr<DIEBuilder::DIEInfo> &DI : DIs) {
    DIE *Die = DI->Die;
    switch (Die->getTag()) {
    case dwarf::DW_TAG_compile_unit:
    case dwarf::DW_TAG_skeleton_unit: {
      // For dwarf5 section 3.1.3
      // The following attributes are not part of a split full compilation unit
      // entry but instead are inherited (if present) from the corresponding
      // skeleton compilation unit: DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges,
      // DW_AT_stmt_list, DW_AT_comp_dir, DW_AT_str_offsets_base,
      // DW_AT_addr_base and DW_AT_rnglists_base.
      if (Unit.getVersion() == 5 && Unit.isDWOUnit())
        continue;
      auto ModuleRangesOrError = getDIEAddressRanges(*Die, Unit);
      if (!ModuleRangesOrError) {
        consumeError(ModuleRangesOrError.takeError());
        break;
      }
      DWARFAddressRangesVector &ModuleRanges = *ModuleRangesOrError;
      DebugAddressRangesVector OutputRanges =
          BC.translateModuleAddressRanges(ModuleRanges);
      DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
      // For a case where LLD GCs only function used in the CU.
      // If CU doesn't have DW_AT_low_pc we are not going to convert,
      // so don't need to do anything.
      if (OutputRanges.empty() && !Unit.isDWOUnit() && LowPCAttrInfo)
        OutputRanges.push_back({0, 0});
      const uint64_t RangesSectionOffset =
          RangesSectionWriter.addRanges(OutputRanges);
      // Don't emit the zero low_pc arange.
      if (!Unit.isDWOUnit() && !OutputRanges.empty() &&
          OutputRanges.back().LowPC)
        ARangesSectionWriter->addCURanges(Unit.getOffset(),
                                          std::move(OutputRanges));
      updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset,
                                     RangesBase);
      DIEValue StmtListAttrVal = Die->findAttribute(dwarf::DW_AT_stmt_list);
      if (LineTablePatchMap.count(&Unit))
        DIEBldr.replaceValue(Die, dwarf::DW_AT_stmt_list,
                             StmtListAttrVal.getForm(),
                             DIEInteger(LineTablePatchMap[&Unit]));
      break;
    }

    case dwarf::DW_TAG_subprogram: {
      // Get function address either from ranges or [LowPC, HighPC) pair.
      uint64_t Address = UINT64_MAX;
      uint64_t SectionIndex, HighPC;
      DebugAddressRangesVector FunctionRanges;
      if (!getLowAndHighPC(*Die, Unit, Address, HighPC, SectionIndex)) {
        Expected<DWARFAddressRangesVector> RangesOrError =
            getDIEAddressRanges(*Die, Unit);
        if (!RangesOrError) {
          consumeError(RangesOrError.takeError());
          break;
        }
        DWARFAddressRangesVector Ranges = *RangesOrError;
        // Not a function definition.
        if (Ranges.empty())
          break;

        for (const DWARFAddressRange &Range : Ranges) {
          if (const BinaryFunction *Function =
                  BC.getBinaryFunctionAtAddress(Range.LowPC))
            FunctionRanges.append(Function->getOutputAddressRanges());
        }
      } else {
        if (const BinaryFunction *Function =
                BC.getBinaryFunctionAtAddress(Address))
          FunctionRanges = Function->getOutputAddressRanges();
      }

      // Clear cached ranges as the new function will have its own set.
      CachedRanges.clear();
      DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
      DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
      if (FunctionRanges.empty()) {
        if (LowPCVal && HighPCVal)
          FunctionRanges.push_back({0, HighPCVal.getDIEInteger().getValue()});
        else
          FunctionRanges.push_back({0, 1});
      }

      if (FunctionRanges.size() == 1 && !opts::AlwaysConvertToRanges) {
        updateLowPCHighPC(Die, LowPCVal, HighPCVal, FunctionRanges.back().LowPC,
                          FunctionRanges.back().HighPC);
        break;
      }

      updateDWARFObjectAddressRanges(
          Unit, DIEBldr, *Die, RangesSectionWriter.addRanges(FunctionRanges));

      break;
    }
    case dwarf::DW_TAG_lexical_block:
    case dwarf::DW_TAG_inlined_subroutine:
    case dwarf::DW_TAG_try_block:
    case dwarf::DW_TAG_catch_block: {
      uint64_t RangesSectionOffset = 0;
      Expected<DWARFAddressRangesVector> RangesOrError =
          getDIEAddressRanges(*Die, Unit);
      const BinaryFunction *Function =
          RangesOrError && !RangesOrError->empty()
              ? BC.getBinaryFunctionContainingAddress(
                    RangesOrError->front().LowPC)
              : nullptr;
      DebugAddressRangesVector OutputRanges;
      if (Function) {
        OutputRanges = translateInputToOutputRanges(*Function, *RangesOrError);
        LLVM_DEBUG(if (OutputRanges.empty() != RangesOrError->empty()) {
          dbgs() << "BOLT-DEBUG: problem with DIE at 0x"
                 << Twine::utohexstr(Die->getOffset()) << " in CU at 0x"
                 << Twine::utohexstr(Unit.getOffset()) << '\n';
        });
        if (opts::AlwaysConvertToRanges || OutputRanges.size() > 1) {
          RangesSectionOffset = RangesSectionWriter.addRanges(
              std::move(OutputRanges), CachedRanges);
          OutputRanges.clear();
        } else if (OutputRanges.empty()) {
          OutputRanges.push_back({0, RangesOrError.get().front().HighPC});
        }
      } else if (!RangesOrError) {
        consumeError(RangesOrError.takeError());
      } else {
        OutputRanges.push_back({0, !RangesOrError->empty()
                                       ? RangesOrError.get().front().HighPC
                                       : 0});
      }
      DIEValue LowPCVal = Die->findAttribute(dwarf::DW_AT_low_pc);
      DIEValue HighPCVal = Die->findAttribute(dwarf::DW_AT_high_pc);
      if (OutputRanges.size() == 1) {
        updateLowPCHighPC(Die, LowPCVal, HighPCVal, OutputRanges.back().LowPC,
                          OutputRanges.back().HighPC);
        break;
      }
      updateDWARFObjectAddressRanges(Unit, DIEBldr, *Die, RangesSectionOffset);
      break;
    }
    case dwarf::DW_TAG_call_site: {
      auto patchPC = [&](DIE *Die, DIEValue &AttrVal, StringRef Entry) -> void {
        std::optional<uint64_t> Address = getAsAddress(Unit, AttrVal);
        const BinaryFunction *Function =
            BC.getBinaryFunctionContainingAddress(*Address);
        uint64_t UpdatedAddress = *Address;
        if (Function)
          UpdatedAddress =
              Function->translateInputToOutputAddress(UpdatedAddress);

        if (AttrVal.getForm() == dwarf::DW_FORM_addrx) {
          const uint32_t Index =
              AddrWriter->getIndexFromAddress(UpdatedAddress, Unit);
          DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
                               DIEInteger(Index));
        } else if (AttrVal.getForm() == dwarf::DW_FORM_addr) {
          DIEBldr.replaceValue(Die, AttrVal.getAttribute(), AttrVal.getForm(),
                               DIEInteger(UpdatedAddress));
        } else {
          errs() << "BOLT-ERROR: unsupported form for " << Entry << "\n";
        }
      };
      DIEValue CallPcAttrVal = Die->findAttribute(dwarf::DW_AT_call_pc);
      if (CallPcAttrVal)
        patchPC(Die, CallPcAttrVal, "DW_AT_call_pc");

      DIEValue CallRetPcAttrVal =
          Die->findAttribute(dwarf::DW_AT_call_return_pc);
      if (CallRetPcAttrVal)
        patchPC(Die, CallRetPcAttrVal, "DW_AT_call_return_pc");

      break;
    }
    default: {
      // Handle any tag that can have DW_AT_location attribute.
      DIEValue LocAttrInfo = Die->findAttribute(dwarf::DW_AT_location);
      DIEValue LowPCAttrInfo = Die->findAttribute(dwarf::DW_AT_low_pc);
      if (LocAttrInfo) {
        if (doesFormBelongToClass(LocAttrInfo.getForm(),
                                  DWARFFormValue::FC_Constant,
                                  Unit.getVersion()) ||
            doesFormBelongToClass(LocAttrInfo.getForm(),
                                  DWARFFormValue::FC_SectionOffset,
                                  Unit.getVersion())) {
          uint64_t Offset = LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx
                                ? LocAttrInfo.getDIELocList().getValue()
                                : LocAttrInfo.getDIEInteger().getValue();
          DebugLocationsVector InputLL;

          std::optional<object::SectionedAddress> SectionAddress =
              Unit.getBaseAddress();
          uint64_t BaseAddress = 0;
          if (SectionAddress)
            BaseAddress = SectionAddress->Address;

          if (Unit.getVersion() >= 5 &&
              LocAttrInfo.getForm() == dwarf::DW_FORM_loclistx) {
            std::optional<uint64_t> LocOffset = Unit.getLoclistOffset(Offset);
            assert(LocOffset && "Location Offset is invalid.");
            Offset = *LocOffset;
          }

          Error E = Unit.getLocationTable().visitLocationList(
              &Offset, [&](const DWARFLocationEntry &Entry) {
                switch (Entry.Kind) {
                default:
                  llvm_unreachable("Unsupported DWARFLocationEntry Kind.");
                case dwarf::DW_LLE_end_of_list:
                  return false;
                case dwarf::DW_LLE_base_address: {
                  assert(Entry.SectionIndex == SectionedAddress::UndefSection &&
                         "absolute address expected");
                  BaseAddress = Entry.Value0;
                  break;
                }
                case dwarf::DW_LLE_offset_pair:
                  assert(
                      (Entry.SectionIndex == SectionedAddress::UndefSection &&
                       (!Unit.isDWOUnit() || Unit.getVersion() == 5)) &&
                      "absolute address expected");
                  InputLL.emplace_back(DebugLocationEntry{
                      BaseAddress + Entry.Value0, BaseAddress + Entry.Value1,
                      Entry.Loc});
                  break;
                case dwarf::DW_LLE_start_length:
                  InputLL.emplace_back(DebugLocationEntry{
                      Entry.Value0, Entry.Value0 + Entry.Value1, Entry.Loc});
                  break;
                case dwarf::DW_LLE_base_addressx: {
                  std::optional<object::SectionedAddress> EntryAddress =
                      Unit.getAddrOffsetSectionItem(Entry.Value0);
                  assert(EntryAddress && "base Address not found.");
                  BaseAddress = EntryAddress->Address;
                  break;
                }
                case dwarf::DW_LLE_startx_length: {
                  std::optional<object::SectionedAddress> EntryAddress =
                      Unit.getAddrOffsetSectionItem(Entry.Value0);
                  assert(EntryAddress && "Address does not exist.");
                  InputLL.emplace_back(DebugLocationEntry{
                      EntryAddress->Address,
                      EntryAddress->Address + Entry.Value1, Entry.Loc});
                  break;
                }
                case dwarf::DW_LLE_startx_endx: {
                  std::optional<object::SectionedAddress> StartAddress =
                      Unit.getAddrOffsetSectionItem(Entry.Value0);
                  assert(StartAddress && "Start Address does not exist.");
                  std::optional<object::SectionedAddress> EndAddress =
                      Unit.getAddrOffsetSectionItem(Entry.Value1);
                  assert(EndAddress && "Start Address does not exist.");
                  InputLL.emplace_back(DebugLocationEntry{
                      StartAddress->Address, EndAddress->Address, Entry.Loc});
                  break;
                }
                }
                return true;
              });

          if (E || InputLL.empty()) {
            consumeError(std::move(E));
            errs() << "BOLT-WARNING: empty location list detected at 0x"
                   << Twine::utohexstr(Offset) << " for DIE at 0x" << Die
                   << " in CU at 0x" << Twine::utohexstr(Unit.getOffset())
                   << '\n';
          } else {
            const uint64_t Address = InputLL.front().LowPC;
            DebugLocationsVector OutputLL;
            if (const BinaryFunction *Function =
                    BC.getBinaryFunctionContainingAddress(Address)) {
              OutputLL = translateInputToOutputLocationList(*Function, InputLL);
              LLVM_DEBUG(if (OutputLL.empty()) {
                dbgs() << "BOLT-DEBUG: location list translated to an empty "
                          "one at 0x"
                       << Die << " in CU at 0x"
                       << Twine::utohexstr(Unit.getOffset()) << '\n';
              });
            } else {
              // It's possible for a subprogram to be removed and to have
              // address of 0. Adding this entry to output to preserve debug
              // information.
              OutputLL = InputLL;
            }
            DebugLocWriter.addList(DIEBldr, *Die, LocAttrInfo, OutputLL);
          }
        } else {
          assert((doesFormBelongToClass(LocAttrInfo.getForm(),
                                        DWARFFormValue::FC_Exprloc,
                                        Unit.getVersion()) ||
                  doesFormBelongToClass(LocAttrInfo.getForm(),
                                        DWARFFormValue::FC_Block,
                                        Unit.getVersion())) &&
                 "unexpected DW_AT_location form");
          if (Unit.isDWOUnit() || Unit.getVersion() >= 5) {
            std::vector<uint8_t> Sblock;
            DIEValueList *AttrLocValList;
            if (doesFormBelongToClass(LocAttrInfo.getForm(),
                                      DWARFFormValue::FC_Exprloc,
                                      Unit.getVersion())) {
              for (const DIEValue &Val : LocAttrInfo.getDIELoc().values()) {
                Sblock.push_back(Val.getDIEInteger().getValue());
              }
              DIELoc *LocAttr = const_cast<DIELoc *>(&LocAttrInfo.getDIELoc());
              AttrLocValList = static_cast<DIEValueList *>(LocAttr);
            } else {
              for (const DIEValue &Val : LocAttrInfo.getDIEBlock().values()) {
                Sblock.push_back(Val.getDIEInteger().getValue());
              }
              DIEBlock *BlockAttr =
                  const_cast<DIEBlock *>(&LocAttrInfo.getDIEBlock());
              AttrLocValList = static_cast<DIEValueList *>(BlockAttr);
            }
            ArrayRef<uint8_t> Expr = ArrayRef<uint8_t>(Sblock);
            DataExtractor Data(
                StringRef((const char *)Expr.data(), Expr.size()),
                Unit.getContext().isLittleEndian(), 0);
            DWARFExpression LocExpr(Data, Unit.getAddressByteSize(),
                                    Unit.getFormParams().Format);
            uint32_t PrevOffset = 0;
            DIEValueList *NewAttr;
            DIEValue Value;
            uint32_t NewExprSize = 0;
            DIELoc *Loc = nullptr;
            DIEBlock *Block = nullptr;
            if (LocAttrInfo.getForm() == dwarf::DW_FORM_exprloc) {
              Loc = DIEBldr.allocateDIEValue<DIELoc>();
              NewAttr = Loc;
              Value = DIEValue(LocAttrInfo.getAttribute(),
                               LocAttrInfo.getForm(), Loc);
            } else if (doesFormBelongToClass(LocAttrInfo.getForm(),
                                             DWARFFormValue::FC_Block,
                                             Unit.getVersion())) {
              Block = DIEBldr.allocateDIEValue<DIEBlock>();
              NewAttr = Block;
              Value = DIEValue(LocAttrInfo.getAttribute(),
                               LocAttrInfo.getForm(), Block);
            } else {
              errs() << "BOLT-WARNING: Unexpected Form value in Updating "
                        "DW_AT_Location\n";
              continue;
            }

            for (const DWARFExpression::Operation &Expr : LocExpr) {
              uint32_t CurEndOffset = PrevOffset + 1;
              if (Expr.getDescription().Op.size() == 1)
                CurEndOffset = Expr.getOperandEndOffset(0);
              if (Expr.getDescription().Op.size() == 2)
                CurEndOffset = Expr.getOperandEndOffset(1);
              if (Expr.getDescription().Op.size() > 2)
                errs() << "BOLT-WARNING: [internal-dwarf-error]: Unsupported "
                          "number of operands.\n";
              // not addr index, just copy.
              if (!(Expr.getCode() == dwarf::DW_OP_GNU_addr_index ||
                    Expr.getCode() == dwarf::DW_OP_addrx)) {
                auto Itr = AttrLocValList->values().begin();
                std::advance(Itr, PrevOffset);
                uint32_t CopyNum = CurEndOffset - PrevOffset;
                NewExprSize += CopyNum;
                while (CopyNum--) {
                  DIEBldr.addValue(NewAttr, *Itr);
                  std::advance(Itr, 1);
                }
              } else {
                const uint64_t Index = Expr.getRawOperand(0);
                std::optional<object::SectionedAddress> EntryAddress =
                    Unit.getAddrOffsetSectionItem(Index);
                assert(EntryAddress && "Address is not found.");
                assert(Index <= std::numeric_limits<uint32_t>::max() &&
                       "Invalid Operand Index.");
                const uint32_t AddrIndex = AddrWriter->getIndexFromAddress(
                    EntryAddress->Address, Unit);
                // update Index into .debug_address section for DW_AT_location.
                // The Size field is not stored in IR, we need to minus 1 in
                // offset for each expr.
                SmallString<8> Tmp;
                raw_svector_ostream OSE(Tmp);
                encodeULEB128(AddrIndex, OSE);

                DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
                                 dwarf::DW_FORM_data1,
                                 DIEInteger(Expr.getCode()));
                NewExprSize += 1;
                for (uint8_t Byte : Tmp) {
                  DIEBldr.addValue(NewAttr, static_cast<dwarf::Attribute>(0),
                                   dwarf::DW_FORM_data1, DIEInteger(Byte));
                  NewExprSize += 1;
                }
              }
              PrevOffset = CurEndOffset;
            }

            // update the size since the index might be changed
            if (Loc)
              Loc->setSize(NewExprSize);
            else
              Block->setSize(NewExprSize);
            DIEBldr.replaceValue(Die, LocAttrInfo.getAttribute(),
                                 LocAttrInfo.getForm(), Value);
          }
        }
      } else if (LowPCAttrInfo) {
        uint64_t Address = 0;
        uint64_t SectionIndex = 0;
        if (getLowPC(*Die, Unit, Address, SectionIndex)) {
          uint64_t NewAddress = 0;
          if (const BinaryFunction *Function =
                  BC.getBinaryFunctionContainingAddress(Address)) {
            NewAddress = Function->translateInputToOutputAddress(Address);
            LLVM_DEBUG(dbgs()
                       << "BOLT-DEBUG: Fixing low_pc 0x"
                       << Twine::utohexstr(Address) << " for DIE with tag "
                       << Die->getTag() << " to 0x"
                       << Twine::utohexstr(NewAddress) << '\n');
          }

          dwarf::Form Form = LowPCAttrInfo.getForm();
          assert(Form != dwarf::DW_FORM_LLVM_addrx_offset &&
                 "DW_FORM_LLVM_addrx_offset is not supported");
          std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
          if (Form == dwarf::DW_FORM_addrx ||
              Form == dwarf::DW_FORM_GNU_addr_index) {
            const uint32_t Index = AddrWriter->getIndexFromAddress(
                NewAddress ? NewAddress : Address, Unit);
            DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
                                 LowPCAttrInfo.getForm(), DIEInteger(Index));
          } else {
            DIEBldr.replaceValue(Die, LowPCAttrInfo.getAttribute(),
                                 LowPCAttrInfo.getForm(),
                                 DIEInteger(NewAddress));
          }
        } else if (opts::Verbosity >= 1) {
          errs() << "BOLT-WARNING: unexpected form value for attribute "
                    "LowPCAttrInfo\n";
        }
      }
    }
    }
  }
  if (DIEOffset > NextCUOffset)
    errs() << "BOLT-WARNING: corrupt DWARF detected at 0x"
           << Twine::utohexstr(Unit.getOffset()) << '\n';
}

void DWARFRewriter::updateDWARFObjectAddressRanges(
    DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die, uint64_t DebugRangesOffset,
    std::optional<uint64_t> RangesBase) {

  if (RangesBase) {
    // If DW_AT_GNU_ranges_base is present, update it. No further modifications
    // are needed for ranges base.

    DIEValue RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_GNU_ranges_base);
    if (!RangesBaseInfo) {
      RangesBaseInfo = Die.findAttribute(dwarf::DW_AT_rnglists_base);
    }

    if (RangesBaseInfo) {
      DIEBldr.replaceValue(&Die, RangesBaseInfo.getAttribute(),
                           RangesBaseInfo.getForm(),
                           DIEInteger(static_cast<uint32_t>(*RangesBase)));
      RangesBase = std::nullopt;
    }
  }

  DIEValue LowPCAttrInfo = Die.findAttribute(dwarf::DW_AT_low_pc);
  DIEValue RangesAttrInfo = Die.findAttribute(dwarf::DW_AT_ranges);
  if (RangesAttrInfo) {
    // Case 1: The object was already non-contiguous and had DW_AT_ranges.
    // In this case we simply need to update the value of DW_AT_ranges
    // and introduce DW_AT_GNU_ranges_base if required.
    // For DWARF5 converting all of DW_AT_ranges into DW_FORM_rnglistx
    bool NeedConverted = false;

    if (Unit.getVersion() >= 5 &&
        RangesAttrInfo.getForm() == dwarf::DW_FORM_sec_offset)
      NeedConverted = true;

    uint64_t CurRangeBase = 0;
    if (Unit.isDWOUnit()) {
      if (std::optional<uint64_t> DWOId = Unit.getDWOId())
        CurRangeBase = getDwoRangesBase(*DWOId);
      else
        errs() << "BOLT-WARNING: [internal-dwarf-error]: DWOId is not found "
                  "for DWO Unit.";
    }
    if (NeedConverted || RangesAttrInfo.getForm() == dwarf::DW_FORM_rnglistx)
      DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx,
                           DIEInteger(DebugRangesOffset));
    else
      DIEBldr.replaceValue(&Die, dwarf::DW_AT_ranges, RangesAttrInfo.getForm(),
                           DIEInteger(DebugRangesOffset - CurRangeBase));

    if (!RangesBase) {
      if (LowPCAttrInfo &&
          LowPCAttrInfo.getForm() != dwarf::DW_FORM_GNU_addr_index &&
          LowPCAttrInfo.getForm() != dwarf::DW_FORM_addrx)
        DIEBldr.replaceValue(&Die, dwarf::DW_AT_low_pc, LowPCAttrInfo.getForm(),
                             DIEInteger(0));
      return;
    }

    if (!(Die.getTag() == dwarf::DW_TAG_compile_unit ||
          Die.getTag() == dwarf::DW_TAG_skeleton_unit))
      return;

    // If we are at this point we are in the CU/Skeleton CU, and
    // DW_AT_GNU_ranges_base or DW_AT_rnglists_base doesn't exist.
    if (Unit.getVersion() <= 4)
      DIEBldr.addValue(&Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
                       DIEInteger(*RangesBase));
    else if (Unit.getVersion() == 5)
      DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,
                       dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));
    else
      DIEBldr.addValue(&Die, dwarf::DW_AT_rnglists_base,
                       dwarf::DW_FORM_sec_offset, DIEInteger(*RangesBase));
    return;
  }

  // Case 2: The object has both DW_AT_low_pc and DW_AT_high_pc emitted back
  // to back. Replace with new attributes and patch the DIE.
  DIEValue HighPCAttrInfo = Die.findAttribute(dwarf::DW_AT_high_pc);
  if (LowPCAttrInfo && HighPCAttrInfo) {

    convertToRangesPatchDebugInfo(Unit, DIEBldr, Die, DebugRangesOffset,
                                  LowPCAttrInfo, HighPCAttrInfo, RangesBase);
  } else if (!(Unit.isDWOUnit() &&
               Die.getTag() == dwarf::DW_TAG_compile_unit)) {
    if (opts::Verbosity >= 1)
      errs() << "BOLT-WARNING: cannot update ranges for DIE in Unit offset 0x"
             << Unit.getOffset() << '\n';
  }
}

void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
  ErrorOr<BinarySection &> DbgInfoSection =
      BC.getUniqueSectionByName(".debug_info");
  ErrorOr<BinarySection &> TypeInfoSection =
      BC.getUniqueSectionByName(".debug_types");
  assert(((BC.DwCtx->getNumTypeUnits() > 0 && TypeInfoSection) ||
          BC.DwCtx->getNumTypeUnits() == 0) &&
         "Was not able to retrieve Debug Types section.");

  // There is no direct connection between CU and TU, but same offsets,
  // encoded in DW_AT_stmt_list, into .debug_line get modified.
  // We take advantage of that to map original CU line table offsets to new
  // ones.
  std::unordered_map<uint64_t, uint64_t> DebugLineOffsetMap;

  auto GetStatementListValue =
      [](const DWARFDie &DIE) -> std::optional<uint64_t> {
    std::optional<DWARFFormValue> StmtList = DIE.find(dwarf::DW_AT_stmt_list);
    if (!StmtList)
      return std::nullopt;
    std::optional<uint64_t> Offset = dwarf::toSectionOffset(StmtList);
    assert(Offset && "Was not able to retrieve value of DW_AT_stmt_list.");
    return *Offset;
  };

  SmallVector<DWARFUnit *, 1> TUs;
  for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
    if (CU->isTypeUnit()) {
      TUs.push_back(CU.get());
      continue;
    }
    const unsigned CUID = CU->getOffset();
    MCSymbol *Label = BC.getDwarfLineTable(CUID).getLabel();
    if (!Label)
      continue;

    std::optional<uint64_t> StmtOffset =
        GetStatementListValue(CU.get()->getUnitDIE());
    if (!StmtOffset)
      continue;

    const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
    DebugLineOffsetMap[*StmtOffset] = LineTableOffset;
    assert(DbgInfoSection && ".debug_info section must exist");
    LineTablePatchMap[CU.get()] = LineTableOffset;
  }

  for (const std::unique_ptr<DWARFUnit> &TU : BC.DwCtx->types_section_units())
    TUs.push_back(TU.get());

  for (DWARFUnit *TU : TUs) {
    std::optional<uint64_t> StmtOffset =
        GetStatementListValue(TU->getUnitDIE());
    if (!StmtOffset)
      continue;
    auto Iter = DebugLineOffsetMap.find(*StmtOffset);
    if (Iter == DebugLineOffsetMap.end()) {
      // Implementation depends on TU sharing DW_AT_stmt_list with a CU.
      // Only case that it hasn't been true was for manually modified assembly
      // file. Adding this warning in case assumption is false.
      errs()
          << "BOLT-WARNING: [internal-dwarf-error]: A TU at offset: 0x"
          << Twine::utohexstr(TU->getOffset())
          << " is not sharing "
             ".debug_line entry with CU. DW_AT_stmt_list for this TU won't be "
             "updated.\n";
      continue;
    }
    TypeUnitRelocMap[TU] = Iter->second;
  }

  // Set .debug_info as finalized so it won't be skipped over when
  // we process sections while writing out the new binary. This ensures
  // that the pending relocations will be processed and not ignored.
  if (DbgInfoSection)
    DbgInfoSection->setIsFinalized();

  if (TypeInfoSection)
    TypeInfoSection->setIsFinalized();
}

CUOffsetMap DWARFRewriter::finalizeTypeSections(DIEBuilder &DIEBlder,
                                                DIEStreamer &Streamer) {
  // update TypeUnit DW_AT_stmt_list with new .debug_line information.
  auto updateLineTable = [&](const DWARFUnit &Unit) -> void {
    DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(Unit);
    DIEValue StmtAttrInfo = UnitDIE->findAttribute(dwarf::DW_AT_stmt_list);
    if (!StmtAttrInfo || !TypeUnitRelocMap.count(&Unit))
      return;
    DIEBlder.replaceValue(UnitDIE, dwarf::DW_AT_stmt_list,
                          StmtAttrInfo.getForm(),
                          DIEInteger(TypeUnitRelocMap[&Unit]));
  };

  // generate and populate abbrevs here
  DIEBlder.generateAbbrevs();
  DIEBlder.finish();
  SmallVector<char, 20> OutBuffer;
  std::shared_ptr<raw_svector_ostream> ObjOS =
      std::make_shared<raw_svector_ostream>(OutBuffer);
  const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
  auto TheTriple = std::make_unique<Triple>(File->makeTriple());
  std::unique_ptr<DIEStreamer> TypeStreamer =
      createDIEStreamer(*TheTriple, *ObjOS, "TypeStreamer", DIEBlder, *this);

  // generate debug_info and CUMap
  CUOffsetMap CUMap;
  for (std::unique_ptr<llvm::DWARFUnit> &CU : BC.DwCtx->info_section_units()) {
    if (!CU->isTypeUnit())
      continue;
    updateLineTable(*CU.get());
    emitUnit(DIEBlder, Streamer, *CU.get());
    uint32_t StartOffset = CUOffset;
    DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU.get());
    CUOffset += CU.get()->getHeaderSize();
    CUOffset += UnitDIE->getSize();
    CUMap[CU.get()->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
  }

  // Emit Type Unit of DWARF 4 to .debug_type section
  for (DWARFUnit *TU : DIEBlder.getDWARF4TUVector()) {
    updateLineTable(*TU);
    emitUnit(DIEBlder, *TypeStreamer, *TU);
  }

  TypeStreamer->finish();

  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
      MemoryBuffer::getMemBuffer(ObjOS->str(), "in-memory object file", false);
  std::unique_ptr<object::ObjectFile> Obj = cantFail(
      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
      "error creating in-memory object");

  for (const SectionRef &Section : Obj->sections()) {
    StringRef Contents = cantFail(Section.getContents());
    StringRef Name = cantFail(Section.getName());
    if (Name.equals(".debug_types"))
      BC.registerOrUpdateNoteSection(".debug_types", copyByteArray(Contents),
                                     Contents.size());
  }
  return CUMap;
}

void DWARFRewriter::finalizeDebugSections(
    DIEBuilder &DIEBlder, DWARF5AcceleratorTable &DebugNamesTable,
    DIEStreamer &Streamer, raw_svector_ostream &ObjOS, CUOffsetMap &CUMap) {
  if (StrWriter->isInitialized()) {
    RewriteInstance::addToDebugSectionsToOverwrite(".debug_str");
    std::unique_ptr<DebugStrBufferVector> DebugStrSectionContents =
        StrWriter->releaseBuffer();
    BC.registerOrUpdateNoteSection(".debug_str",
                                   copyByteArray(*DebugStrSectionContents),
                                   DebugStrSectionContents->size());
  }

  if (StrOffstsWriter->isFinalized()) {
    RewriteInstance::addToDebugSectionsToOverwrite(".debug_str_offsets");
    std::unique_ptr<DebugStrOffsetsBufferVector>
        DebugStrOffsetsSectionContents = StrOffstsWriter->releaseBuffer();
    BC.registerOrUpdateNoteSection(
        ".debug_str_offsets", copyByteArray(*DebugStrOffsetsSectionContents),
        DebugStrOffsetsSectionContents->size());
  }

  if (BC.isDWARFLegacyUsed()) {
    std::unique_ptr<DebugBufferVector> RangesSectionContents =
        LegacyRangesSectionWriter->releaseBuffer();
    BC.registerOrUpdateNoteSection(".debug_ranges",
                                   copyByteArray(*RangesSectionContents),
                                   RangesSectionContents->size());
  }

  if (BC.isDWARF5Used()) {
    std::unique_ptr<DebugBufferVector> RangesSectionContents =
        RangeListsSectionWriter->releaseBuffer();
    BC.registerOrUpdateNoteSection(".debug_rnglists",
                                   copyByteArray(*RangesSectionContents),
                                   RangesSectionContents->size());
  }

  if (BC.isDWARF5Used()) {
    std::unique_ptr<DebugBufferVector> LocationListSectionContents =
        makeFinalLocListsSection(DWARFVersion::DWARF5);
    if (!LocationListSectionContents->empty())
      BC.registerOrUpdateNoteSection(
          ".debug_loclists", copyByteArray(*LocationListSectionContents),
          LocationListSectionContents->size());
  }

  if (BC.isDWARFLegacyUsed()) {
    std::unique_ptr<DebugBufferVector> LocationListSectionContents =
        makeFinalLocListsSection(DWARFVersion::DWARFLegacy);
    if (!LocationListSectionContents->empty())
      BC.registerOrUpdateNoteSection(
          ".debug_loc", copyByteArray(*LocationListSectionContents),
          LocationListSectionContents->size());
  }

  // AddrWriter should be finalized after debug_loc since more addresses can be
  // added there.
  if (AddrWriter->isInitialized()) {
    AddressSectionBuffer AddressSectionContents = AddrWriter->finalize();
    BC.registerOrUpdateNoteSection(".debug_addr",
                                   copyByteArray(AddressSectionContents),
                                   AddressSectionContents.size());
  }

  Streamer.emitAbbrevs(DIEBlder.getAbbrevs(), BC.DwCtx->getMaxVersion());
  Streamer.finish();

  std::unique_ptr<MemoryBuffer> ObjectMemBuffer =
      MemoryBuffer::getMemBuffer(ObjOS.str(), "in-memory object file", false);
  std::unique_ptr<object::ObjectFile> Obj = cantFail(
      object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
      "error creating in-memory object");

  for (const SectionRef &Secs : Obj->sections()) {
    StringRef Contents = cantFail(Secs.getContents());
    StringRef Name = cantFail(Secs.getName());
    if (Name.equals(".debug_abbrev")) {
      BC.registerOrUpdateNoteSection(".debug_abbrev", copyByteArray(Contents),
                                     Contents.size());
    } else if (Name.equals(".debug_info")) {
      BC.registerOrUpdateNoteSection(".debug_info", copyByteArray(Contents),
                                     Contents.size());
    }
  }

  // Skip .debug_aranges if we are re-generating .gdb_index.
  if (opts::KeepARanges || !BC.getGdbIndexSection()) {
    SmallVector<char, 16> ARangesBuffer;
    raw_svector_ostream OS(ARangesBuffer);

    auto MAB = std::unique_ptr<MCAsmBackend>(
        BC.TheTarget->createMCAsmBackend(*BC.STI, *BC.MRI, MCTargetOptions()));

    ARangesSectionWriter->writeARangesSection(OS, CUMap);
    const StringRef &ARangesContents = OS.str();

    BC.registerOrUpdateNoteSection(".debug_aranges",
                                   copyByteArray(ARangesContents),
                                   ARangesContents.size());
  }

  if (DebugNamesTable.isCreated()) {
    RewriteInstance::addToDebugSectionsToOverwrite(".debug_names");
    std::unique_ptr<DebugBufferVector> DebugNamesSectionContents =
        DebugNamesTable.releaseBuffer();
    BC.registerOrUpdateNoteSection(".debug_names",
                                   copyByteArray(*DebugNamesSectionContents),
                                   DebugNamesSectionContents->size());
  }
}

void DWARFRewriter::finalizeCompileUnits(DIEBuilder &DIEBlder,
                                         DIEStreamer &Streamer,
                                         CUOffsetMap &CUMap,
                                         const std::list<DWARFUnit *> &CUs) {
  DIEBlder.generateAbbrevs();
  DIEBlder.finish();
  // generate debug_info and CUMap
  for (DWARFUnit *CU : CUs) {
    emitUnit(DIEBlder, Streamer, *CU);
    const uint32_t StartOffset = CUOffset;
    DIE *UnitDIE = DIEBlder.getUnitDIEbyUnit(*CU);
    CUOffset += CU->getHeaderSize();
    CUOffset += UnitDIE->getSize();
    CUMap[CU->getOffset()] = {StartOffset, CUOffset - StartOffset - 4};
  }
}

// Creates all the data structures necessary for creating MCStreamer.
// They are passed by reference because they need to be kept around.
// Also creates known debug sections. These are sections handled by
// handleDebugDataPatching.
namespace {

std::unique_ptr<BinaryContext>
createDwarfOnlyBC(const object::ObjectFile &File) {
  return cantFail(BinaryContext::createBinaryContext(
      File.makeTriple(), File.getFileName(), nullptr, false,
      DWARFContext::create(File, DWARFContext::ProcessDebugRelocations::Ignore,
                           nullptr, "", WithColor::defaultErrorHandler,
                           WithColor::defaultWarningHandler),
      {llvm::outs(), llvm::errs()}));
}

StringMap<DWARFRewriter::KnownSectionsEntry>
createKnownSectionsMap(const MCObjectFileInfo &MCOFI) {
  StringMap<DWARFRewriter::KnownSectionsEntry> KnownSectionsTemp = {
      {"debug_info.dwo", {MCOFI.getDwarfInfoDWOSection(), DW_SECT_INFO}},
      {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
      {"debug_str_offsets.dwo",
       {MCOFI.getDwarfStrOffDWOSection(), DW_SECT_STR_OFFSETS}},
      {"debug_str.dwo", {MCOFI.getDwarfStrDWOSection(), DW_SECT_EXT_unknown}},
      {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
      {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
      {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
      {"debug_loclists.dwo",
       {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
      {"debug_rnglists.dwo",
       {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}};
  return KnownSectionsTemp;
}

StringRef getSectionName(const SectionRef &Section) {
  Expected<StringRef> SectionName = Section.getName();
  assert(SectionName && "Invalid section name.");
  StringRef Name = *SectionName;
  Name = Name.substr(Name.find_first_not_of("._"));
  return Name;
}

// Exctracts an appropriate slice if input is DWP.
// Applies patches or overwrites the section.
std::optional<StringRef> updateDebugData(
    DWARFContext &DWCtx, StringRef SectionName, StringRef SectionContents,
    const StringMap<DWARFRewriter::KnownSectionsEntry> &KnownSections,
    MCStreamer &Streamer, DWARFRewriter &Writer,
    const DWARFUnitIndex::Entry *CUDWOEntry, uint64_t DWOId,
    std::unique_ptr<DebugBufferVector> &OutputBuffer,
    DebugRangeListsSectionWriter *RangeListsWriter, DebugLocWriter &LocWriter,
    const llvm::bolt::DWARFRewriter::OverriddenSectionsMap &OverridenSections) {

  using DWOSectionContribution =
      const DWARFUnitIndex::Entry::SectionContribution;
  auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry,
                          StringRef OutData, DWARFSectionKind Sec,
                          uint64_t &DWPOffset) -> StringRef {
    if (DWOEntry) {
      DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec);
      DWPOffset = DWOContrubution->getOffset();
      OutData = OutData.substr(DWPOffset, DWOContrubution->getLength());
    }
    return OutData;
  };

  auto SectionIter = KnownSections.find(SectionName);
  if (SectionIter == KnownSections.end())
    return std::nullopt;
  Streamer.switchSection(SectionIter->second.first);
  uint64_t DWPOffset = 0;

  auto getOverridenSection =
      [&](DWARFSectionKind Kind) -> std::optional<StringRef> {
    auto Iter = OverridenSections.find(Kind);
    if (Iter == OverridenSections.end()) {
      errs()
          << "BOLT-WARNING: [internal-dwarf-error]: Could not find overriden "
             "section for: "
          << Twine::utohexstr(DWOId) << ".\n";
      return std::nullopt;
    }
    return Iter->second;
  };
  switch (SectionIter->second.second) {
  default: {
    if (!SectionName.equals("debug_str.dwo"))
      errs() << "BOLT-WARNING: unsupported debug section: " << SectionName
             << "\n";
    return SectionContents;
  }
  case DWARFSectionKind::DW_SECT_INFO: {
    return getOverridenSection(DWARFSectionKind::DW_SECT_INFO);
  }
  case DWARFSectionKind::DW_SECT_EXT_TYPES: {
    return getOverridenSection(DWARFSectionKind::DW_SECT_EXT_TYPES);
  }
  case DWARFSectionKind::DW_SECT_STR_OFFSETS: {
    return getSliceData(CUDWOEntry, SectionContents,
                        DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
  }
  case DWARFSectionKind::DW_SECT_ABBREV: {
    return getOverridenSection(DWARFSectionKind::DW_SECT_ABBREV);
  }
  case DWARFSectionKind::DW_SECT_EXT_LOC:
  case DWARFSectionKind::DW_SECT_LOCLISTS: {
    OutputBuffer = LocWriter.getBuffer();
    // Creating explicit StringRef here, otherwise
    // with implicit conversion it will take null byte as end of
    // string.
    return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
                     OutputBuffer->size());
  }
  case DWARFSectionKind::DW_SECT_LINE: {
    return getSliceData(CUDWOEntry, SectionContents,
                        DWARFSectionKind::DW_SECT_LINE, DWPOffset);
  }
  case DWARFSectionKind::DW_SECT_RNGLISTS: {
    assert(RangeListsWriter && "RangeListsWriter was not created.");
    OutputBuffer = RangeListsWriter->releaseBuffer();
    return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
                     OutputBuffer->size());
  }
  }
}

} // namespace

void DWARFRewriter::initDWPState(DWPState &State) {
  SmallString<0> OutputNameStr;
  StringRef OutputName;
  if (opts::DwarfOutputPath.empty()) {
    OutputName =
        Twine(opts::OutputFilename).concat(".dwp").toStringRef(OutputNameStr);
  } else {
    StringRef ExeFileName = llvm::sys::path::filename(opts::OutputFilename);
    OutputName = Twine(opts::DwarfOutputPath)
                     .concat("/")
                     .concat(ExeFileName)
                     .concat(".dwp")
                     .toStringRef(OutputNameStr);
    errs() << "BOLT-WARNING: dwarf-output-path is in effect and .dwp file will "
              "possibly be written to another location that is not the same as "
              "the executable\n";
  }
  std::error_code EC;
  State.Out =
      std::make_unique<ToolOutputFile>(OutputName, EC, sys::fs::OF_None);
  const object::ObjectFile *File = BC.DwCtx->getDWARFObj().getFile();
  State.TmpBC = createDwarfOnlyBC(*File);
  State.Streamer = State.TmpBC->createStreamer(State.Out->os());
  State.MCOFI = State.Streamer->getContext().getObjectFileInfo();
  State.KnownSections = createKnownSectionsMap(*State.MCOFI);
  MCSection *const StrSection = State.MCOFI->getDwarfStrDWOSection();

  // Data Structures for DWP book keeping
  // Size of array corresponds to the number of sections supported by DWO format
  // in DWARF4/5.

  State.Strings = std::make_unique<DWPStringPool>(*State.Streamer, StrSection);

  // Setup DWP code once.
  DWARFContext *DWOCtx = BC.getDWOContext();

  if (DWOCtx) {
    State.CUIndex = &DWOCtx->getCUIndex();
    State.IsDWP = !State.CUIndex->getRows().empty();
  }
}

void DWARFRewriter::finalizeDWP(DWPState &State) {
  if (State.Version < 5) {
    // Lie about there being no info contributions so the TU index only includes
    // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
    // contribution to the info section, so we do not want to lie about it.
    State.ContributionOffsets[0] = 0;
  }
  writeIndex(*State.Streamer.get(), State.MCOFI->getDwarfTUIndexSection(),
             State.ContributionOffsets, State.TypeIndexEntries,
             State.IndexVersion);

  if (State.Version < 5) {
    // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
    // section does not exist, so no need to do anything about this.
    State.ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
    // Unlie about the info contribution
    State.ContributionOffsets[0] = 1;
  }
  writeIndex(*State.Streamer.get(), State.MCOFI->getDwarfCUIndexSection(),
             State.ContributionOffsets, State.IndexEntries, State.IndexVersion);

  State.Streamer->finish();
  State.Out->keep();
}

void DWARFRewriter::updateDWP(DWARFUnit &CU,
                              const OverriddenSectionsMap &OverridenSections,
                              const DWARFRewriter::UnitMeta &CUMI,
                              DWARFRewriter::UnitMetaVectorType &TUMetaVector,
                              DWPState &State, DebugLocWriter &LocWriter) {
  const uint64_t DWOId = *CU.getDWOId();
  MCSection *const StrOffsetSection = State.MCOFI->getDwarfStrOffDWOSection();
  assert(StrOffsetSection && "StrOffsetSection does not exist.");
  // Skipping CUs that we failed to load.
  std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
  if (!DWOCU)
    return;

  if (State.Version == 0) {
    State.Version = CU.getVersion();
    State.IndexVersion = State.Version < 5 ? 2 : 5;
  } else if (State.Version != CU.getVersion()) {
    errs() << "BOLT-ERROR: incompatible DWARF compile unit versions\n";
    exit(1);
  }

  UnitIndexEntry CurEntry = {};
  CurEntry.DWOName = dwarf::toString(
      CU.getUnitDIE().find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
      "");
  const char *Name = CU.getUnitDIE().getShortName();
  if (Name)
    CurEntry.Name = Name;
  StringRef CurStrSection;
  StringRef CurStrOffsetSection;

  // This maps each section contained in this file to its length.
  // This information is later on used to calculate the contributions,
  // i.e. offset and length, of each compile/type unit to a section.
  std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;

  const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
  if (State.IsDWP)
    CUDWOEntry = State.CUIndex->getFromHash(DWOId);

  bool StrSectionWrittenOut = false;
  const object::ObjectFile *DWOFile =
      (*DWOCU)->getContext().getDWARFObj().getFile();

  DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
  if (CU.getVersion() == 5) {
    assert(RangeListsWritersByCU.count(DWOId) != 0 &&
           "No RangeListsWriter for DWO ID.");
    RangeListssWriter = RangeListsWritersByCU[DWOId].get();
  }
  auto AddType = [&](unsigned int Index, uint32_t IndexVersion, uint64_t Offset,
                     uint64_t Length, uint64_t Hash) -> void {
    UnitIndexEntry TUEntry = CurEntry;
    if (IndexVersion < 5)
      TUEntry.Contributions[0] = {};
    TUEntry.Contributions[Index].setOffset(Offset);
    TUEntry.Contributions[Index].setLength(Length);
    State.ContributionOffsets[Index] +=
        TUEntry.Contributions[Index].getLength32();
    State.TypeIndexEntries.insert(std::make_pair(Hash, TUEntry));
  };
  for (const SectionRef &Section : DWOFile->sections()) {
    std::unique_ptr<DebugBufferVector> OutputData;
    StringRef SectionName = getSectionName(Section);
    Expected<StringRef> ContentsExp = Section.getContents();
    assert(ContentsExp && "Invalid contents.");
    std::optional<StringRef> TOutData = updateDebugData(
        (*DWOCU)->getContext(), SectionName, *ContentsExp, State.KnownSections,
        *State.Streamer, *this, CUDWOEntry, DWOId, OutputData,
        RangeListssWriter, LocWriter, OverridenSections);
    if (!TOutData)
      continue;

    StringRef OutData = *TOutData;
    if (SectionName == "debug_types.dwo") {
      State.Streamer->emitBytes(OutData);
      continue;
    }

    if (SectionName.equals("debug_str.dwo")) {
      CurStrSection = OutData;
    } else {
      // Since handleDebugDataPatching returned true, we already know this is
      // a known section.
      auto SectionIter = State.KnownSections.find(SectionName);
      if (SectionIter->second.second == DWARFSectionKind::DW_SECT_STR_OFFSETS)
        CurStrOffsetSection = OutData;
      else
        State.Streamer->emitBytes(OutData);
      unsigned int Index =
          getContributionIndex(SectionIter->second.second, State.IndexVersion);
      uint64_t Offset = State.ContributionOffsets[Index];
      uint64_t Length = OutData.size();
      if (CU.getVersion() >= 5 &&
          SectionIter->second.second == DWARFSectionKind::DW_SECT_INFO) {
        for (UnitMeta &MI : TUMetaVector)
          MI.Offset += State.DebugInfoSize;

        Offset = State.DebugInfoSize + CUMI.Offset;
        Length = CUMI.Length;
        State.DebugInfoSize += OutData.size();
      }
      CurEntry.Contributions[Index].setOffset(Offset);
      CurEntry.Contributions[Index].setLength(Length);
      State.ContributionOffsets[Index] +=
          CurEntry.Contributions[Index].getLength32();
    }

    // Strings are combined in to a new string section, and de-duplicated
    // based on hash.
    if (!StrSectionWrittenOut && !CurStrOffsetSection.empty() &&
        !CurStrSection.empty()) {
      writeStringsAndOffsets(*State.Streamer.get(), *State.Strings.get(),
                             StrOffsetSection, CurStrSection,
                             CurStrOffsetSection, CU.getVersion());
      StrSectionWrittenOut = true;
    }
  }
  CompileUnitIdentifiers CUI{DWOId, CurEntry.Name.c_str(),
                             CurEntry.DWOName.c_str()};
  auto P = State.IndexEntries.insert(std::make_pair(CUI.Signature, CurEntry));
  if (!P.second) {
    Error Err = buildDuplicateError(*P.first, CUI, "");
    errs() << "BOLT-ERROR: " << toString(std::move(Err)) << "\n";
    return;
  }

  // Handling TU
  const unsigned Index = getContributionIndex(
      State.IndexVersion < 5 ? DW_SECT_EXT_TYPES : DW_SECT_INFO,
      State.IndexVersion);
  for (UnitMeta &MI : TUMetaVector)
    AddType(Index, State.IndexVersion, MI.Offset, MI.Length, MI.TUHash);
}

void DWARFRewriter::writeDWOFiles(
    DWARFUnit &CU, const OverriddenSectionsMap &OverridenSections,
    const std::string &DWOName, DebugLocWriter &LocWriter) {
  // Setup DWP code once.
  DWARFContext *DWOCtx = BC.getDWOContext();
  const uint64_t DWOId = *CU.getDWOId();
  const DWARFUnitIndex *CUIndex = nullptr;
  bool IsDWP = false;
  if (DWOCtx) {
    CUIndex = &DWOCtx->getCUIndex();
    IsDWP = !CUIndex->getRows().empty();
  }

  // Skipping CUs that we failed to load.
  std::optional<DWARFUnit *> DWOCU = BC.getDWOCU(DWOId);
  if (!DWOCU) {
    errs() << "BOLT-WARNING: [internal-dwarf-error]: CU for DWO_ID "
           << Twine::utohexstr(DWOId) << " is not found.\n";
    return;
  }

  std::string CompDir = CU.getCompilationDir();

  if (!opts::DwarfOutputPath.empty())
    CompDir = opts::DwarfOutputPath.c_str();
  else if (!opts::CompDirOverride.empty())
    CompDir = opts::CompDirOverride;

  SmallString<16> AbsolutePath;
  sys::path::append(AbsolutePath, CompDir);
  sys::path::append(AbsolutePath, DWOName);

  std::error_code EC;
  std::unique_ptr<ToolOutputFile> TempOut =
      std::make_unique<ToolOutputFile>(AbsolutePath, EC, sys::fs::OF_None);

  const DWARFUnitIndex::Entry *CUDWOEntry = nullptr;
  if (IsDWP)
    CUDWOEntry = CUIndex->getFromHash(DWOId);

  const object::ObjectFile *File =
      (*DWOCU)->getContext().getDWARFObj().getFile();
  std::unique_ptr<BinaryContext> TmpBC = createDwarfOnlyBC(*File);
  std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
  const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
  StringMap<KnownSectionsEntry> KnownSections = createKnownSectionsMap(MCOFI);

  DebugRangeListsSectionWriter *RangeListssWriter = nullptr;
  if (CU.getVersion() == 5) {
    assert(RangeListsWritersByCU.count(DWOId) != 0 &&
           "No RangeListsWriter for DWO ID.");
    RangeListssWriter = RangeListsWritersByCU[DWOId].get();

    // Handling .debug_rnglists.dwo separately. The original .o/.dwo might not
    // have .debug_rnglists so won't be part of the loop below.
    if (!RangeListssWriter->empty()) {
      std::unique_ptr<DebugBufferVector> OutputData;
      if (std::optional<StringRef> OutData = updateDebugData(
              (*DWOCU)->getContext(), "debug_rnglists.dwo", "", KnownSections,
              *Streamer, *this, CUDWOEntry, DWOId, OutputData,
              RangeListssWriter, LocWriter, OverridenSections))
        Streamer->emitBytes(*OutData);
    }
  }

  for (const SectionRef &Section : File->sections()) {
    std::unique_ptr<DebugBufferVector> OutputData;
    StringRef SectionName = getSectionName(Section);
    if (SectionName == "debug_rnglists.dwo")
      continue;
    Expected<StringRef> ContentsExp = Section.getContents();
    assert(ContentsExp && "Invalid contents.");
    if (std::optional<StringRef> OutData = updateDebugData(
            (*DWOCU)->getContext(), SectionName, *ContentsExp, KnownSections,
            *Streamer, *this, CUDWOEntry, DWOId, OutputData, RangeListssWriter,
            LocWriter, OverridenSections))
      Streamer->emitBytes(*OutData);
  }
  Streamer->finish();
  TempOut->keep();
}

void DWARFRewriter::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
  std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
  if (!BC.getGdbIndexSection())
    return;
  GDBIndexTUEntryVector.emplace_back(Entry);
}

void DWARFRewriter::updateGdbIndexSection(CUOffsetMap &CUMap, uint32_t NumCUs) {
  if (!BC.getGdbIndexSection())
    return;

  // See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
  // for .gdb_index section format.

  StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();

  const char *Data = GdbIndexContents.data();

  // Parse the header.
  const uint32_t Version = read32le(Data);
  if (Version != 7 && Version != 8) {
    errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
    exit(1);
  }

  // Some .gdb_index generators use file offsets while others use section
  // offsets. Hence we can only rely on offsets relative to each other,
  // and ignore their absolute values.
  const uint32_t CUListOffset = read32le(Data + 4);
  const uint32_t CUTypesOffset = read32le(Data + 8);
  const uint32_t AddressTableOffset = read32le(Data + 12);
  const uint32_t SymbolTableOffset = read32le(Data + 16);
  const uint32_t ConstantPoolOffset = read32le(Data + 20);
  Data += 24;

  // Map CUs offsets to indices and verify existing index table.
  std::map<uint32_t, uint32_t> OffsetToIndexMap;
  const uint32_t CUListSize = CUTypesOffset - CUListOffset;
  const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
  const unsigned NUmCUsEncoded = CUListSize / 16;
  unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
  unsigned NumDWARF5TUs =
      getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
  bool SkipTypeUnits = false;
  // For DWARF5 Types are in .debug_info.
  // LLD doesn't generate Types CU List, and in CU list offset
  // only includes CUs.
  // GDB 11+ includes only CUs in CU list and generates Types
  // list.
  // GDB 9 includes CUs and TUs in CU list and generates TYpes
  // list. The NumCUs is CUs + TUs, so need to modify the check.
  // For split-dwarf
  // GDB-11, DWARF5: TU units from dwo are not included.
  // GDB-11, DWARF4: TU units from dwo are included.
  if (MaxDWARFVersion >= 5)
    SkipTypeUnits = !TUListSize ? true
                                : ((NUmCUsEncoded + NumDWARF5TUs) ==
                                   BC.DwCtx->getNumCompileUnits());

  if (!((CUListSize == NumCUs * 16) ||
        (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
    errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
    exit(1);
  }
  DenseSet<uint64_t> OriginalOffsets;
  for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
       Index < Units; ++Index) {
    const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index);
    if (SkipTypeUnits && CU->isTypeUnit())
      continue;
    const uint64_t Offset = read64le(Data);
    Data += 16;
    if (CU->getOffset() != Offset) {
      errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
      exit(1);
    }

    OriginalOffsets.insert(Offset);
    OffsetToIndexMap[Offset] = Index;
  }

  // Ignore old address table.
  const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
  // Move Data to the beginning of symbol table.
  Data += SymbolTableOffset - CUTypesOffset;

  // Calculate the size of the new address table.
  uint32_t NewAddressTableSize = 0;
  for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
    const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
    NewAddressTableSize += Ranges.size() * 20;
  }

  // Difference between old and new table (and section) sizes.
  // Could be negative.
  int32_t Delta = NewAddressTableSize - OldAddressTableSize;

  size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;

  // Free'd by ExecutableFileMemoryManager.
  auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
  uint8_t *Buffer = NewGdbIndexContents;

  write32le(Buffer, Version);
  write32le(Buffer + 4, CUListOffset);
  write32le(Buffer + 8, CUTypesOffset);
  write32le(Buffer + 12, AddressTableOffset);
  write32le(Buffer + 16, SymbolTableOffset + Delta);
  write32le(Buffer + 20, ConstantPoolOffset + Delta);
  Buffer += 24;

  using MapEntry = std::pair<uint32_t, CUInfo>;
  std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
  // Need to sort since we write out all of TUs in .debug_info before CUs.
  std::sort(CUVector.begin(), CUVector.end(),
            [](const MapEntry &E1, const MapEntry &E2) -> bool {
              return E1.second.Offset < E2.second.Offset;
            });
  // Writing out CU List <Offset, Size>
  for (auto &CUInfo : CUVector) {
    // Skipping TU for DWARF5 when they are not included in CU list.
    if (!OriginalOffsets.count(CUInfo.first))
      continue;
    write64le(Buffer, CUInfo.second.Offset);
    // Length encoded in CU doesn't contain first 4 bytes that encode length.
    write64le(Buffer + 8, CUInfo.second.Length + 4);
    Buffer += 16;
  }

  // Rewrite TU CU List, since abbrevs can be different.
  // Entry example:
  // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
  // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
  // the second value is the type offset in the CU, and the third value is the
  // type signature" Looking at what is being generated by gdb-add-index. The
  // first entry is TU offset, second entry is offset from it, and third entry
  // is the type signature.
  if (TUListSize)
    for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
      write64le(Buffer, Entry.UnitOffset);
      write64le(Buffer + 8, Entry.TypeDIERelativeOffset);
      write64le(Buffer + 16, Entry.TypeHash);
      Buffer += sizeof(GDBIndexTUEntry);
    }

  // Generate new address table.
  for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
       ARangesSectionWriter->getCUAddressRanges()) {
    const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
    const DebugAddressRangesVector &Ranges = CURangesPair.second;
    for (const DebugAddressRange &Range : Ranges) {
      write64le(Buffer, Range.LowPC);
      write64le(Buffer + 8, Range.HighPC);
      write32le(Buffer + 16, CUIndex);
      Buffer += 20;
    }
  }

  const size_t TrailingSize =
      GdbIndexContents.data() + GdbIndexContents.size() - Data;
  assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
         "size calculation error");

  // Copy over the rest of the original data.
  memcpy(Buffer, Data, TrailingSize);

  // Register the new section.
  BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
                                 NewGdbIndexSize);
}

std::unique_ptr<DebugBufferVector>
DWARFRewriter::makeFinalLocListsSection(DWARFVersion Version) {
  auto LocBuffer = std::make_unique<DebugBufferVector>();
  auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
  auto Writer =
      std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));

  for (std::pair<const uint64_t, std::unique_ptr<DebugLocWriter>> &Loc :
       LocListWritersByCU) {
    DebugLocWriter *LocWriter = Loc.second.get();
    auto *LocListWriter = llvm::dyn_cast<DebugLoclistWriter>(LocWriter);

    // Filter out DWARF4, writing out DWARF5
    if (Version == DWARFVersion::DWARF5 &&
        (!LocListWriter || LocListWriter->getDwarfVersion() <= 4))
      continue;

    // Filter out DWARF5, writing out DWARF4
    if (Version == DWARFVersion::DWARFLegacy &&
        (LocListWriter && LocListWriter->getDwarfVersion() >= 5))
      continue;

    // Skipping DWARF4/5 split dwarf.
    if (LocListWriter && LocListWriter->getDwarfVersion() <= 4)
      continue;
    std::unique_ptr<DebugBufferVector> CurrCULocationLists =
        LocWriter->getBuffer();
    *LocStream << *CurrCULocationLists;
  }

  return LocBuffer;
}

void DWARFRewriter::convertToRangesPatchDebugInfo(
    DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
    uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
    DIEValue &HighPCAttrInfo, std::optional<uint64_t> RangesBase) {
  uint32_t BaseOffset = 0;
  dwarf::Form LowForm = LowPCAttrInfo.getForm();
  dwarf::Attribute RangeBaseAttribute = dwarf::DW_AT_GNU_ranges_base;
  dwarf::Form RangesForm = dwarf::DW_FORM_sec_offset;

  if (Unit.getVersion() >= 5) {
    RangeBaseAttribute = dwarf::DW_AT_rnglists_base;
    RangesForm = dwarf::DW_FORM_rnglistx;
  } else if (Unit.getVersion() < 4) {
    RangesForm = dwarf::DW_FORM_data4;
  }
  bool IsUnitDie = Die.getTag() == dwarf::DW_TAG_compile_unit ||
                   Die.getTag() == dwarf::DW_TAG_skeleton_unit;
  if (!IsUnitDie)
    DIEBldr.deleteValue(&Die, LowPCAttrInfo.getAttribute());
  // In DWARF4 for DW_AT_low_pc in binary DW_FORM_addr is used. In the DWO
  // section DW_FORM_GNU_addr_index is used. So for if we are converting
  // DW_AT_low_pc/DW_AT_high_pc and see DW_FORM_GNU_addr_index. We are
  // converting in DWO section, and DW_AT_ranges [DW_FORM_sec_offset] is
  // relative to DW_AT_GNU_ranges_base.
  if (LowForm == dwarf::DW_FORM_GNU_addr_index) {
    // Ranges are relative to DW_AT_GNU_ranges_base.
    uint64_t CurRangeBase = 0;
    if (std::optional<uint64_t> DWOId = Unit.getDWOId()) {
      CurRangeBase = getDwoRangesBase(*DWOId);
    }
    BaseOffset = CurRangeBase;
  } else {
    // In DWARF 5 we can have DW_AT_low_pc either as DW_FORM_addr, or
    // DW_FORM_addrx. Former is when DW_AT_rnglists_base is present. Latter is
    // when it's absent.
    if (IsUnitDie) {
      if (LowForm == dwarf::DW_FORM_addrx) {
        const uint32_t Index = AddrWriter->getIndexFromAddress(0, Unit);
        DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
                             LowPCAttrInfo.getForm(), DIEInteger(Index));
      } else {
        DIEBldr.replaceValue(&Die, LowPCAttrInfo.getAttribute(),
                             LowPCAttrInfo.getForm(), DIEInteger(0));
      }
    }
    // Original CU didn't have DW_AT_*_base. We converted it's children (or
    // dwo), so need to insert it into CU.
    if (RangesBase)
      DIEBldr.addValue(&Die, RangeBaseAttribute, dwarf::DW_FORM_sec_offset,
                       DIEInteger(*RangesBase));
  }

  uint64_t RangeAttrVal = RangesSectionOffset - BaseOffset;
  if (Unit.getVersion() >= 5)
    RangeAttrVal = RangesSectionOffset;
  // HighPC was conveted into DW_AT_ranges.
  // For DWARF5 we only access ranges through index.

  DIEBldr.replaceValue(&Die, HighPCAttrInfo.getAttribute(), dwarf::DW_AT_ranges,
                       RangesForm, DIEInteger(RangeAttrVal));
}
