//===- bolt/Core/DebugData.cpp - Debugging information handling -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements functions and classes for handling debug info.
//
//===----------------------------------------------------------------------===//

#include "bolt/Core/DebugData.h"
#include "bolt/Core/BinaryContext.h"
#include "bolt/Core/DIEBuilder.h"
#include "bolt/Rewrite/RewriteInstance.h"
#include "bolt/Utils/Utils.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/SHA1.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <functional>
#include <limits>
#include <memory>
#include <unordered_map>
#include <vector>

#define DEBUG_TYPE "bolt-debug-info"

namespace opts {
extern llvm::cl::opt<unsigned> Verbosity;
} // namespace opts

namespace llvm {
class MCSymbol;

namespace bolt {

static void replaceLocValbyForm(DIEBuilder &DIEBldr, DIE &Die, DIEValue DIEVal,
                                dwarf::Form Format, uint64_t NewVal) {
  if (Format == dwarf::DW_FORM_loclistx)
    DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
                         DIELocList(NewVal));
  else
    DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
                         DIEInteger(NewVal));
}

std::optional<AttrInfo>
findAttributeInfo(const DWARFDie DIE,
                  const DWARFAbbreviationDeclaration *AbbrevDecl,
                  uint32_t Index) {
  const DWARFUnit &U = *DIE.getDwarfUnit();
  uint64_t Offset =
      AbbrevDecl->getAttributeOffsetFromIndex(Index, DIE.getOffset(), U);
  std::optional<DWARFFormValue> Value =
      AbbrevDecl->getAttributeValueFromOffset(Index, Offset, U);
  if (!Value)
    return std::nullopt;
  // AttributeSpec
  const DWARFAbbreviationDeclaration::AttributeSpec *AttrVal =
      AbbrevDecl->attributes().begin() + Index;
  uint32_t ValSize = 0;
  std::optional<int64_t> ValSizeOpt = AttrVal->getByteSize(U);
  if (ValSizeOpt) {
    ValSize = static_cast<uint32_t>(*ValSizeOpt);
  } else {
    DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor();
    uint64_t NewOffset = Offset;
    DWARFFormValue::skipValue(Value->getForm(), DebugInfoData, &NewOffset,
                              U.getFormParams());
    // This includes entire size of the entry, which might not be just the
    // encoding part. For example for DW_AT_loc it will include expression
    // location.
    ValSize = NewOffset - Offset;
  }
  return AttrInfo{*Value, DIE.getAbbreviationDeclarationPtr(), Offset, ValSize};
}

std::optional<AttrInfo> findAttributeInfo(const DWARFDie DIE,
                                          dwarf::Attribute Attr) {
  if (!DIE.isValid())
    return std::nullopt;
  const DWARFAbbreviationDeclaration *AbbrevDecl =
      DIE.getAbbreviationDeclarationPtr();
  if (!AbbrevDecl)
    return std::nullopt;
  std::optional<uint32_t> Index = AbbrevDecl->findAttributeIndex(Attr);
  if (!Index)
    return std::nullopt;
  return findAttributeInfo(DIE, AbbrevDecl, *Index);
}

const DebugLineTableRowRef DebugLineTableRowRef::NULL_ROW{0, 0};

LLVM_ATTRIBUTE_UNUSED
static void printLE64(const std::string &S) {
  for (uint32_t I = 0, Size = S.size(); I < Size; ++I) {
    errs() << Twine::utohexstr(S[I]);
    errs() << Twine::utohexstr((int8_t)S[I]);
  }
  errs() << "\n";
}

// Writes address ranges to Writer as pairs of 64-bit (address, size).
// If RelativeRange is true, assumes the address range to be written must be of
// the form (begin address, range size), otherwise (begin address, end address).
// Terminates the list by writing a pair of two zeroes.
// Returns the number of written bytes.
static uint64_t
writeAddressRanges(raw_svector_ostream &Stream,
                   const DebugAddressRangesVector &AddressRanges,
                   const bool WriteRelativeRanges = false) {
  for (const DebugAddressRange &Range : AddressRanges) {
    support::endian::write(Stream, Range.LowPC, llvm::endianness::little);
    support::endian::write(
        Stream, WriteRelativeRanges ? Range.HighPC - Range.LowPC : Range.HighPC,
        llvm::endianness::little);
  }
  // Finish with 0 entries.
  support::endian::write(Stream, 0ULL, llvm::endianness::little);
  support::endian::write(Stream, 0ULL, llvm::endianness::little);
  return AddressRanges.size() * 16 + 16;
}

DebugRangesSectionWriter::DebugRangesSectionWriter() {
  RangesBuffer = std::make_unique<DebugBufferVector>();
  RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);

  // Add an empty range as the first entry;
  SectionOffset +=
      writeAddressRanges(*RangesStream.get(), DebugAddressRangesVector{});
  Kind = RangesWriterKind::DebugRangesWriter;
}

uint64_t DebugRangesSectionWriter::addRanges(
    DebugAddressRangesVector &&Ranges,
    std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
  if (Ranges.empty())
    return getEmptyRangesOffset();

  const auto RI = CachedRanges.find(Ranges);
  if (RI != CachedRanges.end())
    return RI->second;

  const uint64_t EntryOffset = addRanges(Ranges);
  CachedRanges.emplace(std::move(Ranges), EntryOffset);

  return EntryOffset;
}

uint64_t DebugRangesSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
  if (Ranges.empty())
    return getEmptyRangesOffset();

  // Reading the SectionOffset and updating it should be atomic to guarantee
  // unique and correct offsets in patches.
  std::lock_guard<std::mutex> Lock(WriterMutex);
  const uint32_t EntryOffset = SectionOffset;
  SectionOffset += writeAddressRanges(*RangesStream.get(), Ranges);

  return EntryOffset;
}

