//===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// The DWARF component of yaml2obj. Provided as library code for tests.
///
//===----------------------------------------------------------------------===//

#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>

using namespace llvm;

template <typename T>
static void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {
  if (IsLittleEndian != sys::IsLittleEndianHost)
    sys::swapByteOrder(Integer);
  OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));
}

static Error writeVariableSizedInteger(uint64_t Integer, size_t Size,
                                       raw_ostream &OS, bool IsLittleEndian) {
  if (8 == Size)
    writeInteger((uint64_t)Integer, OS, IsLittleEndian);
  else if (4 == Size)
    writeInteger((uint32_t)Integer, OS, IsLittleEndian);
  else if (2 == Size)
    writeInteger((uint16_t)Integer, OS, IsLittleEndian);
  else if (1 == Size)
    writeInteger((uint8_t)Integer, OS, IsLittleEndian);
  else
    return createStringError(errc::not_supported,
                             "invalid integer write size: %zu", Size);

  return Error::success();
}

static void ZeroFillBytes(raw_ostream &OS, size_t Size) {
  std::vector<uint8_t> FillData(Size, 0);
  OS.write(reinterpret_cast<char *>(FillData.data()), Size);
}

static void writeInitialLength(const dwarf::DwarfFormat Format,
                               const uint64_t Length, raw_ostream &OS,
                               bool IsLittleEndian) {
  bool IsDWARF64 = Format == dwarf::DWARF64;
  if (IsDWARF64)
    cantFail(writeVariableSizedInteger(dwarf::DW_LENGTH_DWARF64, 4, OS,
                                       IsLittleEndian));
  cantFail(
      writeVariableSizedInteger(Length, IsDWARF64 ? 8 : 4, OS, IsLittleEndian));
}

static void writeDWARFOffset(uint64_t Offset, dwarf::DwarfFormat Format,
                             raw_ostream &OS, bool IsLittleEndian) {
  cantFail(writeVariableSizedInteger(Offset, Format == dwarf::DWARF64 ? 8 : 4,
                                     OS, IsLittleEndian));
}

Error DWARFYAML::emitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {
  for (StringRef Str : *DI.DebugStrings) {
    OS.write(Str.data(), Str.size());
    OS.write('\0');
  }

  return Error::success();
}

StringRef DWARFYAML::Data::getAbbrevTableContentByIndex(uint64_t Index) const {
  assert(Index < DebugAbbrev.size() &&
         "Index should be less than the size of DebugAbbrev array");
  auto [It, Inserted] = AbbrevTableContents.try_emplace(Index);
  if (!Inserted)
    return It->second;

  raw_string_ostream OS(It->second);

  uint64_t AbbrevCode = 0;
  for (const DWARFYAML::Abbrev &AbbrevDecl : DebugAbbrev[Index].Table) {
    AbbrevCode = AbbrevDecl.Code ? (uint64_t)*AbbrevDecl.Code : AbbrevCode + 1;
    encodeULEB128(AbbrevCode, OS);
    encodeULEB128(AbbrevDecl.Tag, OS);
    OS.write(AbbrevDecl.Children);
    for (const auto &Attr : AbbrevDecl.Attributes) {
      encodeULEB128(Attr.Attribute, OS);
      encodeULEB128(Attr.Form, OS);
      if (Attr.Form == dwarf::DW_FORM_implicit_const)
        encodeSLEB128(Attr.Value, OS);
    }
    encodeULEB128(0, OS);
    encodeULEB128(0, OS);
  }

  // The abbreviations for a given compilation unit end with an entry
  // consisting of a 0 byte for the abbreviation code.
  OS.write_zeros(1);

  return It->second;
}

Error DWARFYAML::emitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
  for (uint64_t I = 0; I < DI.DebugAbbrev.size(); ++I) {
    StringRef AbbrevTableContent = DI.getAbbrevTableContentByIndex(I);
    OS.write(AbbrevTableContent.data(), AbbrevTableContent.size());
  }

  return Error::success();
}

Error DWARFYAML::emitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
  assert(DI.DebugAranges && "unexpected emitDebugAranges() call");
  for (const auto &Range : *DI.DebugAranges) {
    uint8_t AddrSize;
    if (Range.AddrSize)
      AddrSize = *Range.AddrSize;
    else
      AddrSize = DI.Is64BitAddrSize ? 8 : 4;

    uint64_t Length = 4; // sizeof(version) 2 + sizeof(address_size) 1 +
                         // sizeof(segment_selector_size) 1
    Length +=
        Range.Format == dwarf::DWARF64 ? 8 : 4; // sizeof(debug_info_offset)

    const uint64_t HeaderLength =
        Length + (Range.Format == dwarf::DWARF64
                      ? 12
                      : 4); // sizeof(unit_header) = 12 (DWARF64) or 4 (DWARF32)
    const uint64_t PaddedHeaderLength = alignTo(HeaderLength, AddrSize * 2);

    if (Range.Length) {
      Length = *Range.Length;
    } else {
      Length += PaddedHeaderLength - HeaderLength;
      Length += AddrSize * 2 * (Range.Descriptors.size() + 1);
    }

    writeInitialLength(Range.Format, Length, OS, DI.IsLittleEndian);
    writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
    writeDWARFOffset(Range.CuOffset, Range.Format, OS, DI.IsLittleEndian);
    writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
    ZeroFillBytes(OS, PaddedHeaderLength - HeaderLength);

    for (const auto &Descriptor : Range.Descriptors) {
      if (Error Err = writeVariableSizedInteger(Descriptor.Address, AddrSize,
                                                OS, DI.IsLittleEndian))
        return createStringError(errc::not_supported,
                                 "unable to write debug_aranges address: %s",
                                 toString(std::move(Err)).c_str());
      cantFail(writeVariableSizedInteger(Descriptor.Length, AddrSize, OS,
                                         DI.IsLittleEndian));
    }
    ZeroFillBytes(OS, AddrSize * 2);
  }

  return Error::success();
}

