//===- 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/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/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 <memory>
#include <optional>
#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);
}

void forEachDIEInUnit(DWARFUnit &Unit,
                      function_ref<void(const DWARFDie &)> Callback) {
  DWARFDataExtractor DebugInfoData = Unit.getDebugInfoExtractor();
  uint64_t DIEOffset = Unit.getOffset() + Unit.getHeaderSize();
  const uint64_t NextCUOffset = Unit.getNextUnitOffset();
  DWARFDebugInfoEntry DIEEntry;
  // ParentIdx is passed as 0 throughout: we visit every DIE but never
  // reconstruct the tree, so the parent linkage extractFast would record is
  // unused. The single reusable transient entry means no DIE vector is built.
  while (DIEOffset < NextCUOffset &&
         DIEEntry.extractFast(Unit, &DIEOffset, DebugInfoData, NextCUOffset,
                              /*ParentIdx=*/0)) {
    if (!DIEEntry.getAbbreviationDeclarationPtr())
      continue; // Null entry: terminator of a sibling chain.
    DWARFDie Die(&Unit, &DIEEntry);
    Callback(Die);
  }
}

[[maybe_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;
}

/// Return the size of a DWARF v5 .debug_addr contribution header.
static uint32_t getHeaderSize(dwarf::DwarfFormat Format) {
  // The initial length is followed by version(2), address size(1),
  // and segment size(1).
  return dwarf::getUnitLengthFieldByteSize(Format) + sizeof(uint16_t) +
         sizeof(uint8_t) + sizeof(uint8_t);
}

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

  Kind = RangesWriterKind::DebugRangesWriter;
}

void DebugRangesSectionWriter::initSection() {
  // Adds an empty range to the buffer.
  writeAddressRanges(*RangesStream, DebugAddressRangesVector{});
}

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 = RangesBuffer->size();
  writeAddressRanges(*RangesStream, Ranges);

  return EntryOffset;
}

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

void DebugRangesSectionWriter::appendToRangeBuffer(
    const DebugBufferVector &CUBuffer) {
  *RangesStream << CUBuffer;
}

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

struct LocListsRangelistsHeader {
  dwarf::DwarfFormat Format;
  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(Header.Format) -
                              dwarf::getUnitLengthFieldByteSize(Header.Format);

  if (Header.Format == dwarf::DwarfFormat::DWARF64)
    support::endian::write(*HeaderStream, dwarf::DW_LENGTH_DWARF64,
                           llvm::endianness::little);
  writeDWARFLengthOrOffset(*HeaderStream, Header.Format,
                           Header.UnitLength + HeaderSize);
  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;
  uint64_t StartOffset;
  uint64_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;
    uint64_t StartOffset = Entry.LowPC - Base;
    uint64_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);
  const dwarf::DwarfFormat Format = CU->getFormParams().Format;
  const uint64_t SizeOfArraySection =
      RangeEntries.size() * dwarf::getDwarfOffsetByteSize(Format);
  for (uint64_t Offset : RangeEntries)
    writeDWARFLengthOrOffset(*CUArrayStream, Format,
                             Offset + SizeOfArraySection);

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

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;
    assert(CUMap.count(Offset) && "Original CU offset is not found in CU Map");
    const CUInfo &Info = CUMap.find(Offset)->second;
    const dwarf::DwarfFormat Format = Info.Format;
    const uint8_t DwarfOffsetByteSize = dwarf::getDwarfOffsetByteSize(Format);

    // Emit header.

    // Header size: version(2) + offset(4/8) + address size(1) + segment(1).
    const uint64_t HeaderSize = sizeof(uint16_t) + DwarfOffsetByteSize +
                                sizeof(uint8_t) + sizeof(uint8_t);

    // Size of this set: header (8/12 bytes depending on the DWARF format) +
    // padding after header (4/8 bytes) + 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.
    const uint64_t Size = HeaderSize + DwarfOffsetByteSize +
                          2 * sizeof(uint64_t) * (AddressRanges.size() + 1);

    // Header field #1: set size.
    if (Format == dwarf::DwarfFormat::DWARF64)
      support::endian::write(RangesStream, dwarf::DW_LENGTH_DWARF64,
                             llvm::endianness::little);
    writeDWARFLengthOrOffset(RangesStream, Format, Size);

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

    // Header field #3: debug info offset of the correspondent compile unit.
    writeDWARFLengthOrOffset(RangesStream, Format, Info.Offset);

    // 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/8 bytes.
    writeDWARFLengthOrOffset(RangesStream, Format, 0);

    writeAddressRanges(RangesStream, AddressRanges, true);
  }
}