uint64_t DebugRangesSectionWriter::getSectionOffset() {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  return SectionOffset;
}

DebugAddrWriter *DebugRangeListsSectionWriter::AddrWriter = nullptr;

uint64_t DebugRangeListsSectionWriter::addRanges(
    DebugAddressRangesVector &&Ranges,
    std::map<DebugAddressRangesVector, uint64_t> &CachedRanges) {
  return addRanges(Ranges);
}

struct LocListsRangelistsHeader {
  UnitLengthType UnitLength; // Size of loclist entries section, not including
                             // size of header.
  VersionType Version;
  AddressSizeType AddressSize;
  SegmentSelectorType SegmentSelector;
  OffsetEntryCountType OffsetEntryCount;
};

static std::unique_ptr<DebugBufferVector>
getDWARF5Header(const LocListsRangelistsHeader &Header) {
  std::unique_ptr<DebugBufferVector> HeaderBuffer =
      std::make_unique<DebugBufferVector>();
  std::unique_ptr<raw_svector_ostream> HeaderStream =
      std::make_unique<raw_svector_ostream>(*HeaderBuffer);

  // 7.29 length of the set of entries for this compilation unit, not including
  // the length field itself
  const uint32_t HeaderSize =
      getDWARF5RngListLocListHeaderSize() - sizeof(UnitLengthType);

  support::endian::write(*HeaderStream, Header.UnitLength + HeaderSize,
                         llvm::endianness::little);
  support::endian::write(*HeaderStream, Header.Version,
                         llvm::endianness::little);
  support::endian::write(*HeaderStream, Header.AddressSize,
                         llvm::endianness::little);
  support::endian::write(*HeaderStream, Header.SegmentSelector,
                         llvm::endianness::little);
  support::endian::write(*HeaderStream, Header.OffsetEntryCount,
                         llvm::endianness::little);
  return HeaderBuffer;
}

struct OffsetEntry {
  uint32_t Index;
  uint32_t StartOffset;
  uint32_t EndOffset;
};
template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>
static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
                         DebugAddrWriter &AddrWriter, DWARFUnit &CU,
                         uint32_t &Index, const ListEntry BaseAddressx,
                         const ListEntry OffsetPair,
                         const std::function<void(uint32_t)> &Func) {
  if (Entries.size() < 2)
    return false;
  uint64_t Base = Entries[Index].LowPC;
  std::vector<OffsetEntry> Offsets;
  uint8_t TempBuffer[64];
  while (Index < Entries.size()) {
    const DebugAddressEntry &Entry = Entries[Index];
    if (Entry.LowPC == 0)
      break;
    // In case rnglists or loclists are not sorted.
    if (Base > Entry.LowPC)
      break;
    uint32_t StartOffset = Entry.LowPC - Base;
    uint32_t EndOffset = Entry.HighPC - Base;
    if (encodeULEB128(EndOffset, TempBuffer) > 2)
      break;
    Offsets.push_back({Index, StartOffset, EndOffset});
    ++Index;
  }

  if (Offsets.size() < 2) {
    Index -= Offsets.size();
    return false;
  }

  support::endian::write(OS, static_cast<uint8_t>(BaseAddressx),
                         llvm::endianness::little);
  uint32_t BaseIndex = AddrWriter.getIndexFromAddress(Base, CU);
  encodeULEB128(BaseIndex, OS);
  for (auto &OffsetEntry : Offsets) {
    support::endian::write(OS, static_cast<uint8_t>(OffsetPair),
                           llvm::endianness::little);
    encodeULEB128(OffsetEntry.StartOffset, OS);
    encodeULEB128(OffsetEntry.EndOffset, OS);
    Func(OffsetEntry.Index);
  }
  return true;
}

uint64_t
DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
  std::lock_guard<std::mutex> Lock(WriterMutex);

  RangeEntries.push_back(CurrentOffset);
  std::sort(
      Ranges.begin(), Ranges.end(),
      [](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {
        return R1.LowPC < R2.LowPC;
      });
  for (unsigned I = 0; I < Ranges.size();) {
    if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,
                     DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU,
                                        I, dwarf::DW_RLE_base_addressx,
                                        dwarf::DW_RLE_offset_pair,
                                        [](uint32_t Index) -> void {}))
      continue;

    const DebugAddressRange &Range = Ranges[I];
    support::endian::write(*CUBodyStream,
                           static_cast<uint8_t>(dwarf::DW_RLE_startx_length),
                           llvm::endianness::little);
    uint32_t Index = AddrWriter->getIndexFromAddress(Range.LowPC, *CU);
    encodeULEB128(Index, *CUBodyStream);
    encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
    ++I;
  }

  support::endian::write(*CUBodyStream,
                         static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
                         llvm::endianness::little);
  CurrentOffset = CUBodyBuffer->size();
  return RangeEntries.size() - 1;
}

void DebugRangeListsSectionWriter::finalizeSection() {
  std::unique_ptr<DebugBufferVector> CUArrayBuffer =
      std::make_unique<DebugBufferVector>();
  std::unique_ptr<raw_svector_ostream> CUArrayStream =
      std::make_unique<raw_svector_ostream>(*CUArrayBuffer);
  constexpr uint32_t SizeOfArrayEntry = 4;
  const uint32_t SizeOfArraySection = RangeEntries.size() * SizeOfArrayEntry;
  for (uint32_t Offset : RangeEntries)
    support::endian::write(*CUArrayStream, Offset + SizeOfArraySection,
                           llvm::endianness::little);

  std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
      {static_cast<uint32_t>(SizeOfArraySection + CUBodyBuffer.get()->size()),
       5, 8, 0, static_cast<uint32_t>(RangeEntries.size())});
  *RangesStream << *Header;
  *RangesStream << *CUArrayBuffer;
  *RangesStream << *CUBodyBuffer;
  SectionOffset = RangesBuffer->size();
}