Error DWARFYAML::emitDebugRanges(raw_ostream &OS, const DWARFYAML::Data &DI) {
  const size_t RangesOffset = OS.tell();
  uint64_t EntryIndex = 0;
  for (const auto &DebugRanges : *DI.DebugRanges) {
    const size_t CurrOffset = OS.tell() - RangesOffset;
    if (DebugRanges.Offset && (uint64_t)*DebugRanges.Offset < CurrOffset)
      return createStringError(errc::invalid_argument,
                               "'Offset' for 'debug_ranges' with index " +
                                   Twine(EntryIndex) +
                                   " must be greater than or equal to the "
                                   "number of bytes written already (0x" +
                                   Twine::utohexstr(CurrOffset) + ")");
    if (DebugRanges.Offset)
      ZeroFillBytes(OS, *DebugRanges.Offset - CurrOffset);

    uint8_t AddrSize;
    if (DebugRanges.AddrSize)
      AddrSize = *DebugRanges.AddrSize;
    else
      AddrSize = DI.Is64BitAddrSize ? 8 : 4;
    for (const auto &Entry : DebugRanges.Entries) {
      if (Error Err = writeVariableSizedInteger(Entry.LowOffset, AddrSize, OS,
                                                DI.IsLittleEndian))
        return createStringError(
            errc::not_supported,
            "unable to write debug_ranges address offset: %s",
            toString(std::move(Err)).c_str());
      cantFail(writeVariableSizedInteger(Entry.HighOffset, AddrSize, OS,
                                         DI.IsLittleEndian));
    }
    ZeroFillBytes(OS, AddrSize * 2);
    ++EntryIndex;
  }

  return Error::success();
}

static Error emitPubSection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,
                            bool IsLittleEndian, bool IsGNUPubSec = false) {
  writeInitialLength(Sect.Format, Sect.Length, OS, IsLittleEndian);
  writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
  writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
  writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
  for (const auto &Entry : Sect.Entries) {
    writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
    if (IsGNUPubSec)
      writeInteger((uint8_t)Entry.Descriptor, OS, IsLittleEndian);
    OS.write(Entry.Name.data(), Entry.Name.size());
    OS.write('\0');
  }
  return Error::success();
}

Error DWARFYAML::emitDebugPubnames(raw_ostream &OS, const Data &DI) {
  assert(DI.PubNames && "unexpected emitDebugPubnames() call");
  return emitPubSection(OS, *DI.PubNames, DI.IsLittleEndian);
}

Error DWARFYAML::emitDebugPubtypes(raw_ostream &OS, const Data &DI) {
  assert(DI.PubTypes && "unexpected emitDebugPubtypes() call");
  return emitPubSection(OS, *DI.PubTypes, DI.IsLittleEndian);
}

Error DWARFYAML::emitDebugGNUPubnames(raw_ostream &OS, const Data &DI) {
  assert(DI.GNUPubNames && "unexpected emitDebugGNUPubnames() call");
  return emitPubSection(OS, *DI.GNUPubNames, DI.IsLittleEndian,
                        /*IsGNUStyle=*/true);
}

Error DWARFYAML::emitDebugGNUPubtypes(raw_ostream &OS, const Data &DI) {
  assert(DI.GNUPubTypes && "unexpected emitDebugGNUPubtypes() call");
  return emitPubSection(OS, *DI.GNUPubTypes, DI.IsLittleEndian,
                        /*IsGNUStyle=*/true);
}

static Expected<uint64_t> writeDIE(const DWARFYAML::Data &DI, uint64_t CUIndex,
                                   uint64_t AbbrevTableID,
                                   const dwarf::FormParams &Params,
                                   const DWARFYAML::Entry &Entry,
                                   raw_ostream &OS, bool IsLittleEndian) {
  uint64_t EntryBegin = OS.tell();
  encodeULEB128(Entry.AbbrCode, OS);
  uint32_t AbbrCode = Entry.AbbrCode;
  if (AbbrCode == 0 || Entry.Values.empty())
    return OS.tell() - EntryBegin;

  Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
      DI.getAbbrevTableInfoByID(AbbrevTableID);
  if (!AbbrevTableInfoOrErr)
    return createStringError(errc::invalid_argument,
                             toString(AbbrevTableInfoOrErr.takeError()) +
                                 " for compilation unit with index " +
                                 utostr(CUIndex));

  ArrayRef<DWARFYAML::Abbrev> AbbrevDecls(
      DI.DebugAbbrev[AbbrevTableInfoOrErr->Index].Table);

  if (AbbrCode > AbbrevDecls.size())
    return createStringError(
        errc::invalid_argument,
        "abbrev code must be less than or equal to the number of "
        "entries in abbreviation table");
  const DWARFYAML::Abbrev &Abbrev = AbbrevDecls[AbbrCode - 1];
  auto FormVal = Entry.Values.begin();
  auto AbbrForm = Abbrev.Attributes.begin();
  for (; FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
       ++FormVal, ++AbbrForm) {
    dwarf::Form Form = AbbrForm->Form;
    bool Indirect;
    do {
      Indirect = false;
      switch (Form) {
      case dwarf::DW_FORM_addr:
        // TODO: Test this error.
        if (Error Err = writeVariableSizedInteger(
                FormVal->Value, Params.AddrSize, OS, IsLittleEndian))
          return std::move(Err);
        break;
      case dwarf::DW_FORM_ref_addr:
        // TODO: Test this error.
        if (Error Err = writeVariableSizedInteger(FormVal->Value,
                                                  Params.getRefAddrByteSize(),
                                                  OS, IsLittleEndian))
          return std::move(Err);
        break;
      case dwarf::DW_FORM_exprloc:
      case dwarf::DW_FORM_block:
        encodeULEB128(FormVal->BlockData.size(), OS);
        OS.write((const char *)FormVal->BlockData.data(),
                 FormVal->BlockData.size());
        break;
      case dwarf::DW_FORM_block1: {
        writeInteger((uint8_t)FormVal->BlockData.size(), OS, IsLittleEndian);
        OS.write((const char *)FormVal->BlockData.data(),
                 FormVal->BlockData.size());
        break;
      }
      case dwarf::DW_FORM_block2: {
        writeInteger((uint16_t)FormVal->BlockData.size(), OS, IsLittleEndian);
        OS.write((const char *)FormVal->BlockData.data(),
                 FormVal->BlockData.size());
        break;
      }
      case dwarf::DW_FORM_block4: {
        writeInteger((uint32_t)FormVal->BlockData.size(), OS, IsLittleEndian);
        OS.write((const char *)FormVal->BlockData.data(),
                 FormVal->BlockData.size());
        break;
      }
      case dwarf::DW_FORM_strx:
      case dwarf::DW_FORM_addrx:
      case dwarf::DW_FORM_rnglistx:
      case dwarf::DW_FORM_loclistx:
      case dwarf::DW_FORM_udata:
      case dwarf::DW_FORM_ref_udata:
      case dwarf::DW_FORM_GNU_addr_index:
      case dwarf::DW_FORM_GNU_str_index:
        encodeULEB128(FormVal->Value, OS);
        break;
      case dwarf::DW_FORM_data1:
      case dwarf::DW_FORM_ref1:
      case dwarf::DW_FORM_flag:
      case dwarf::DW_FORM_strx1:
      case dwarf::DW_FORM_addrx1:
        writeInteger((uint8_t)FormVal->Value, OS, IsLittleEndian);
        break;
      case dwarf::DW_FORM_data2:
      case dwarf::DW_FORM_ref2:
      case dwarf::DW_FORM_strx2:
      case dwarf::DW_FORM_addrx2:
        writeInteger((uint16_t)FormVal->Value, OS, IsLittleEndian);
        break;
      case dwarf::DW_FORM_data4:
      case dwarf::DW_FORM_ref4:
      case dwarf::DW_FORM_ref_sup4:
      case dwarf::DW_FORM_strx4:
      case dwarf::DW_FORM_addrx4:
        writeInteger((uint32_t)FormVal->Value, OS, IsLittleEndian);
        break;
      case dwarf::DW_FORM_data8:
      case dwarf::DW_FORM_ref8:
      case dwarf::DW_FORM_ref_sup8:
      case dwarf::DW_FORM_ref_sig8:
        writeInteger((uint64_t)FormVal->Value, OS, IsLittleEndian);
        break;
      case dwarf::DW_FORM_sdata:
        encodeSLEB128(FormVal->Value, OS);
        break;
      case dwarf::DW_FORM_string:
        OS.write(FormVal->CStr.data(), FormVal->CStr.size());
        OS.write('\0');
        break;
      case dwarf::DW_FORM_indirect:
        encodeULEB128(FormVal->Value, OS);
        Indirect = true;
        Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
        ++FormVal;
        break;
      case dwarf::DW_FORM_strp:
      case dwarf::DW_FORM_sec_offset:
      case dwarf::DW_FORM_GNU_ref_alt:
      case dwarf::DW_FORM_GNU_strp_alt:
      case dwarf::DW_FORM_line_strp:
      case dwarf::DW_FORM_strp_sup:
        cantFail(writeVariableSizedInteger(FormVal->Value,
                                           Params.getDwarfOffsetByteSize(), OS,
                                           IsLittleEndian));
        break;
      default:
        break;
      }
    } while (Indirect);
  }

  return OS.tell() - EntryBegin;
}