DebugAddrWriter::DebugAddrWriter(BinaryContext *BC,
                                 const uint8_t AddressByteSize)
    : BC(BC), AddressByteSize(AddressByteSize) {
  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);
  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::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
                                     const uint64_t Offset) {
  updateAddressBase(DIEBlder, *this, CU, Offset);
}

std::optional<uint64_t> DebugAddrWriter::finalize(const size_t BufferSize) {
  if (Map.begin() == Map.end())
    return std::nullopt;
  std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),
                                          Map.indexToAdddessEnd());
  // Sorting address in increasing order of indices.
  llvm::sort(SortedMap, llvm::less_first());

  uint32_t Counter = 0;
  auto WriteAddress = [&](uint64_t Address) -> void {
    ++Counter;
    switch (AddressByteSize) {
    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);
  }
  return std::nullopt;
}

void DebugAddrWriterDwarf5::updateAddrBase(DIEBuilder &DIEBlder, DWARFUnit &CU,
                                           const uint64_t Offset) {
  /// Header for DWARF5 has size 8 bytes in DWARF32 or 16 bytes in DWARF64,
  /// so we add it to the offset.
  updateAddressBase(DIEBlder, *this, CU, Offset + getHeaderSize(Format));
}

DenseMap<uint64_t, uint64_t> DebugAddrWriter::UnmodifiedAddressOffsets;

std::optional<uint64_t>
DebugAddrWriterDwarf5::finalize(const size_t BufferSize) {
  // 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;
  // A case where CU has entry in .debug_addr, but we don't modify addresses
  // for it.
  if (Map.begin() == Map.end()) {
    if (!AddrOffsetSectionBase)
      return std::nullopt;
    // Address base offset is to the first entry.
    uint64_t Offset = *AddrOffsetSectionBase - getHeaderSize(Format);
    auto Iter = UnmodifiedAddressOffsets.find(Offset);
    if (Iter != UnmodifiedAddressOffsets.end())
      return Iter->second;
    UnmodifiedAddressOffsets[Offset] = BufferSize;
    if (Error Err = AddrTable.extract(AddrData, &Offset, 5, AddressByteSize,
                                      DumpOpts.WarningHandler)) {
      DumpOpts.RecoverableErrorHandler(std::move(Err));
      return std::nullopt;
    }
    uint32_t Index = 0;
    for (uint64_t Addr : AddrTable.getAddressEntries())
      Map.insert(Addr, Index++);
  }

  std::vector<IndexAddressPair> SortedMap(Map.indexToAddressBegin(),
                                          Map.indexToAdddessEnd());
  // Sorting address in increasing order of indices.
  llvm::sort(SortedMap, llvm::less_first());
  // Writing out Header
  const uint64_t Length = SortedMap.size() * AddressByteSize + 4;
  if (Format == dwarf::DwarfFormat::DWARF64)
    support::endian::write(*AddressStream, dwarf::DW_LENGTH_DWARF64, Endian);
  writeDWARFLengthOrOffset(*AddressStream, Format, Length, Endian);
  support::endian::write(*AddressStream, static_cast<uint16_t>(5), Endian);
  support::endian::write(*AddressStream, static_cast<uint8_t>(AddressByteSize),
                         Endian);
  support::endian::write(*AddressStream, static_cast<uint8_t>(0), Endian);

  uint32_t Counter = 0;
  auto writeAddress = [&](uint64_t Address) -> void {
    ++Counter;
    switch (AddressByteSize) {
    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);
  }
  return std::nullopt;
}

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 (DwarfVersion < 5) {
    const char Zeroes[16] = {0};
    *LocStream << StringRef(Zeroes, 16);
  }
}

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 = LocBuffer->size();

  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());
  }
  LocStream->write_zeros(16);
  LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset});
  replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
  LocListPatches.push_back({&Die, AttrInfo.getAttribute(), AttrInfo.getForm()});
}

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

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