void DebugRangeListsSectionWriter::initSection(DWARFUnit &Unit) {
  CUBodyBuffer = std::make_unique<DebugBufferVector>();
  CUBodyStream = std::make_unique<raw_svector_ostream>(*CUBodyBuffer);
  RangeEntries.clear();
  CurrentOffset = 0;
  CU = &Unit;
}

void DebugARangesSectionWriter::addCURanges(uint64_t CUOffset,
                                            DebugAddressRangesVector &&Ranges) {
  std::lock_guard<std::mutex> Lock(CUAddressRangesMutex);
  CUAddressRanges.emplace(CUOffset, std::move(Ranges));
}

void DebugARangesSectionWriter::writeARangesSection(
    raw_svector_ostream &RangesStream, const CUOffsetMap &CUMap) const {
  // For reference on the format of the .debug_aranges section, see the DWARF4
  // specification, section 6.1.4 Lookup by Address
  // http://www.dwarfstd.org/doc/DWARF4.pdf
  for (const auto &CUOffsetAddressRangesPair : CUAddressRanges) {
    const uint64_t Offset = CUOffsetAddressRangesPair.first;
    const DebugAddressRangesVector &AddressRanges =
        CUOffsetAddressRangesPair.second;

    // Emit header.

    // Size of this set: 8 (size of the header) + 4 (padding after header)
    // + 2*sizeof(uint64_t) bytes for each of the ranges, plus an extra
    // pair of uint64_t's for the terminating, zero-length range.
    // Does not include size field itself.
    uint32_t Size = 8 + 4 + 2 * sizeof(uint64_t) * (AddressRanges.size() + 1);

    // Header field #1: set size.
    support::endian::write(RangesStream, Size, llvm::endianness::little);

    // Header field #2: version number, 2 as per the specification.
    support::endian::write(RangesStream, static_cast<uint16_t>(2),
                           llvm::endianness::little);

    assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
    // Header field #3: debug info offset of the correspondent compile unit.
    support::endian::write(
        RangesStream, static_cast<uint32_t>(CUMap.find(Offset)->second.Offset),
        llvm::endianness::little);

    // Header field #4: address size.
    // 8 since we only write ELF64 binaries for now.
    RangesStream << char(8);

    // Header field #5: segment size of target architecture.
    RangesStream << char(0);

    // Padding before address table - 4 bytes in the 64-bit-pointer case.
    support::endian::write(RangesStream, static_cast<uint32_t>(0),
                           llvm::endianness::little);

    writeAddressRanges(RangesStream, AddressRanges, true);
  }
}

DebugAddrWriter::DebugAddrWriter(BinaryContext *BC) : BC(BC) {
  Buffer = std::make_unique<AddressSectionBuffer>();
  AddressStream = std::make_unique<raw_svector_ostream>(*Buffer);
}

void DebugAddrWriter::AddressForDWOCU::dump() {
  std::vector<IndexAddressPair> SortedMap(indexToAddressBegin(),
                                          indexToAdddessEnd());
  // Sorting address in increasing order of indices.
  llvm::sort(SortedMap, llvm::less_first());
  for (auto &Pair : SortedMap)
    dbgs() << Twine::utohexstr(Pair.second) << "\t" << Pair.first << "\n";
}
uint32_t DebugAddrWriter::getIndexFromAddress(uint64_t Address, DWARFUnit &CU) {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  const uint64_t CUID = getCUID(CU);
  if (!AddressMaps.count(CUID))
    AddressMaps[CUID] = AddressForDWOCU();

  AddressForDWOCU &Map = AddressMaps[CUID];
  auto Entry = Map.find(Address);
  if (Entry == Map.end()) {
    auto Index = Map.getNextIndex();
    Entry = Map.insert(Address, Index).first;
  }
  return Entry->second;
}

static void updateAddressBase(DIEBuilder &DIEBlder, DebugAddrWriter &AddrWriter,
                              DWARFUnit &CU, const uint64_t Offset) {
  DIE *Die = DIEBlder.getUnitDIEbyUnit(CU);
  DIEValue GnuAddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_GNU_addr_base);
  DIEValue AddrBaseAttrInfo = Die->findAttribute(dwarf::DW_AT_addr_base);
  dwarf::Form BaseAttrForm;
  dwarf::Attribute BaseAttr;
  // For cases where Skeleton CU does not have DW_AT_GNU_addr_base
  if (!GnuAddrBaseAttrInfo && CU.getVersion() < 5)
    return;

  if (GnuAddrBaseAttrInfo) {
    BaseAttrForm = GnuAddrBaseAttrInfo.getForm();
    BaseAttr = GnuAddrBaseAttrInfo.getAttribute();
  }

  if (AddrBaseAttrInfo) {
    BaseAttrForm = AddrBaseAttrInfo.getForm();
    BaseAttr = AddrBaseAttrInfo.getAttribute();
  }

  if (GnuAddrBaseAttrInfo || AddrBaseAttrInfo) {
    DIEBlder.replaceValue(Die, BaseAttr, BaseAttrForm, DIEInteger(Offset));
  } else if (CU.getVersion() >= 5) {
    // A case where we were not using .debug_addr section, but after update
    // now using it.
    DIEBlder.addValue(Die, dwarf::DW_AT_addr_base, dwarf::DW_FORM_sec_offset,
                      DIEInteger(Offset));
  }
}