Error DWARFYAML::emitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
  for (uint64_t I = 0; I < DI.Units.size(); ++I) {
    const DWARFYAML::Unit &Unit = DI.Units[I];
    uint8_t AddrSize;
    if (Unit.AddrSize)
      AddrSize = *Unit.AddrSize;
    else
      AddrSize = DI.Is64BitAddrSize ? 8 : 4;
    dwarf::FormParams Params = {Unit.Version, AddrSize, Unit.Format};
    uint64_t Length = 3; // sizeof(version) + sizeof(address_size)
    Length += Params.getDwarfOffsetByteSize(); // sizeof(debug_abbrev_offset)
    if (Unit.Version >= 5) {
      ++Length; // sizeof(unit_type)
      switch (Unit.Type) {
      case dwarf::DW_UT_compile:
      case dwarf::DW_UT_partial:
      default:
        break;
      case dwarf::DW_UT_type:
      case dwarf::DW_UT_split_type:
        // sizeof(type_signature) + sizeof(type_offset)
        Length += 8 + Params.getDwarfOffsetByteSize();
        break;
      case dwarf::DW_UT_skeleton:
      case dwarf::DW_UT_split_compile:
        Length += 8; // sizeof(dwo_id)
      }
    }

    // Since the length of the current compilation unit is undetermined yet, we
    // firstly write the content of the compilation unit to a buffer to
    // calculate it and then serialize the buffer content to the actual output
    // stream.
    std::string EntryBuffer;
    raw_string_ostream EntryBufferOS(EntryBuffer);

    uint64_t AbbrevTableID = Unit.AbbrevTableID.value_or(I);
    for (const DWARFYAML::Entry &Entry : Unit.Entries) {
      if (Expected<uint64_t> EntryLength =
              writeDIE(DI, I, AbbrevTableID, Params, Entry, EntryBufferOS,
                       DI.IsLittleEndian))
        Length += *EntryLength;
      else
        return EntryLength.takeError();
    }

    // If the length is specified in the YAML description, we use it instead of
    // the actual length.
    if (Unit.Length)
      Length = *Unit.Length;

    writeInitialLength(Unit.Format, Length, OS, DI.IsLittleEndian);
    writeInteger((uint16_t)Unit.Version, OS, DI.IsLittleEndian);

    uint64_t AbbrevTableOffset = 0;
    if (Unit.AbbrOffset) {
      AbbrevTableOffset = *Unit.AbbrOffset;
    } else {
      if (Expected<DWARFYAML::Data::AbbrevTableInfo> AbbrevTableInfoOrErr =
              DI.getAbbrevTableInfoByID(AbbrevTableID)) {
        AbbrevTableOffset = AbbrevTableInfoOrErr->Offset;
      } else {
        // The current compilation unit may not have DIEs and it will not be
        // able to find the associated abbrev table. We consume the error and
        // assign 0 to the debug_abbrev_offset in such circumstances.
        consumeError(AbbrevTableInfoOrErr.takeError());
      }
    }

    if (Unit.Version >= 5) {
      writeInteger((uint8_t)Unit.Type, OS, DI.IsLittleEndian);
      writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
      writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
      switch (Unit.Type) {
      case dwarf::DW_UT_compile:
      case dwarf::DW_UT_partial:
      default:
        break;
      case dwarf::DW_UT_type:
      case dwarf::DW_UT_split_type:
        writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);
        writeDWARFOffset(Unit.TypeOffset, Unit.Format, OS, DI.IsLittleEndian);
        break;
      case dwarf::DW_UT_skeleton:
      case dwarf::DW_UT_split_compile:
        writeInteger(Unit.TypeSignatureOrDwoID, OS, DI.IsLittleEndian);
        break;
      }
    } else {
      writeDWARFOffset(AbbrevTableOffset, Unit.Format, OS, DI.IsLittleEndian);
      writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    }

    OS.write(EntryBuffer.data(), EntryBuffer.size());
  }

  return Error::success();
}

static void emitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
  OS.write(File.Name.data(), File.Name.size());
  OS.write('\0');
  encodeULEB128(File.DirIdx, OS);
  encodeULEB128(File.ModTime, OS);
  encodeULEB128(File.Length, OS);
}