/// Rebases all pending location list offsets by adding \p Base,
/// updating the corresponding attributes in each patched DIE.
void DebugLocWriter::applyBase(DIEBuilder &DIEBldr, uint64_t Base) {
  if (Base == 0) {
    LocListPatches.clear();
    return;
  }
  for (const LocListPatch &LP : LocListPatches) {
    if (!LP.Die)
      continue;
    DIEValue Cur = LP.Die->findAttribute(LP.Attr);
    if (!Cur.getType())
      continue;
    uint64_t OldVal = Cur.getDIEInteger().getValue();
    if (OldVal == DebugLocWriter::EmptyListOffset)
      continue;
    DIEBldr.replaceValue(LP.Die, LP.Attr, LP.Form, DIEInteger(OldVal + Base));
  }
  LocListPatches.clear();
}

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<uint64_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;
  }

  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);
}

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(
                               CU.getFormParams().Format)));
    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 dwarf::DwarfFormat Format = CU.getFormParams().Format;
  const uint64_t SizeOfArraySection =
      NumberOfEntries * dwarf::getDwarfOffsetByteSize(Format);
  // Write out IndexArray
  for (uint64_t RelativeOffset : RelativeLocListOffsets)
    writeDWARFLengthOrOffset(*LocArrayStream, Format,
                             SizeOfArraySection + RelativeOffset);

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

  if (!isSplitDwarf()) {
    const uint64_t LocalBase = getDWARF5RngListLocListHeaderSize(Format);
    DIEValue LocListBaseAttrInfo =
        Die.findAttribute(dwarf::DW_AT_loclists_base);
    if (LocListBaseAttrInfo.getType()) {
      DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
                           LocListBaseAttrInfo.getForm(),
                           DIEInteger(LocalBase));
    } else {
      DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,
                       dwarf::DW_FORM_sec_offset, DIEInteger(LocalBase));
    }
  }
  clearList(RelativeLocListOffsets);
  clearList(*LocArrayBuffer);
  clearList(*LocBodyBuffer);
}

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

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) {
    uint64_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 dwarf::DwarfFormat Format = Unit.getFormParams().Format;
  const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
  StrOffsets.reserve(Contr->Size / DwarfOffsetByteSize);
  for (uint64_t Offset = 0; Offset < Contr->Size;
       Offset += DwarfOffsetByteSize) {
    uint64_t Value =
        Format == dwarf::DwarfFormat::DWARF32
            ? support::endian::read32le(StrOffsetsSection.Data.data() +
                                        Contr->Base + Offset)
            : support::endian::read64le(StrOffsetsSection.Data.data() +
                                        Contr->Base + Offset);
    StrOffsets.push_back(Value);
  }
}

void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint64_t Address,
                                             const DWARFUnit &Unit) {
  assert(DebugStrOffsetFinalized.count(Unit.getOffset()) == 0 &&
         "Cannot update address map since debug_str_offsets was already "
         "finalized for this CU.");
  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 && !Unit.isDWOUnit())
    return;
  std::optional<uint64_t> Val = std::nullopt;
  if (AttrVal) {
    Val = AttrVal->V.getAsSectionOffset();
  } else {
    if (!Unit.isDWOUnit())
      BC.errs() << "BOLT-WARNING: [internal-dwarf-error]: "
                   "DW_AT_str_offsets_base Value not present\n";
    Val = 0;
  }
  DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
  DIEValue StrListBaseAttrInfo =
      Die.findAttribute(dwarf::DW_AT_str_offsets_base);
  auto RetVal = ProcessedBaseOffsets.find(*Val);
  // Handling reuse 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;
    const dwarf::DwarfFormat Format = Unit.getFormParams().Format;
    // Writing out the header for each section.
    if (Format == dwarf::DwarfFormat::DWARF64)
      support::endian::write(*StrOffsetsStream, dwarf::DW_LENGTH_DWARF64,
                             llvm::endianness::little);
    writeDWARFLengthOrOffset(*StrOffsetsStream, Format,
                             StrOffsets.size() *
                                     dwarf::getDwarfOffsetByteSize(Format) +
                                 sizeof(uint16_t) + sizeof(uint16_t));
    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 uint64_t Offset : StrOffsets)
      writeDWARFLengthOrOffset(*StrOffsetsStream, Format, Offset);
  } else {
    DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
                         StrListBaseAttrInfo.getForm(),
                         DIEInteger(RetVal->second));
  }

  StrOffsetSectionWasModified = false;
  assert(DebugStrOffsetFinalized.insert(Unit.getOffset()).second &&
         "debug_str_offsets was already finalized for this CU.");
  clear();
}

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

void DebugStrWriter::initialize() {
  StringRef StrSection;
  if (IsDWO)
    StrSection = DwCtx.getDWARFObj().getStrDWOSection();
  else
    StrSection = 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 reuse .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());
  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();
  const dwarf::DwarfFormat Format = BC.Ctx->getDwarfFormat();
  // Handle the rest of the Compile Units.
  for (auto &CUIDTablePair : LineTables) {
    Streamer.getContext().setDwarfVersion(
        CUIDTablePair.second.getDwarfVersion());
    Streamer.getContext().setDwarfFormat(CUIDTablePair.second.getFormat());
    CUIDTablePair.second.emitCU(&Streamer, Params, LineStr, BC);
  }

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

  // 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