void DebugAddrWriter::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
  // Handling the case where debug information is a mix of Debug fission and
  // monolithic.
  if (!CU.getDWOId())
    return;
  const uint64_t CUID = getCUID(CU);
  auto AM = AddressMaps.find(CUID);
  // Adding to map even if it did not contribute to .debug_addr.
  // The Skeleton CU might still have DW_AT_GNU_addr_base.
  uint64_t Offset = Buffer->size();
  // If does not exist this CUs DWO section didn't contribute to .debug_addr.
  if (AM == AddressMaps.end())
    return;
  std::vector<IndexAddressPair> SortedMap(AM->second.indexToAddressBegin(),
                                          AM->second.indexToAdddessEnd());
  // Sorting address in increasing order of indices.
  llvm::sort(SortedMap, llvm::less_first());

  uint8_t AddrSize = CU.getAddressByteSize();
  uint32_t Counter = 0;
  auto WriteAddress = [&](uint64_t Address) -> void {
    ++Counter;
    switch (AddrSize) {
    default:
      assert(false && "Address Size is invalid.");
      break;
    case 4:
      support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
                             llvm::endianness::little);
      break;
    case 8:
      support::endian::write(*AddressStream, Address, llvm::endianness::little);
      break;
    }
  };

  for (const IndexAddressPair &Val : SortedMap) {
    while (Val.first > Counter)
      WriteAddress(0);
    WriteAddress(Val.second);
  }
  updateAddressBase(DIEBlder, *this, CU, Offset);
}

void DebugAddrWriterDwarf5::update(DIEBuilder &DIEBlder, DWARFUnit &CU) {
  // Need to layout all sections within .debug_addr
  // Within each section sort Address by index.
  const endianness Endian = BC->DwCtx->isLittleEndian()
                                ? llvm::endianness::little
                                : llvm::endianness::big;
  const DWARFSection &AddrSec = BC->DwCtx->getDWARFObj().getAddrSection();
  DWARFDataExtractor AddrData(BC->DwCtx->getDWARFObj(), AddrSec,
                              Endian == llvm::endianness::little, 0);
  DWARFDebugAddrTable AddrTable;
  DIDumpOptions DumpOpts;
  constexpr uint32_t HeaderSize = 8;
  const uint64_t CUID = getCUID(CU);
  const uint8_t AddrSize = CU.getAddressByteSize();
  auto AMIter = AddressMaps.find(CUID);
  // A case where CU has entry in .debug_addr, but we don't modify addresses
  // for it.
  if (AMIter == AddressMaps.end()) {
    AMIter = AddressMaps.insert({CUID, AddressForDWOCU()}).first;
    std::optional<uint64_t> BaseOffset = CU.getAddrOffsetSectionBase();
    if (!BaseOffset)
      return;
    // Address base offset is to the first entry.
    // The size of header is 8 bytes.
    uint64_t Offset = *BaseOffset - HeaderSize;
    auto Iter = UnmodifiedAddressOffsets.find(Offset);
    if (Iter != UnmodifiedAddressOffsets.end()) {
      updateAddressBase(DIEBlder, *this, CU, Iter->getSecond());
      return;
    }
    UnmodifiedAddressOffsets[Offset] = Buffer->size() + HeaderSize;
    if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddrSize,
                                      DumpOpts.WarningHandler)) {
      DumpOpts.RecoverableErrorHandler(std::move(Err));
      return;
    }

    uint32_t Index = 0;
    for (uint64_t Addr : AddrTable.getAddressEntries())
      AMIter->second.insert(Addr, Index++);
  }

  updateAddressBase(DIEBlder, *this, CU, Buffer->size() + HeaderSize);

  std::vector<IndexAddressPair> SortedMap(AMIter->second.indexToAddressBegin(),
                                          AMIter->second.indexToAdddessEnd());
  // Sorting address in increasing order of indices.
  llvm::sort(SortedMap, llvm::less_first());
  // Writing out Header
  const uint32_t Length = SortedMap.size() * AddrSize + 4;
  support::endian::write(*AddressStream, Length, Endian);
  support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);
  support::endian::write(*AddressStream, static_cast<uint8_t>(AddrSize),
                         Endian);
  support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);

  uint32_t Counter = 0;
  auto writeAddress = [&](uint64_t Address) -> void {
    ++Counter;
    switch (AddrSize) {
    default:
      llvm_unreachable("Address Size is invalid.");
      break;
    case 4:
      support::endian::write(*AddressStream, static_cast<uint32_t>(Address),
                             Endian);
      break;
    case 8:
      support::endian::write(*AddressStream, Address, Endian);
      break;
    }
  };

  for (const IndexAddressPair &Val : SortedMap) {
    while (Val.first > Counter)
      writeAddress(0);
    writeAddress(Val.second);
  }
}

void DebugLocWriter::init() {
  LocBuffer = std::make_unique<DebugBufferVector>();
  LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
  // Writing out empty location list to which all references to empty location
  // lists will point.
  if (!LocSectionOffset && DwarfVersion < 5) {
    const char Zeroes[16] = {0};
    *LocStream << StringRef(Zeroes, 16);
    LocSectionOffset += 16;
  }
}

uint32_t DebugLocWriter::LocSectionOffset = 0;
void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
                             DebugLocationsVector &LocList) {
  if (LocList.empty()) {
    replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
                        DebugLocWriter::EmptyListOffset);
    return;
  }
  // Since there is a separate DebugLocWriter for each thread,
  // we don't need a lock to read the SectionOffset and update it.
  const uint32_t EntryOffset = LocSectionOffset;

  for (const DebugLocationEntry &Entry : LocList) {
    support::endian::write(*LocStream, static_cast<uint64_t>(Entry.LowPC),
                           llvm::endianness::little);
    support::endian::write(*LocStream, static_cast<uint64_t>(Entry.HighPC),
                           llvm::endianness::little);
    support::endian::write(*LocStream, static_cast<uint16_t>(Entry.Expr.size()),
                           llvm::endianness::little);
    *LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
                            Entry.Expr.size());
    LocSectionOffset += 2 * 8 + 2 + Entry.Expr.size();
  }
  LocStream->write_zeros(16);
  LocSectionOffset += 16;
  LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen
                                                                // use
  replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
}