static void writeExtendedOpcode(const DWARFYAML::LineTableOpcode &Op,
                                uint8_t AddrSize, bool IsLittleEndian,
                                raw_ostream &OS) {
  // The first byte of extended opcodes is a zero byte. The next bytes are an
  // ULEB128 integer giving the number of bytes in the instruction itself (does
  // not include the first zero byte or the size). We serialize the instruction
  // itself into the OpBuffer and then write the size of the buffer and the
  // buffer to the real output stream.
  std::string OpBuffer;
  raw_string_ostream OpBufferOS(OpBuffer);
  writeInteger((uint8_t)Op.SubOpcode, OpBufferOS, IsLittleEndian);
  switch (Op.SubOpcode) {
  case dwarf::DW_LNE_set_address:
    cantFail(writeVariableSizedInteger(Op.Data, AddrSize, OpBufferOS,
                                       IsLittleEndian));
    break;
  case dwarf::DW_LNE_define_file:
    emitFileEntry(OpBufferOS, Op.FileEntry);
    break;
  case dwarf::DW_LNE_set_discriminator:
    encodeULEB128(Op.Data, OpBufferOS);
    break;
  case dwarf::DW_LNE_end_sequence:
    break;
  default:
    for (auto OpByte : Op.UnknownOpcodeData)
      writeInteger((uint8_t)OpByte, OpBufferOS, IsLittleEndian);
  }
  uint64_t ExtLen = Op.ExtLen.value_or(OpBuffer.size());
  encodeULEB128(ExtLen, OS);
  OS.write(OpBuffer.data(), OpBuffer.size());
}

static void writeLineTableOpcode(const DWARFYAML::LineTableOpcode &Op,
                                 uint8_t OpcodeBase, uint8_t AddrSize,
                                 raw_ostream &OS, bool IsLittleEndian) {
  writeInteger((uint8_t)Op.Opcode, OS, IsLittleEndian);
  if (Op.Opcode == 0) {
    writeExtendedOpcode(Op, AddrSize, IsLittleEndian, OS);
  } else if (Op.Opcode < OpcodeBase) {
    switch (Op.Opcode) {
    case dwarf::DW_LNS_copy:
    case dwarf::DW_LNS_negate_stmt:
    case dwarf::DW_LNS_set_basic_block:
    case dwarf::DW_LNS_const_add_pc:
    case dwarf::DW_LNS_set_prologue_end:
    case dwarf::DW_LNS_set_epilogue_begin:
      break;

    case dwarf::DW_LNS_advance_pc:
    case dwarf::DW_LNS_set_file:
    case dwarf::DW_LNS_set_column:
    case dwarf::DW_LNS_set_isa:
      encodeULEB128(Op.Data, OS);
      break;

    case dwarf::DW_LNS_advance_line:
      encodeSLEB128(Op.SData, OS);
      break;

    case dwarf::DW_LNS_fixed_advance_pc:
      writeInteger((uint16_t)Op.Data, OS, IsLittleEndian);
      break;

    default:
      for (auto OpData : Op.StandardOpcodeData) {
        encodeULEB128(OpData, OS);
      }
    }
  }
}

static std::vector<uint8_t>
getStandardOpcodeLengths(uint16_t Version, std::optional<uint8_t> OpcodeBase) {
  // If the opcode_base field isn't specified, we returns the
  // standard_opcode_lengths array according to the version by default.
  std::vector<uint8_t> StandardOpcodeLengths{0, 1, 1, 1, 1, 0,
                                             0, 0, 1, 0, 0, 1};
  if (Version == 2) {
    // DWARF v2 uses the same first 9 standard opcodes as v3-5.
    StandardOpcodeLengths.resize(9);
  } else if (OpcodeBase) {
    StandardOpcodeLengths.resize(*OpcodeBase > 0 ? *OpcodeBase - 1 : 0, 0);
  }
  return StandardOpcodeLengths;
}

Error DWARFYAML::emitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
  for (const DWARFYAML::LineTable &LineTable : DI.DebugLines) {
    // Buffer holds the bytes following the header_length (or prologue_length in
    // DWARFv2) field to the end of the line number program itself.
    std::string Buffer;
    raw_string_ostream BufferOS(Buffer);

    writeInteger(LineTable.MinInstLength, BufferOS, DI.IsLittleEndian);
    // TODO: Add support for emitting DWARFv5 line table.
    if (LineTable.Version >= 4)
      writeInteger(LineTable.MaxOpsPerInst, BufferOS, DI.IsLittleEndian);
    writeInteger(LineTable.DefaultIsStmt, BufferOS, DI.IsLittleEndian);
    writeInteger(LineTable.LineBase, BufferOS, DI.IsLittleEndian);
    writeInteger(LineTable.LineRange, BufferOS, DI.IsLittleEndian);

    std::vector<uint8_t> StandardOpcodeLengths =
        LineTable.StandardOpcodeLengths.value_or(
            getStandardOpcodeLengths(LineTable.Version, LineTable.OpcodeBase));
    uint8_t OpcodeBase = LineTable.OpcodeBase
                             ? *LineTable.OpcodeBase
                             : StandardOpcodeLengths.size() + 1;
    writeInteger(OpcodeBase, BufferOS, DI.IsLittleEndian);
    for (uint8_t OpcodeLength : StandardOpcodeLengths)
      writeInteger(OpcodeLength, BufferOS, DI.IsLittleEndian);

    for (StringRef IncludeDir : LineTable.IncludeDirs) {
      BufferOS.write(IncludeDir.data(), IncludeDir.size());
      BufferOS.write('\0');
    }
    BufferOS.write('\0');

    for (const DWARFYAML::File &File : LineTable.Files)
      emitFileEntry(BufferOS, File);
    BufferOS.write('\0');

    uint64_t HeaderLength =
        LineTable.PrologueLength ? *LineTable.PrologueLength : Buffer.size();

    for (const DWARFYAML::LineTableOpcode &Op : LineTable.Opcodes)
      writeLineTableOpcode(Op, OpcodeBase, DI.Is64BitAddrSize ? 8 : 4, BufferOS,
                           DI.IsLittleEndian);

    uint64_t Length;
    if (LineTable.Length) {
      Length = *LineTable.Length;
    } else {
      Length = 2; // sizeof(version)
      Length +=
          (LineTable.Format == dwarf::DWARF64 ? 8 : 4); // sizeof(header_length)
      Length += Buffer.size();
    }

    writeInitialLength(LineTable.Format, Length, OS, DI.IsLittleEndian);
    writeInteger(LineTable.Version, OS, DI.IsLittleEndian);
    writeDWARFOffset(HeaderLength, LineTable.Format, OS, DI.IsLittleEndian);
    OS.write(Buffer.data(), Buffer.size());
  }

  return Error::success();
}