std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
  return std::move(LocBuffer);
}

// DWARF 4: 2.6.2
void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}

static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
  support::endian::write(Stream, static_cast<uint32_t>(4),
                         llvm::endianness::little);
  support::endian::write(Stream, static_cast<uint8_t>(dwarf::DW_LLE_start_end),
                         llvm::endianness::little);

  const char Zeroes[16] = {0};
  Stream << StringRef(Zeroes, 16);
  encodeULEB128(0, Stream);
  support::endian::write(Stream,
                         static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
                         llvm::endianness::little);
}

static void writeLegacyLocList(DIEValue &AttrInfo,
                               DebugLocationsVector &LocList,
                               DIEBuilder &DIEBldr, DIE &Die,
                               DebugAddrWriter &AddrWriter,
                               DebugBufferVector &LocBuffer, DWARFUnit &CU,
                               raw_svector_ostream &LocStream) {
  if (LocList.empty()) {
    replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
                        DebugLocWriter::EmptyListOffset);
    return;
  }

  const uint32_t EntryOffset = LocBuffer.size();
  for (const DebugLocationEntry &Entry : LocList) {
    support::endian::write(LocStream,
                           static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
                           llvm::endianness::little);
    const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
    encodeULEB128(Index, LocStream);

    support::endian::write(LocStream,
                           static_cast<uint32_t>(Entry.HighPC - Entry.LowPC),
                           llvm::endianness::little);
    support::endian::write(LocStream, static_cast<uint16_t>(Entry.Expr.size()),
                           llvm::endianness::little);
    LocStream << StringRef(reinterpret_cast<const char *>(Entry.Expr.data()),
                           Entry.Expr.size());
  }
  support::endian::write(LocStream,
                         static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
                         llvm::endianness::little);
  replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
}

static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,
                               DebugLocationsVector &LocList, DIE &Die,
                               DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter,
                               DebugBufferVector &LocBodyBuffer,
                               std::vector<uint32_t> &RelativeLocListOffsets,
                               DWARFUnit &CU,
                               raw_svector_ostream &LocBodyStream) {

  replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
                      NumberOfEntries);

  RelativeLocListOffsets.push_back(LocBodyBuffer.size());
  ++NumberOfEntries;
  if (LocList.empty()) {
    writeEmptyListDwarf5(LocBodyStream);
    return;
  }

  std::vector<uint64_t> OffsetsArray;
  auto writeExpression = [&](uint32_t Index) -> void {
    const DebugLocationEntry &Entry = LocList[Index];
    encodeULEB128(Entry.Expr.size(), LocBodyStream);
    LocBodyStream << StringRef(
        reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
  };
  for (unsigned I = 0; I < LocList.size();) {
    if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,
                     DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU,
                                         I, dwarf::DW_LLE_base_addressx,
                                         dwarf::DW_LLE_offset_pair,
                                         writeExpression))
      continue;

    const DebugLocationEntry &Entry = LocList[I];
    support::endian::write(LocBodyStream,
                           static_cast<uint8_t>(dwarf::DW_LLE_startx_length),
                           llvm::endianness::little);
    const uint32_t Index = AddrWriter.getIndexFromAddress(Entry.LowPC, CU);
    encodeULEB128(Index, LocBodyStream);
    encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);
    writeExpression(I);
    ++I;
  }

  support::endian::write(LocBodyStream,
                         static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
                         llvm::endianness::little);
}

void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,
                                 DIEValue &AttrInfo,
                                 DebugLocationsVector &LocList) {
  if (DwarfVersion < 5)
    writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, *AddrWriter, *LocBuffer,
                       CU, *LocStream);
  else
    writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
                       *AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
                       *LocBodyStream);
}

uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;
void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) {
  if (LocBodyBuffer->empty()) {
    DIEValue LocListBaseAttrInfo =
        Die.findAttribute(dwarf::DW_AT_loclists_base);
    // Pointing to first one, because it doesn't matter. There are no uses of it
    // in this CU.
    if (!isSplitDwarf() && LocListBaseAttrInfo.getType())
      DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
                           LocListBaseAttrInfo.getForm(),
                           DIEInteger(getDWARF5RngListLocListHeaderSize()));
    return;
  }

  std::unique_ptr<DebugBufferVector> LocArrayBuffer =
      std::make_unique<DebugBufferVector>();
  std::unique_ptr<raw_svector_ostream> LocArrayStream =
      std::make_unique<raw_svector_ostream>(*LocArrayBuffer);

  const uint32_t SizeOfArraySection = NumberOfEntries * sizeof(uint32_t);
  // Write out IndexArray
  for (uint32_t RelativeOffset : RelativeLocListOffsets)
    support::endian::write(
        *LocArrayStream,
        static_cast<uint32_t>(SizeOfArraySection + RelativeOffset),
        llvm::endianness::little);

  std::unique_ptr<DebugBufferVector> Header = getDWARF5Header(
      {static_cast<uint32_t>(SizeOfArraySection + LocBodyBuffer.get()->size()),
       5, 8, 0, NumberOfEntries});
  *LocStream << *Header;
  *LocStream << *LocArrayBuffer;
  *LocStream << *LocBodyBuffer;

  if (!isSplitDwarf()) {
    DIEValue LocListBaseAttrInfo =
        Die.findAttribute(dwarf::DW_AT_loclists_base);
    if (LocListBaseAttrInfo.getType()) {
      DIEBldr.replaceValue(
          &Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(),
          DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize()));
    } else {
      DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,
                       dwarf::DW_FORM_sec_offset,
                       DIEInteger(LoclistBaseOffset + Header->size()));
    }
    LoclistBaseOffset += LocBuffer->size();
  }
  clearList(RelativeLocListOffsets);
  clearList(*LocArrayBuffer);
  clearList(*LocBodyBuffer);
}