Error DWARFYAML::emitDebugAddr(raw_ostream &OS, const Data &DI) {
  for (const AddrTableEntry &TableEntry : *DI.DebugAddr) {
    uint8_t AddrSize;
    if (TableEntry.AddrSize)
      AddrSize = *TableEntry.AddrSize;
    else
      AddrSize = DI.Is64BitAddrSize ? 8 : 4;

    uint64_t Length;
    if (TableEntry.Length)
      Length = (uint64_t)*TableEntry.Length;
    else
      // 2 (version) + 1 (address_size) + 1 (segment_selector_size) = 4
      Length = 4 + (AddrSize + TableEntry.SegSelectorSize) *
                       TableEntry.SegAddrPairs.size();

    writeInitialLength(TableEntry.Format, Length, OS, DI.IsLittleEndian);
    writeInteger((uint16_t)TableEntry.Version, OS, DI.IsLittleEndian);
    writeInteger((uint8_t)AddrSize, OS, DI.IsLittleEndian);
    writeInteger((uint8_t)TableEntry.SegSelectorSize, OS, DI.IsLittleEndian);

    for (const SegAddrPair &Pair : TableEntry.SegAddrPairs) {
      if (TableEntry.SegSelectorSize != yaml::Hex8{0})
        if (Error Err = writeVariableSizedInteger(Pair.Segment,
                                                  TableEntry.SegSelectorSize,
                                                  OS, DI.IsLittleEndian))
          return createStringError(errc::not_supported,
                                   "unable to write debug_addr segment: %s",
                                   toString(std::move(Err)).c_str());
      if (AddrSize != 0)
        if (Error Err = writeVariableSizedInteger(Pair.Address, AddrSize, OS,
                                                  DI.IsLittleEndian))
          return createStringError(errc::not_supported,
                                   "unable to write debug_addr address: %s",
                                   toString(std::move(Err)).c_str());
    }
  }

  return Error::success();
}

Error DWARFYAML::emitDebugStrOffsets(raw_ostream &OS, const Data &DI) {
  assert(DI.DebugStrOffsets && "unexpected emitDebugStrOffsets() call");
  for (const DWARFYAML::StringOffsetsTable &Table : *DI.DebugStrOffsets) {
    uint64_t Length;
    if (Table.Length)
      Length = *Table.Length;
    else
      // sizeof(version) + sizeof(padding) = 4
      Length =
          4 + Table.Offsets.size() * (Table.Format == dwarf::DWARF64 ? 8 : 4);

    writeInitialLength(Table.Format, Length, OS, DI.IsLittleEndian);
    writeInteger((uint16_t)Table.Version, OS, DI.IsLittleEndian);
    writeInteger((uint16_t)Table.Padding, OS, DI.IsLittleEndian);

    for (uint64_t Offset : Table.Offsets)
      writeDWARFOffset(Offset, Table.Format, OS, DI.IsLittleEndian);
  }

  return Error::success();
}

namespace {
/// Emits the header for a DebugNames section.
void emitDebugNamesHeader(raw_ostream &OS, bool IsLittleEndian,
                          uint32_t NameCount, uint32_t AbbrevSize,
                          uint32_t CombinedSizeOtherParts) {
  // Use the same AugmentationString as AsmPrinter.
  StringRef AugmentationString = "LLVM0700";
  size_t TotalSize = CombinedSizeOtherParts + 5 * sizeof(uint32_t) +
                     2 * sizeof(uint16_t) + sizeof(NameCount) +
                     sizeof(AbbrevSize) + AugmentationString.size();
  writeInteger(uint32_t(TotalSize), OS, IsLittleEndian); // Unit length

  // Everything below is included in total size.
  writeInteger(uint16_t(5), OS, IsLittleEndian); // Version
  writeInteger(uint16_t(0), OS, IsLittleEndian); // Padding
  writeInteger(uint32_t(1), OS, IsLittleEndian); // Compilation Unit count
  writeInteger(uint32_t(0), OS, IsLittleEndian); // Local Type Unit count
  writeInteger(uint32_t(0), OS, IsLittleEndian); // Foreign Type Unit count
  writeInteger(uint32_t(0), OS, IsLittleEndian); // Bucket count
  writeInteger(NameCount, OS, IsLittleEndian);
  writeInteger(AbbrevSize, OS, IsLittleEndian);
  writeInteger(uint32_t(AugmentationString.size()), OS, IsLittleEndian);
  OS.write(AugmentationString.data(), AugmentationString.size());
}

/// Emits the abbreviations for a DebugNames section.
std::string
emitDebugNamesAbbrev(ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
  std::string Data;
  raw_string_ostream OS(Data);
  for (const DWARFYAML::DebugNameAbbreviation &Abbrev : Abbrevs) {
    encodeULEB128(Abbrev.Code, OS);
    encodeULEB128(Abbrev.Tag, OS);
    for (auto [Idx, Form] : Abbrev.Indices) {
      encodeULEB128(Idx, OS);
      encodeULEB128(Form, OS);
    }
    encodeULEB128(0, OS);
    encodeULEB128(0, OS);
  }
  encodeULEB128(0, OS);
  return Data;
}

/// Emits a simple CU offsets list for a DebugNames section containing a single
/// CU at offset 0.
std::string emitDebugNamesCUOffsets(bool IsLittleEndian) {
  std::string Data;
  raw_string_ostream OS(Data);
  writeInteger(uint32_t(0), OS, IsLittleEndian);
  return Data;
}

/// Emits the "NameTable" for a DebugNames section; according to the spec, it
/// consists of two arrays: an array of string offsets, followed immediately by
/// an array of entry offsets. The string offsets are emitted in the order
/// provided in `Entries`.
std::string emitDebugNamesNameTable(
    bool IsLittleEndian,
    const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> &Entries,
    ArrayRef<uint32_t> EntryPoolOffsets) {
  assert(Entries.size() == EntryPoolOffsets.size());

  std::string Data;
  raw_string_ostream OS(Data);

  for (uint32_t Strp : make_first_range(Entries))
    writeInteger(Strp, OS, IsLittleEndian);
  for (uint32_t PoolOffset : EntryPoolOffsets)
    writeInteger(PoolOffset, OS, IsLittleEndian);
  return Data;
}

/// Groups entries based on their name (strp) code and returns a map.
DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
groupEntries(ArrayRef<DWARFYAML::DebugNameEntry> Entries) {
  DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>> StrpToEntries;
  for (const DWARFYAML::DebugNameEntry &Entry : Entries)
    StrpToEntries[Entry.NameStrp].push_back(Entry);
  return StrpToEntries;
}

/// Finds the abbreviation whose code is AbbrevCode and returns a list
/// containing the expected size of all non-zero-length forms.
Expected<SmallVector<uint8_t>>
getNonZeroDataSizesFor(uint32_t AbbrevCode,
                       ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
  const auto *AbbrevIt = find_if(Abbrevs, [&](const auto &Abbrev) {
    return Abbrev.Code.value == AbbrevCode;
  });
  if (AbbrevIt == Abbrevs.end())
    return createStringError(inconvertibleErrorCode(),
                             "did not find an Abbreviation for this code");

  SmallVector<uint8_t> DataSizes;
  dwarf::FormParams Params{/*Version=*/5, /*AddrSize=*/4, dwarf::DWARF32};
  for (auto [Idx, Form] : AbbrevIt->Indices) {
    std::optional<uint8_t> FormSize = dwarf::getFixedFormByteSize(Form, Params);
    if (!FormSize)
      return createStringError(inconvertibleErrorCode(),
                               "unsupported Form for YAML debug_names emitter");
    if (FormSize == 0)
      continue;
    DataSizes.push_back(*FormSize);
  }
  return DataSizes;
}

struct PoolOffsetsAndData {
  std::string PoolData;
  std::vector<uint32_t> PoolOffsets;
};

/// Emits the entry pool and returns an array of offsets containing the start
/// offset for the entries of each unique name.
/// Verifies that the provided number of data values match those expected by
/// the abbreviation table.
Expected<PoolOffsetsAndData> emitDebugNamesEntryPool(
    bool IsLittleEndian,
    const DenseMap<uint32_t, std::vector<DWARFYAML::DebugNameEntry>>
        &StrpToEntries,
    ArrayRef<DWARFYAML::DebugNameAbbreviation> Abbrevs) {
  PoolOffsetsAndData Result;
  raw_string_ostream OS(Result.PoolData);

  for (ArrayRef<DWARFYAML::DebugNameEntry> EntriesWithSameName :
       make_second_range(StrpToEntries)) {
    Result.PoolOffsets.push_back(Result.PoolData.size());

    for (const DWARFYAML::DebugNameEntry &Entry : EntriesWithSameName) {
      encodeULEB128(Entry.Code, OS);

      Expected<SmallVector<uint8_t>> DataSizes =
          getNonZeroDataSizesFor(Entry.Code, Abbrevs);
      if (!DataSizes)
        return DataSizes.takeError();
      if (DataSizes->size() != Entry.Values.size())
        return createStringError(
            inconvertibleErrorCode(),
            "mismatch between provided and required number of values");

      for (auto [Value, ValueSize] : zip_equal(Entry.Values, *DataSizes))
        if (Error E =
                writeVariableSizedInteger(Value, ValueSize, OS, IsLittleEndian))
          return std::move(E);
    }
    encodeULEB128(0, OS);
  }

  return Result;
}
} // namespace