void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {
  if (DwarfVersion >= 5)
    finalizeDWARF5(DIEBldr, Die);
}

DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;

static std::string encodeLE(size_t ByteSize, uint64_t NewValue) {
  std::string LE64(ByteSize, 0);
  for (size_t I = 0; I < ByteSize; ++I) {
    LE64[I] = NewValue & 0xff;
    NewValue >>= 8;
  }
  return LE64;
}

void SimpleBinaryPatcher::addBinaryPatch(uint64_t Offset,
                                         std::string &&NewValue,
                                         uint32_t OldValueSize) {
  Patches.emplace_back(Offset, std::move(NewValue));
}

void SimpleBinaryPatcher::addBytePatch(uint64_t Offset, uint8_t Value) {
  auto Str = std::string(1, Value);
  Patches.emplace_back(Offset, std::move(Str));
}

void SimpleBinaryPatcher::addLEPatch(uint64_t Offset, uint64_t NewValue,
                                     size_t ByteSize) {
  Patches.emplace_back(Offset, encodeLE(ByteSize, NewValue));
}

void SimpleBinaryPatcher::addUDataPatch(uint64_t Offset, uint64_t Value,
                                        uint32_t OldValueSize) {
  std::string Buff;
  raw_string_ostream OS(Buff);
  encodeULEB128(Value, OS, OldValueSize);

  Patches.emplace_back(Offset, std::move(Buff));
}

void SimpleBinaryPatcher::addLE64Patch(uint64_t Offset, uint64_t NewValue) {
  addLEPatch(Offset, NewValue, 8);
}

void SimpleBinaryPatcher::addLE32Patch(uint64_t Offset, uint32_t NewValue,
                                       uint32_t OldValueSize) {
  addLEPatch(Offset, NewValue, 4);
}

std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
  std::string BinaryContentsStr = std::string(BinaryContents);
  for (const auto &Patch : Patches) {
    uint32_t Offset = Patch.first;
    const std::string &ByteSequence = Patch.second;
    assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
           "Applied patch runs over binary size.");
    for (uint64_t I = 0, Size = ByteSequence.size(); I < Size; ++I) {
      BinaryContentsStr[Offset + I] = ByteSequence[I];
    }
  }
  return BinaryContentsStr;
}

void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) {
  if (Unit.getVersion() < 5)
    return;
  const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
  const std::optional<StrOffsetsContributionDescriptor> &Contr =
      Unit.getStringOffsetsTableContribution();
  if (!Contr)
    return;
  const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
  assert(DwarfOffsetByteSize == 4 &&
         "Dwarf String Offsets Byte Size is not supported.");
  StrOffsets.reserve(Contr->Size);
  for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)
    StrOffsets.push_back(support::endian::read32le(
        StrOffsetsSection.Data.data() + Contr->Base + Offset));
}

void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) {
  IndexToAddressMap[Index] = Address;
  StrOffsetSectionWasModified = true;
}

void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
                                            DIEBuilder &DIEBldr) {
  std::optional<AttrInfo> AttrVal =
      findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
  if (!AttrVal)
    return;
  std::optional<uint64_t> Val = AttrVal->V.getAsSectionOffset();
  assert(Val && "DW_AT_str_offsets_base Value not present.");
  DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
  DIEValue StrListBaseAttrInfo =
      Die.findAttribute(dwarf::DW_AT_str_offsets_base);
  auto RetVal = ProcessedBaseOffsets.find(*Val);
  // Handling re-use of str-offsets section.
  if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {
    initialize(Unit);
    // Update String Offsets that were modified.
    for (const auto &Entry : IndexToAddressMap)
      StrOffsets[Entry.first] = Entry.second;
    // Writing out the header for each section.
    support::endian::write(*StrOffsetsStream,
                           static_cast<uint32_t>(StrOffsets.size() * 4 + 4),
                           llvm::endianness::little);
    support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),
                           llvm::endianness::little);
    support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),
                           llvm::endianness::little);

    uint64_t BaseOffset = StrOffsetsBuffer->size();
    ProcessedBaseOffsets[*Val] = BaseOffset;
    if (StrListBaseAttrInfo.getType())
      DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
                           StrListBaseAttrInfo.getForm(),
                           DIEInteger(BaseOffset));
    for (const uint32_t Offset : StrOffsets)
      support::endian::write(*StrOffsetsStream, Offset,
                             llvm::endianness::little);
  } else {
    DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
                         StrListBaseAttrInfo.getForm(),
                         DIEInteger(RetVal->second));
  }

  StrOffsetSectionWasModified = false;
  clear();
}

void DebugStrWriter::create() {
  StrBuffer = std::make_unique<DebugStrBufferVector>();
  StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
}

void DebugStrWriter::initialize() {
  auto StrSection = BC.DwCtx->getDWARFObj().getStrSection();
  (*StrStream) << StrSection;
}

uint32_t DebugStrWriter::addString(StringRef Str) {
  std::lock_guard<std::mutex> Lock(WriterMutex);
  if (StrBuffer->empty())
    initialize();
  auto Offset = StrBuffer->size();
  (*StrStream) << Str;
  StrStream->write_zeros(1);
  return Offset;
}

static void emitDwarfSetLineAddrAbs(MCStreamer &OS,
                                    MCDwarfLineTableParams Params,
                                    int64_t LineDelta, uint64_t Address,
                                    int PointerSize) {
  // emit the sequence to set the address
  OS.emitIntValue(dwarf::DW_LNS_extended_op, 1);
  OS.emitULEB128IntValue(PointerSize + 1);
  OS.emitIntValue(dwarf::DW_LNE_set_address, 1);
  OS.emitIntValue(Address, PointerSize);

  // emit the sequence for the LineDelta (from 1) and a zero address delta.
  MCDwarfLineAddr::Emit(&OS, Params, LineDelta, 0);
}

static inline void emitBinaryDwarfLineTable(
    MCStreamer *MCOS, MCDwarfLineTableParams Params,
    const DWARFDebugLine::LineTable *Table,
    const std::vector<DwarfLineTable::RowSequence> &InputSequences) {
  if (InputSequences.empty())
    return;

  constexpr uint64_t InvalidAddress = UINT64_MAX;
  unsigned FileNum = 1;
  unsigned LastLine = 1;
  unsigned Column = 0;
  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  unsigned Isa = 0;
  unsigned Discriminator = 0;
  uint64_t LastAddress = InvalidAddress;
  uint64_t PrevEndOfSequence = InvalidAddress;
  const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();

  auto emitEndOfSequence = [&](uint64_t Address) {
    MCDwarfLineAddr::Emit(MCOS, Params, INT64_MAX, Address - LastAddress);
    FileNum = 1;
    LastLine = 1;
    Column = 0;
    Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
    Isa = 0;
    Discriminator = 0;
    LastAddress = InvalidAddress;
  };

  for (const DwarfLineTable::RowSequence &Sequence : InputSequences) {
    const uint64_t SequenceStart =
        Table->Rows[Sequence.FirstIndex].Address.Address;

    // Check if we need to mark the end of the sequence.
    if (PrevEndOfSequence != InvalidAddress && LastAddress != InvalidAddress &&
        PrevEndOfSequence != SequenceStart) {
      emitEndOfSequence(PrevEndOfSequence);
    }

    for (uint32_t RowIndex = Sequence.FirstIndex;
         RowIndex <= Sequence.LastIndex; ++RowIndex) {
      const DWARFDebugLine::Row &Row = Table->Rows[RowIndex];
      int64_t LineDelta = static_cast<int64_t>(Row.Line) - LastLine;
      const uint64_t Address = Row.Address.Address;

      if (FileNum != Row.File) {
        FileNum = Row.File;
        MCOS->emitInt8(dwarf::DW_LNS_set_file);
        MCOS->emitULEB128IntValue(FileNum);
      }
      if (Column != Row.Column) {
        Column = Row.Column;
        MCOS->emitInt8(dwarf::DW_LNS_set_column);
        MCOS->emitULEB128IntValue(Column);
      }
      if (Discriminator != Row.Discriminator &&
          MCOS->getContext().getDwarfVersion() >= 4) {
        Discriminator = Row.Discriminator;
        unsigned Size = getULEB128Size(Discriminator);
        MCOS->emitInt8(dwarf::DW_LNS_extended_op);
        MCOS->emitULEB128IntValue(Size + 1);
        MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
        MCOS->emitULEB128IntValue(Discriminator);
      }
      if (Isa != Row.Isa) {
        Isa = Row.Isa;
        MCOS->emitInt8(dwarf::DW_LNS_set_isa);
        MCOS->emitULEB128IntValue(Isa);
      }
      if (Row.IsStmt != Flags) {
        Flags = Row.IsStmt;
        MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
      }
      if (Row.BasicBlock)
        MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
      if (Row.PrologueEnd)
        MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
      if (Row.EpilogueBegin)
        MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);

      // The end of the sequence is not normal in the middle of the input
      // sequence, but could happen, e.g. for assembly code.
      if (Row.EndSequence) {
        emitEndOfSequence(Address);
      } else {
        if (LastAddress == InvalidAddress)
          emitDwarfSetLineAddrAbs(*MCOS, Params, LineDelta, Address,
                                  AsmInfo->getCodePointerSize());
        else
          MCDwarfLineAddr::Emit(MCOS, Params, LineDelta, Address - LastAddress);

        LastAddress = Address;
        LastLine = Row.Line;
      }

      Discriminator = 0;
    }
    PrevEndOfSequence = Sequence.EndAddress;
  }

  // Finish with the end of the sequence.
  if (LastAddress != InvalidAddress)
    emitEndOfSequence(PrevEndOfSequence);
}