Error DWARFYAML::emitDebugNames(raw_ostream &OS, const Data &DI) {
  assert(DI.DebugNames && "unexpected emitDebugNames() call");
  const DebugNamesSection DebugNames = DI.DebugNames.value();

  DenseMap<uint32_t, std::vector<DebugNameEntry>> StrpToEntries =
      groupEntries(DebugNames.Entries);

  // Emit all sub-sections into individual strings so that we may compute
  // relative offsets and sizes.
  Expected<PoolOffsetsAndData> PoolInfo = emitDebugNamesEntryPool(
      DI.IsLittleEndian, StrpToEntries, DebugNames.Abbrevs);
  if (!PoolInfo)
    return PoolInfo.takeError();
  std::string NamesTableData = emitDebugNamesNameTable(
      DI.IsLittleEndian, StrpToEntries, PoolInfo->PoolOffsets);

  std::string AbbrevData = emitDebugNamesAbbrev(DebugNames.Abbrevs);
  std::string CUOffsetsData = emitDebugNamesCUOffsets(DI.IsLittleEndian);

  size_t TotalSize = PoolInfo->PoolData.size() + NamesTableData.size() +
                     AbbrevData.size() + CUOffsetsData.size();

  // Start real emission by combining all individual strings.
  emitDebugNamesHeader(OS, DI.IsLittleEndian, StrpToEntries.size(),
                       AbbrevData.size(), TotalSize);
  OS.write(CUOffsetsData.data(), CUOffsetsData.size());
  // No local TUs, no foreign TUs, no hash lookups table.
  OS.write(NamesTableData.data(), NamesTableData.size());
  OS.write(AbbrevData.data(), AbbrevData.size());
  OS.write(PoolInfo->PoolData.data(), PoolInfo->PoolData.size());

  return Error::success();
}

static Error checkOperandCount(StringRef EncodingString,
                               ArrayRef<yaml::Hex64> Values,
                               uint64_t ExpectedOperands) {
  if (Values.size() != ExpectedOperands)
    return createStringError(
        errc::invalid_argument,
        "invalid number (%zu) of operands for the operator: %s, %" PRIu64
        " expected",
        Values.size(), EncodingString.str().c_str(), ExpectedOperands);

  return Error::success();
}

static Error writeListEntryAddress(StringRef EncodingName, raw_ostream &OS,
                                   uint64_t Addr, uint8_t AddrSize,
                                   bool IsLittleEndian) {
  if (Error Err = writeVariableSizedInteger(Addr, AddrSize, OS, IsLittleEndian))
    return createStringError(errc::invalid_argument,
                             "unable to write address for the operator %s: %s",
                             EncodingName.str().c_str(),
                             toString(std::move(Err)).c_str());

  return Error::success();
}

static Expected<uint64_t>
writeDWARFExpression(raw_ostream &OS,
                     const DWARFYAML::DWARFOperation &Operation,
                     uint8_t AddrSize, bool IsLittleEndian) {
  auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
    return checkOperandCount(dwarf::OperationEncodingString(Operation.Operator),
                             Operation.Values, ExpectedOperands);
  };

  uint64_t ExpressionBegin = OS.tell();
  writeInteger((uint8_t)Operation.Operator, OS, IsLittleEndian);
  switch (Operation.Operator) {
  case dwarf::DW_OP_consts:
    if (Error Err = CheckOperands(1))
      return std::move(Err);
    encodeSLEB128(Operation.Values[0], OS);
    break;
  case dwarf::DW_OP_stack_value:
    if (Error Err = CheckOperands(0))
      return std::move(Err);
    break;
  default:
    StringRef EncodingStr = dwarf::OperationEncodingString(Operation.Operator);
    return createStringError(errc::not_supported,
                             "DWARF expression: " +
                                 (EncodingStr.empty()
                                      ? "0x" + utohexstr(Operation.Operator)
                                      : EncodingStr) +
                                 " is not supported");
  }
  return OS.tell() - ExpressionBegin;
}

static Expected<uint64_t> writeListEntry(raw_ostream &OS,
                                         const DWARFYAML::RnglistEntry &Entry,
                                         uint8_t AddrSize,
                                         bool IsLittleEndian) {
  uint64_t BeginOffset = OS.tell();
  writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);

  StringRef EncodingName = dwarf::RangeListEncodingString(Entry.Operator);

  auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
    return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
  };

  auto WriteAddress = [&](uint64_t Addr) -> Error {
    return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
                                 IsLittleEndian);
  };

  switch (Entry.Operator) {
  case dwarf::DW_RLE_end_of_list:
    if (Error Err = CheckOperands(0))
      return std::move(Err);
    break;
  case dwarf::DW_RLE_base_addressx:
    if (Error Err = CheckOperands(1))
      return std::move(Err);
    encodeULEB128(Entry.Values[0], OS);
    break;
  case dwarf::DW_RLE_startx_endx:
  case dwarf::DW_RLE_startx_length:
  case dwarf::DW_RLE_offset_pair:
    if (Error Err = CheckOperands(2))
      return std::move(Err);
    encodeULEB128(Entry.Values[0], OS);
    encodeULEB128(Entry.Values[1], OS);
    break;
  case dwarf::DW_RLE_base_address:
    if (Error Err = CheckOperands(1))
      return std::move(Err);
    if (Error Err = WriteAddress(Entry.Values[0]))
      return std::move(Err);
    break;
  case dwarf::DW_RLE_start_end:
    if (Error Err = CheckOperands(2))
      return std::move(Err);
    if (Error Err = WriteAddress(Entry.Values[0]))
      return std::move(Err);
    cantFail(WriteAddress(Entry.Values[1]));
    break;
  case dwarf::DW_RLE_start_length:
    if (Error Err = CheckOperands(2))
      return std::move(Err);
    if (Error Err = WriteAddress(Entry.Values[0]))
      return std::move(Err);
    encodeULEB128(Entry.Values[1], OS);
    break;
  }

  return OS.tell() - BeginOffset;
}

static Expected<uint64_t> writeListEntry(raw_ostream &OS,
                                         const DWARFYAML::LoclistEntry &Entry,
                                         uint8_t AddrSize,
                                         bool IsLittleEndian) {
  uint64_t BeginOffset = OS.tell();
  writeInteger((uint8_t)Entry.Operator, OS, IsLittleEndian);

  StringRef EncodingName = dwarf::LocListEncodingString(Entry.Operator);

  auto CheckOperands = [&](uint64_t ExpectedOperands) -> Error {
    return checkOperandCount(EncodingName, Entry.Values, ExpectedOperands);
  };

  auto WriteAddress = [&](uint64_t Addr) -> Error {
    return writeListEntryAddress(EncodingName, OS, Addr, AddrSize,
                                 IsLittleEndian);
  };

  auto WriteDWARFOperations = [&]() -> Error {
    std::string OpBuffer;
    raw_string_ostream OpBufferOS(OpBuffer);
    uint64_t DescriptionsLength = 0;

    for (const DWARFYAML::DWARFOperation &Op : Entry.Descriptions) {
      if (Expected<uint64_t> OpSize =
              writeDWARFExpression(OpBufferOS, Op, AddrSize, IsLittleEndian))
        DescriptionsLength += *OpSize;
      else
        return OpSize.takeError();
    }

    if (Entry.DescriptionsLength)
      DescriptionsLength = *Entry.DescriptionsLength;
    else
      DescriptionsLength = OpBuffer.size();

    encodeULEB128(DescriptionsLength, OS);
    OS.write(OpBuffer.data(), OpBuffer.size());

    return Error::success();
  };

  switch (Entry.Operator) {
  case dwarf::DW_LLE_end_of_list:
    if (Error Err = CheckOperands(0))
      return std::move(Err);
    break;
  case dwarf::DW_LLE_base_addressx:
    if (Error Err = CheckOperands(1))
      return std::move(Err);
    encodeULEB128(Entry.Values[0], OS);
    break;
  case dwarf::DW_LLE_startx_endx:
  case dwarf::DW_LLE_startx_length:
  case dwarf::DW_LLE_offset_pair:
    if (Error Err = CheckOperands(2))
      return std::move(Err);
    encodeULEB128(Entry.Values[0], OS);
    encodeULEB128(Entry.Values[1], OS);
    if (Error Err = WriteDWARFOperations())
      return std::move(Err);
    break;
  case dwarf::DW_LLE_default_location:
    if (Error Err = CheckOperands(0))
      return std::move(Err);
    if (Error Err = WriteDWARFOperations())
      return std::move(Err);
    break;
  case dwarf::DW_LLE_base_address:
    if (Error Err = CheckOperands(1))
      return std::move(Err);
    if (Error Err = WriteAddress(Entry.Values[0]))
      return std::move(Err);
    break;
  case dwarf::DW_LLE_start_end:
    if (Error Err = CheckOperands(2))
      return std::move(Err);
    if (Error Err = WriteAddress(Entry.Values[0]))
      return std::move(Err);
    cantFail(WriteAddress(Entry.Values[1]));
    if (Error Err = WriteDWARFOperations())
      return std::move(Err);
    break;
  case dwarf::DW_LLE_start_length:
    if (Error Err = CheckOperands(2))
      return std::move(Err);
    if (Error Err = WriteAddress(Entry.Values[0]))
      return std::move(Err);
    encodeULEB128(Entry.Values[1], OS);
    if (Error Err = WriteDWARFOperations())
      return std::move(Err);
    break;
  }

  return OS.tell() - BeginOffset;
}