// This function is similar to the one from MCDwarfLineTable, except it handles
// end-of-sequence entries differently by utilizing line entries with
// DWARF2_FLAG_END_SEQUENCE flag.
static inline void emitDwarfLineTable(
    MCStreamer *MCOS, MCSection *Section,
    const MCLineSection::MCDwarfLineEntryCollection &LineEntries) {
  unsigned FileNum = 1;
  unsigned LastLine = 1;
  unsigned Column = 0;
  unsigned Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
  unsigned Isa = 0;
  unsigned Discriminator = 0;
  MCSymbol *LastLabel = nullptr;
  const MCAsmInfo *AsmInfo = MCOS->getContext().getAsmInfo();

  // Loop through each MCDwarfLineEntry and encode the dwarf line number table.
  for (const MCDwarfLineEntry &LineEntry : LineEntries) {
    if (LineEntry.getFlags() & DWARF2_FLAG_END_SEQUENCE) {
      MCOS->emitDwarfAdvanceLineAddr(INT64_MAX, LastLabel, LineEntry.getLabel(),
                                     AsmInfo->getCodePointerSize());
      FileNum = 1;
      LastLine = 1;
      Column = 0;
      Flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
      Isa = 0;
      Discriminator = 0;
      LastLabel = nullptr;
      continue;
    }

    int64_t LineDelta = static_cast<int64_t>(LineEntry.getLine()) - LastLine;

    if (FileNum != LineEntry.getFileNum()) {
      FileNum = LineEntry.getFileNum();
      MCOS->emitInt8(dwarf::DW_LNS_set_file);
      MCOS->emitULEB128IntValue(FileNum);
    }
    if (Column != LineEntry.getColumn()) {
      Column = LineEntry.getColumn();
      MCOS->emitInt8(dwarf::DW_LNS_set_column);
      MCOS->emitULEB128IntValue(Column);
    }
    if (Discriminator != LineEntry.getDiscriminator() &&
        MCOS->getContext().getDwarfVersion() >= 2) {
      Discriminator = LineEntry.getDiscriminator();
      unsigned Size = getULEB128Size(Discriminator);
      MCOS->emitInt8(dwarf::DW_LNS_extended_op);
      MCOS->emitULEB128IntValue(Size + 1);
      MCOS->emitInt8(dwarf::DW_LNE_set_discriminator);
      MCOS->emitULEB128IntValue(Discriminator);
    }
    if (Isa != LineEntry.getIsa()) {
      Isa = LineEntry.getIsa();
      MCOS->emitInt8(dwarf::DW_LNS_set_isa);
      MCOS->emitULEB128IntValue(Isa);
    }
    if ((LineEntry.getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
      Flags = LineEntry.getFlags();
      MCOS->emitInt8(dwarf::DW_LNS_negate_stmt);
    }
    if (LineEntry.getFlags() & DWARF2_FLAG_BASIC_BLOCK)
      MCOS->emitInt8(dwarf::DW_LNS_set_basic_block);
    if (LineEntry.getFlags() & DWARF2_FLAG_PROLOGUE_END)
      MCOS->emitInt8(dwarf::DW_LNS_set_prologue_end);
    if (LineEntry.getFlags() & DWARF2_FLAG_EPILOGUE_BEGIN)
      MCOS->emitInt8(dwarf::DW_LNS_set_epilogue_begin);

    MCSymbol *Label = LineEntry.getLabel();

    // At this point we want to emit/create the sequence to encode the delta
    // in line numbers and the increment of the address from the previous
    // Label and the current Label.
    MCOS->emitDwarfAdvanceLineAddr(LineDelta, LastLabel, Label,
                                   AsmInfo->getCodePointerSize());
    Discriminator = 0;
    LastLine = LineEntry.getLine();
    LastLabel = Label;
  }

  assert(LastLabel == nullptr && "end of sequence expected");
}

void DwarfLineTable::emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params,
                            std::optional<MCDwarfLineStr> &LineStr,
                            BinaryContext &BC) const {
  if (!RawData.empty()) {
    assert(MCLineSections.getMCLineEntries().empty() &&
           InputSequences.empty() &&
           "cannot combine raw data with new line entries");
    MCOS->emitLabel(getLabel());
    MCOS->emitBytes(RawData);
    return;
  }

  MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;

  // Put out the line tables.
  for (const auto &LineSec : MCLineSections.getMCLineEntries())
    emitDwarfLineTable(MCOS, LineSec.first, LineSec.second);

  // Emit line tables for the original code.
  emitBinaryDwarfLineTable(MCOS, Params, InputTable, InputSequences);

  // This is the end of the section, so set the value of the symbol at the end
  // of this section (that was used in a previous expression).
  MCOS->emitLabel(LineEndSym);
}

// Helper function to parse .debug_line_str, and populate one we are using.
// For functions that we do not modify we output them as raw data.
// Re-constructing .debug_line_str so that offsets are correct for those
// debug line tables.
// Bonus is that when we output a final binary we can re-use .debug_line_str
// section. So we don't have to do the SHF_ALLOC trick we did with
// .debug_line.
static void parseAndPopulateDebugLineStr(BinarySection &LineStrSection,
                                         MCDwarfLineStr &LineStr,
                                         BinaryContext &BC) {
  DataExtractor StrData(LineStrSection.getContents(),
                        BC.DwCtx->isLittleEndian(), 0);
  uint64_t Offset = 0;
  while (StrData.isValidOffset(Offset)) {
    const uint64_t StrOffset = Offset;
    Error Err = Error::success();
    const char *CStr = StrData.getCStr(&Offset, &Err);
    if (Err) {
      BC.errs() << "BOLT-ERROR: could not extract string from .debug_line_str";
      continue;
    }
    const size_t NewOffset = LineStr.addString(CStr);
    assert(StrOffset == NewOffset &&
           "New offset in .debug_line_str doesn't match original offset");
    (void)StrOffset;
    (void)NewOffset;
  }
}

void DwarfLineTable::emit(BinaryContext &BC, MCStreamer &Streamer) {
  MCAssembler &Assembler =
      static_cast<MCObjectStreamer *>(&Streamer)->getAssembler();

  MCDwarfLineTableParams Params = Assembler.getDWARFLinetableParams();

  auto &LineTables = BC.getDwarfLineTables();

  // Bail out early so we don't switch to the debug_line section needlessly and
  // in doing so create an unnecessary (if empty) section.
  if (LineTables.empty())
    return;
  // In a v5 non-split line table, put the strings in a separate section.
  std::optional<MCDwarfLineStr> LineStr;
  ErrorOr<BinarySection &> LineStrSection =
      BC.getUniqueSectionByName(".debug_line_str");

  // Some versions of GCC output DWARF5 .debug_info, but DWARF4 or lower
  // .debug_line, so need to check if section exists.
  if (LineStrSection) {
    LineStr.emplace(*BC.Ctx);
    parseAndPopulateDebugLineStr(*LineStrSection, *LineStr, BC);
  }

  // Switch to the section where the table will be emitted into.
  Streamer.switchSection(BC.MOFI->getDwarfLineSection());

  const uint16_t DwarfVersion = BC.Ctx->getDwarfVersion();
  // Handle the rest of the Compile Units.
  for (auto &CUIDTablePair : LineTables) {
    Streamer.getContext().setDwarfVersion(
        CUIDTablePair.second.getDwarfVersion());
    CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
  }

  // Resetting DWARF version for rest of the flow.
  BC.Ctx->setDwarfVersion(DwarfVersion);

  // Still need to write the section out for the ExecutionEngine, and temp in
  // memory object we are constructing.
  if (LineStr)
    LineStr->emitSection(&Streamer);
}

} // namespace bolt
} // namespace llvm