template <typename EntryType>
static Error writeDWARFLists(raw_ostream &OS,
                             ArrayRef<DWARFYAML::ListTable<EntryType>> Tables,
                             bool IsLittleEndian, bool Is64BitAddrSize) {
  for (const DWARFYAML::ListTable<EntryType> &Table : Tables) {
    // sizeof(version) + sizeof(address_size) + sizeof(segment_selector_size) +
    // sizeof(offset_entry_count) = 8
    uint64_t Length = 8;

    uint8_t AddrSize;
    if (Table.AddrSize)
      AddrSize = *Table.AddrSize;
    else
      AddrSize = Is64BitAddrSize ? 8 : 4;

    // Since the length of the current range/location lists entry is
    // undetermined yet, we firstly write the content of the range/location
    // lists to a buffer to calculate the length and then serialize the buffer
    // content to the actual output stream.
    std::string ListBuffer;
    raw_string_ostream ListBufferOS(ListBuffer);

    // Offsets holds offsets for each range/location list. The i-th element is
    // the offset from the beginning of the first range/location list to the
    // location of the i-th range list.
    std::vector<uint64_t> Offsets;

    for (const DWARFYAML::ListEntries<EntryType> &List : Table.Lists) {
      Offsets.push_back(ListBufferOS.tell());
      if (List.Content) {
        List.Content->writeAsBinary(ListBufferOS, UINT64_MAX);
        Length += List.Content->binary_size();
      } else if (List.Entries) {
        for (const EntryType &Entry : *List.Entries) {
          Expected<uint64_t> EntrySize =
              writeListEntry(ListBufferOS, Entry, AddrSize, IsLittleEndian);
          if (!EntrySize)
            return EntrySize.takeError();
          Length += *EntrySize;
        }
      }
    }

    // If the offset_entry_count field isn't specified, yaml2obj will infer it
    // from the 'Offsets' field in the YAML description. If the 'Offsets' field
    // isn't specified either, yaml2obj will infer it from the auto-generated
    // offsets.
    uint32_t OffsetEntryCount;
    if (Table.OffsetEntryCount)
      OffsetEntryCount = *Table.OffsetEntryCount;
    else
      OffsetEntryCount = Table.Offsets ? Table.Offsets->size() : Offsets.size();
    uint64_t OffsetsSize =
        OffsetEntryCount * (Table.Format == dwarf::DWARF64 ? 8 : 4);
    Length += OffsetsSize;

    // If the length is specified in the YAML description, we use it instead of
    // the actual length.
    if (Table.Length)
      Length = *Table.Length;

    writeInitialLength(Table.Format, Length, OS, IsLittleEndian);
    writeInteger((uint16_t)Table.Version, OS, IsLittleEndian);
    writeInteger((uint8_t)AddrSize, OS, IsLittleEndian);
    writeInteger((uint8_t)Table.SegSelectorSize, OS, IsLittleEndian);
    writeInteger((uint32_t)OffsetEntryCount, OS, IsLittleEndian);

    auto EmitOffsets = [&](ArrayRef<uint64_t> Offsets, uint64_t OffsetsSize) {
      for (uint64_t Offset : Offsets)
        writeDWARFOffset(OffsetsSize + Offset, Table.Format, OS,
                         IsLittleEndian);
    };

    if (Table.Offsets)
      EmitOffsets(ArrayRef<uint64_t>((const uint64_t *)Table.Offsets->data(),
                                     Table.Offsets->size()),
                  0);
    else if (OffsetEntryCount != 0)
      EmitOffsets(Offsets, OffsetsSize);

    OS.write(ListBuffer.data(), ListBuffer.size());
  }

  return Error::success();
}

Error DWARFYAML::emitDebugRnglists(raw_ostream &OS, const Data &DI) {
  assert(DI.DebugRnglists && "unexpected emitDebugRnglists() call");
  return writeDWARFLists<DWARFYAML::RnglistEntry>(
      OS, *DI.DebugRnglists, DI.IsLittleEndian, DI.Is64BitAddrSize);
}

Error DWARFYAML::emitDebugLoclists(raw_ostream &OS, const Data &DI) {
  assert(DI.DebugLoclists && "unexpected emitDebugRnglists() call");
  return writeDWARFLists<DWARFYAML::LoclistEntry>(
      OS, *DI.DebugLoclists, DI.IsLittleEndian, DI.Is64BitAddrSize);
}

std::function<Error(raw_ostream &, const DWARFYAML::Data &)>
DWARFYAML::getDWARFEmitterByName(StringRef SecName) {
  auto EmitFunc =
      StringSwitch<
          std::function<Error(raw_ostream &, const DWARFYAML::Data &)>>(SecName)
          .Case("debug_abbrev", DWARFYAML::emitDebugAbbrev)
          .Case("debug_addr", DWARFYAML::emitDebugAddr)
          .Case("debug_aranges", DWARFYAML::emitDebugAranges)
          .Case("debug_gnu_pubnames", DWARFYAML::emitDebugGNUPubnames)
          .Case("debug_gnu_pubtypes", DWARFYAML::emitDebugGNUPubtypes)
          .Case("debug_info", DWARFYAML::emitDebugInfo)
          .Case("debug_line", DWARFYAML::emitDebugLine)
          .Case("debug_loclists", DWARFYAML::emitDebugLoclists)
          .Case("debug_pubnames", DWARFYAML::emitDebugPubnames)
          .Case("debug_pubtypes", DWARFYAML::emitDebugPubtypes)
          .Case("debug_ranges", DWARFYAML::emitDebugRanges)
          .Case("debug_rnglists", DWARFYAML::emitDebugRnglists)
          .Case("debug_str", DWARFYAML::emitDebugStr)
          .Case("debug_str_offsets", DWARFYAML::emitDebugStrOffsets)
          .Case("debug_names", DWARFYAML::emitDebugNames)
          .Default([&](raw_ostream &, const DWARFYAML::Data &) {
            return createStringError(errc::not_supported,
                                     SecName + " is not supported");
          });

  return EmitFunc;
}

static Error
emitDebugSectionImpl(const DWARFYAML::Data &DI, StringRef Sec,
                     StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
  std::string Data;
  raw_string_ostream DebugInfoStream(Data);

  auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Sec);

  if (Error Err = EmitFunc(DebugInfoStream, DI))
    return Err;
  DebugInfoStream.flush();
  if (!Data.empty())
    OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);

  return Error::success();
}

Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
DWARFYAML::emitDebugSections(StringRef YAMLString, bool IsLittleEndian,
                             bool Is64BitAddrSize) {
  auto CollectDiagnostic = [](const SMDiagnostic &Diag, void *DiagContext) {
    *static_cast<SMDiagnostic *>(DiagContext) = Diag;
  };

  SMDiagnostic GeneratedDiag;
  yaml::Input YIn(YAMLString, /*Ctxt=*/nullptr, CollectDiagnostic,
                  &GeneratedDiag);

  DWARFYAML::Data DI;
  DI.IsLittleEndian = IsLittleEndian;
  DI.Is64BitAddrSize = Is64BitAddrSize;

  YIn >> DI;
  if (YIn.error())
    return createStringError(YIn.error(), GeneratedDiag.getMessage());

  StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
  Error Err = Error::success();

  for (StringRef SecName : DI.getNonEmptySectionNames())
    Err = joinErrors(std::move(Err),
                     emitDebugSectionImpl(DI, SecName, DebugSections));

  if (Err)
    return std::move(Err);
  return std::move(DebugSections);
}
