//===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
//
// 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 ELF component of yaml2obj.
///
//===----------------------------------------------------------------------===//

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ELFTypes.h"
#include "llvm/ObjectYAML/DWARFEmitter.h"
#include "llvm/ObjectYAML/DWARFYAML.h"
#include "llvm/ObjectYAML/ELFYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

// This class is used to build up a contiguous binary blob while keeping
// track of an offset in the output (which notionally begins at
// `InitialOffset`).
// The blob might be limited to an arbitrary size. All attempts to write data
// are ignored and the error condition is remembered once the limit is reached.
// Such an approach allows us to simplify the code by delaying error reporting
// and doing it at a convenient time.
namespace {
class ContiguousBlobAccumulator {
  const uint64_t InitialOffset;
  const uint64_t MaxSize;

  SmallVector<char, 128> Buf;
  raw_svector_ostream OS;
  Error ReachedLimitErr = Error::success();

  bool checkLimit(uint64_t Size) {
    if (!ReachedLimitErr && getOffset() + Size <= MaxSize)
      return true;
    if (!ReachedLimitErr)
      ReachedLimitErr = createStringError(errc::invalid_argument,
                                          "reached the output size limit");
    return false;
  }

public:
  ContiguousBlobAccumulator(uint64_t BaseOffset, uint64_t SizeLimit)
      : InitialOffset(BaseOffset), MaxSize(SizeLimit), OS(Buf) {}

  uint64_t tell() const { return OS.tell(); }
  uint64_t getOffset() const { return InitialOffset + OS.tell(); }
  void writeBlobToStream(raw_ostream &Out) const { Out << OS.str(); }

  Error takeLimitError() {
    // Request to write 0 bytes to check we did not reach the limit.
    checkLimit(0);
    return std::move(ReachedLimitErr);
  }

  /// \returns The new offset.
  uint64_t padToAlignment(unsigned Align) {
    uint64_t CurrentOffset = getOffset();
    if (ReachedLimitErr)
      return CurrentOffset;

    uint64_t AlignedOffset = alignTo(CurrentOffset, Align == 0 ? 1 : Align);
    uint64_t PaddingSize = AlignedOffset - CurrentOffset;
    if (!checkLimit(PaddingSize))
      return CurrentOffset;

    writeZeros(PaddingSize);
    return AlignedOffset;
  }

  raw_ostream *getRawOS(uint64_t Size) {
    if (checkLimit(Size))
      return &OS;
    return nullptr;
  }

  void writeAsBinary(const yaml::BinaryRef &Bin, uint64_t N = UINT64_MAX) {
    if (!checkLimit(Bin.binary_size()))
      return;
    Bin.writeAsBinary(OS, N);
  }

  void writeZeros(uint64_t Num) {
    if (checkLimit(Num))
      OS.write_zeros(Num);
  }

  void write(const char *Ptr, size_t Size) {
    if (checkLimit(Size))
      OS.write(Ptr, Size);
  }

  void write(unsigned char C) {
    if (checkLimit(1))
      OS.write(C);
  }

  unsigned writeULEB128(uint64_t Val) {
    if (!checkLimit(sizeof(uint64_t)))
      return 0;
    return encodeULEB128(Val, OS);
  }

  template <typename T> void write(T Val, support::endianness E) {
    if (checkLimit(sizeof(T)))
      support::endian::write<T>(OS, Val, E);
  }

  void updateDataAt(uint64_t Pos, void *Data, size_t Size) {
    assert(Pos >= InitialOffset && Pos + Size <= getOffset());
    memcpy(&Buf[Pos - InitialOffset], Data, Size);
  }
};

// Used to keep track of section and symbol names, so that in the YAML file
// sections and symbols can be referenced by name instead of by index.
class NameToIdxMap {
  StringMap<unsigned> Map;

public:
  /// \Returns false if name is already present in the map.
  bool addName(StringRef Name, unsigned Ndx) {
    return Map.insert({Name, Ndx}).second;
  }
  /// \Returns false if name is not present in the map.
  bool lookup(StringRef Name, unsigned &Idx) const {
    auto I = Map.find(Name);
    if (I == Map.end())
      return false;
    Idx = I->getValue();
    return true;
  }
  /// Asserts if name is not present in the map.
  unsigned get(StringRef Name) const {
    unsigned Idx;
    if (lookup(Name, Idx))
      return Idx;
    assert(false && "Expected section not found in index");
    return 0;
  }
  unsigned size() const { return Map.size(); }
};

namespace {
struct Fragment {
  uint64_t Offset;
  uint64_t Size;
  uint32_t Type;
  uint64_t AddrAlign;
};
} // namespace

/// "Single point of truth" for the ELF file construction.
/// TODO: This class still has a ways to go before it is truly a "single
/// point of truth".
template <class ELFT> class ELFState {
  LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)

  enum class SymtabType { Static, Dynamic };

  /// The future symbol table string section.
  StringTableBuilder DotStrtab{StringTableBuilder::ELF};

  /// The future section header string table section, if a unique string table
  /// is needed. Don't reference this variable direectly: use the
  /// ShStrtabStrings member instead.
  StringTableBuilder DotShStrtab{StringTableBuilder::ELF};

  /// The future dynamic symbol string section.
  StringTableBuilder DotDynstr{StringTableBuilder::ELF};

  /// The name of the section header string table section. If it is .strtab or
  /// .dynstr, the section header strings will be written to the same string
  /// table as the static/dynamic symbols respectively. Otherwise a dedicated
  /// section will be created with that name.
  StringRef SectionHeaderStringTableName = ".shstrtab";
  StringTableBuilder *ShStrtabStrings = &DotShStrtab;

  NameToIdxMap SN2I;
  NameToIdxMap SymN2I;
  NameToIdxMap DynSymN2I;
  ELFYAML::Object &Doc;

  StringSet<> ExcludedSectionHeaders;

  uint64_t LocationCounter = 0;
  bool HasError = false;
  yaml::ErrorHandler ErrHandler;
  void reportError(const Twine &Msg);
  void reportError(Error Err);

  std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
                                    const StringTableBuilder &Strtab);
  unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "");
  unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic);

  void buildSectionIndex();
  void buildSymbolIndexes();
  void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);
  bool initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header,
                          StringRef SecName, ELFYAML::Section *YAMLSec);
  void initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
                          ContiguousBlobAccumulator &CBA);
  void initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType,
                               ContiguousBlobAccumulator &CBA,
                               ELFYAML::Section *YAMLSec);
  void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
                               StringTableBuilder &STB,
                               ContiguousBlobAccumulator &CBA,
                               ELFYAML::Section *YAMLSec);
  void initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
                              ContiguousBlobAccumulator &CBA,
                              ELFYAML::Section *YAMLSec);
  void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
                              std::vector<Elf_Shdr> &SHeaders);

  std::vector<Fragment>
  getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,
                   ArrayRef<typename ELFT::Shdr> SHeaders);

  void finalizeStrings();
  void writeELFHeader(raw_ostream &OS);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::NoBitsSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::RawContentSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::RelocationSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::RelrSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::GroupSection &Group,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::SymtabShndxSection &Shndx,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::SymverSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::VerneedSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::VerdefSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::ARMIndexTableSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::MipsABIFlags &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::DynamicSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::StackSizesSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::BBAddrMapSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::HashSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::AddrsigSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::NoteSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::GnuHashSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::LinkerOptionsSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::DependentLibrariesSection &Section,
                           ContiguousBlobAccumulator &CBA);
  void writeSectionContent(Elf_Shdr &SHeader,
                           const ELFYAML::CallGraphProfileSection &Section,
                           ContiguousBlobAccumulator &CBA);

  void writeFill(ELFYAML::Fill &Fill, ContiguousBlobAccumulator &CBA);

  ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH);

  void assignSectionAddress(Elf_Shdr &SHeader, ELFYAML::Section *YAMLSec);

  DenseMap<StringRef, size_t> buildSectionHeaderReorderMap();

  BumpPtrAllocator StringAlloc;
  uint64_t alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,
                         llvm::Optional<llvm::yaml::Hex64> Offset);

  uint64_t getSectionNameOffset(StringRef Name);

public:
  static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
                       yaml::ErrorHandler EH, uint64_t MaxSize);
};
} // end anonymous namespace

template <class T> static size_t arrayDataSize(ArrayRef<T> A) {
  return A.size() * sizeof(T);
}

template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
  OS.write((const char *)A.data(), arrayDataSize(A));
}

template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); }

template <class ELFT>
ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH)
    : Doc(D), ErrHandler(EH) {
  // The input may explicitly request to store the section header table strings
  // in the same string table as dynamic or static symbol names. Set the
  // ShStrtabStrings member accordingly.
  if (Doc.Header.SectionHeaderStringTable) {
    SectionHeaderStringTableName = *Doc.Header.SectionHeaderStringTable;
    if (*Doc.Header.SectionHeaderStringTable == ".strtab")
      ShStrtabStrings = &DotStrtab;
    else if (*Doc.Header.SectionHeaderStringTable == ".dynstr")
      ShStrtabStrings = &DotDynstr;
    // Otherwise, the unique table will be used.
  }

  std::vector<ELFYAML::Section *> Sections = Doc.getSections();
  // Insert SHT_NULL section implicitly when it is not defined in YAML.
  if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL)
    Doc.Chunks.insert(
        Doc.Chunks.begin(),
        std::make_unique<ELFYAML::Section>(
            ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true));

  StringSet<> DocSections;
  ELFYAML::SectionHeaderTable *SecHdrTable = nullptr;
  for (size_t I = 0; I < Doc.Chunks.size(); ++I) {
    const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I];

    // We might have an explicit section header table declaration.
    if (auto S = dyn_cast<ELFYAML::SectionHeaderTable>(C.get())) {
      if (SecHdrTable)
        reportError("multiple section header tables are not allowed");
      SecHdrTable = S;
      continue;
    }

    // We add a technical suffix for each unnamed section/fill. It does not
    // affect the output, but allows us to map them by name in the code and
    // report better error messages.
    if (C->Name.empty()) {
      std::string NewName = ELFYAML::appendUniqueSuffix(
          /*Name=*/"", "index " + Twine(I));
      C->Name = StringRef(NewName).copy(StringAlloc);
      assert(ELFYAML::dropUniqueSuffix(C->Name).empty());
    }

    if (!DocSections.insert(C->Name).second)
      reportError("repeated section/fill name: '" + C->Name +
                  "' at YAML section/fill number " + Twine(I));
  }

  SmallSetVector<StringRef, 8> ImplicitSections;
  if (Doc.DynamicSymbols) {
    if (SectionHeaderStringTableName == ".dynsym")
      reportError("cannot use '.dynsym' as the section header name table when "
                  "there are dynamic symbols");
    ImplicitSections.insert(".dynsym");
    ImplicitSections.insert(".dynstr");
  }
  if (Doc.Symbols) {
    if (SectionHeaderStringTableName == ".symtab")
      reportError("cannot use '.symtab' as the section header name table when "
                  "there are symbols");
    ImplicitSections.insert(".symtab");
  }
  if (Doc.DWARF)
    for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) {
      std::string SecName = ("." + DebugSecName).str();
      // TODO: For .debug_str it should be possible to share the string table,
      // in the same manner as the symbol string tables.
      if (SectionHeaderStringTableName == SecName)
        reportError("cannot use '" + SecName +
                    "' as the section header name table when it is needed for "
                    "DWARF output");
      ImplicitSections.insert(StringRef(SecName).copy(StringAlloc));
    }
  // TODO: Only create the .strtab here if any symbols have been requested.
  ImplicitSections.insert(".strtab");
  if (!SecHdrTable || !SecHdrTable->NoHeaders.getValueOr(false))
    ImplicitSections.insert(SectionHeaderStringTableName);

  // Insert placeholders for implicit sections that are not
  // defined explicitly in YAML.
  for (StringRef SecName : ImplicitSections) {
    if (DocSections.count(SecName))
      continue;

    std::unique_ptr<ELFYAML::Section> Sec = std::make_unique<ELFYAML::Section>(
        ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/);
    Sec->Name = SecName;

    if (SecName == SectionHeaderStringTableName)
      Sec->Type = ELF::SHT_STRTAB;
    else if (SecName == ".dynsym")
      Sec->Type = ELF::SHT_DYNSYM;
    else if (SecName == ".symtab")
      Sec->Type = ELF::SHT_SYMTAB;
    else
      Sec->Type = ELF::SHT_STRTAB;

    // When the section header table is explicitly defined at the end of the
    // sections list, it is reasonable to assume that the user wants to reorder
    // section headers, but still wants to place the section header table after
    // all sections, like it normally happens. In this case we want to insert
    // other implicit sections right before the section header table.
    if (Doc.Chunks.back().get() == SecHdrTable)
      Doc.Chunks.insert(Doc.Chunks.end() - 1, std::move(Sec));
    else
      Doc.Chunks.push_back(std::move(Sec));
  }

  // Insert the section header table implicitly at the end, when it is not
  // explicitly defined.
  if (!SecHdrTable)
    Doc.Chunks.push_back(
        std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/true));
}

template <class ELFT>
void ELFState<ELFT>::writeELFHeader(raw_ostream &OS) {
  using namespace llvm::ELF;

  Elf_Ehdr Header;
  zero(Header);
  Header.e_ident[EI_MAG0] = 0x7f;
  Header.e_ident[EI_MAG1] = 'E';
  Header.e_ident[EI_MAG2] = 'L';
  Header.e_ident[EI_MAG3] = 'F';
  Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
  Header.e_ident[EI_DATA] = Doc.Header.Data;
  Header.e_ident[EI_VERSION] = EV_CURRENT;
  Header.e_ident[EI_OSABI] = Doc.Header.OSABI;
  Header.e_ident[EI_ABIVERSION] = Doc.Header.ABIVersion;
  Header.e_type = Doc.Header.Type;

  if (Doc.Header.Machine)
    Header.e_machine = *Doc.Header.Machine;
  else
    Header.e_machine = EM_NONE;

  Header.e_version = EV_CURRENT;
  Header.e_entry = Doc.Header.Entry;
  Header.e_flags = Doc.Header.Flags;
  Header.e_ehsize = sizeof(Elf_Ehdr);

  if (Doc.Header.EPhOff)
    Header.e_phoff = *Doc.Header.EPhOff;
  else if (!Doc.ProgramHeaders.empty())
    Header.e_phoff = sizeof(Header);
  else
    Header.e_phoff = 0;

  if (Doc.Header.EPhEntSize)
    Header.e_phentsize = *Doc.Header.EPhEntSize;
  else if (!Doc.ProgramHeaders.empty())
    Header.e_phentsize = sizeof(Elf_Phdr);
  else
    Header.e_phentsize = 0;

  if (Doc.Header.EPhNum)
    Header.e_phnum = *Doc.Header.EPhNum;
  else if (!Doc.ProgramHeaders.empty())
    Header.e_phnum = Doc.ProgramHeaders.size();
  else
    Header.e_phnum = 0;

  Header.e_shentsize = Doc.Header.EShEntSize ? (uint16_t)*Doc.Header.EShEntSize
                                             : sizeof(Elf_Shdr);

  const ELFYAML::SectionHeaderTable &SectionHeaders =
      Doc.getSectionHeaderTable();

  if (Doc.Header.EShOff)
    Header.e_shoff = *Doc.Header.EShOff;
  else if (SectionHeaders.Offset)
    Header.e_shoff = *SectionHeaders.Offset;
  else
    Header.e_shoff = 0;

  if (Doc.Header.EShNum)
    Header.e_shnum = *Doc.Header.EShNum;
  else
    Header.e_shnum = SectionHeaders.getNumHeaders(Doc.getSections().size());

  if (Doc.Header.EShStrNdx)
    Header.e_shstrndx = *Doc.Header.EShStrNdx;
  else if (SectionHeaders.Offset &&
           !ExcludedSectionHeaders.count(SectionHeaderStringTableName))
    Header.e_shstrndx = SN2I.get(SectionHeaderStringTableName);
  else
    Header.e_shstrndx = 0;

  OS.write((const char *)&Header, sizeof(Header));
}

template <class ELFT>
void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) {
  DenseMap<StringRef, ELFYAML::Fill *> NameToFill;
  DenseMap<StringRef, size_t> NameToIndex;
  for (size_t I = 0, E = Doc.Chunks.size(); I != E; ++I) {
    if (auto S = dyn_cast<ELFYAML::Fill>(Doc.Chunks[I].get()))
      NameToFill[S->Name] = S;
    NameToIndex[Doc.Chunks[I]->Name] = I + 1;
  }

  std::vector<ELFYAML::Section *> Sections = Doc.getSections();
  for (size_t I = 0, E = Doc.ProgramHeaders.size(); I != E; ++I) {
    ELFYAML::ProgramHeader &YamlPhdr = Doc.ProgramHeaders[I];
    Elf_Phdr Phdr;
    zero(Phdr);
    Phdr.p_type = YamlPhdr.Type;
    Phdr.p_flags = YamlPhdr.Flags;
    Phdr.p_vaddr = YamlPhdr.VAddr;
    Phdr.p_paddr = YamlPhdr.PAddr;
    PHeaders.push_back(Phdr);

    if (!YamlPhdr.FirstSec && !YamlPhdr.LastSec)
      continue;

    // Get the index of the section, or 0 in the case when the section doesn't exist.
    size_t First = NameToIndex[*YamlPhdr.FirstSec];
    if (!First)
      reportError("unknown section or fill referenced: '" + *YamlPhdr.FirstSec +
                  "' by the 'FirstSec' key of the program header with index " +
                  Twine(I));
    size_t Last = NameToIndex[*YamlPhdr.LastSec];
    if (!Last)
      reportError("unknown section or fill referenced: '" + *YamlPhdr.LastSec +
                  "' by the 'LastSec' key of the program header with index " +
                  Twine(I));
    if (!First || !Last)
      continue;

    if (First > Last)
      reportError("program header with index " + Twine(I) +
                  ": the section index of " + *YamlPhdr.FirstSec +
                  " is greater than the index of " + *YamlPhdr.LastSec);

    for (size_t I = First; I <= Last; ++I)
      YamlPhdr.Chunks.push_back(Doc.Chunks[I - 1].get());
  }
}

template <class ELFT>
unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec,
                                        StringRef LocSym) {
  assert(LocSec.empty() || LocSym.empty());

  unsigned Index;
  if (!SN2I.lookup(S, Index) && !to_integer(S, Index)) {
    if (!LocSym.empty())
      reportError("unknown section referenced: '" + S + "' by YAML symbol '" +
                  LocSym + "'");
    else
      reportError("unknown section referenced: '" + S + "' by YAML section '" +
                  LocSec + "'");
    return 0;
  }

  const ELFYAML::SectionHeaderTable &SectionHeaders =
      Doc.getSectionHeaderTable();
  if (SectionHeaders.IsImplicit ||
      (SectionHeaders.NoHeaders && !SectionHeaders.NoHeaders.getValue()) ||
      SectionHeaders.isDefault())
    return Index;

  assert(!SectionHeaders.NoHeaders.getValueOr(false) ||
         !SectionHeaders.Sections);
  size_t FirstExcluded =
      SectionHeaders.Sections ? SectionHeaders.Sections->size() : 0;
  if (Index > FirstExcluded) {
    if (LocSym.empty())
      reportError("unable to link '" + LocSec + "' to excluded section '" + S +
                  "'");
    else
      reportError("excluded section referenced: '" + S + "'  by symbol '" +
                  LocSym + "'");
  }
  return Index;
}

template <class ELFT>
unsigned ELFState<ELFT>::toSymbolIndex(StringRef S, StringRef LocSec,
                                       bool IsDynamic) {
  const NameToIdxMap &SymMap = IsDynamic ? DynSymN2I : SymN2I;
  unsigned Index;
  // Here we try to look up S in the symbol table. If it is not there,
  // treat its value as a symbol index.
  if (!SymMap.lookup(S, Index) && !to_integer(S, Index)) {
    reportError("unknown symbol referenced: '" + S + "' by YAML section '" +
                LocSec + "'");
    return 0;
  }
  return Index;
}

template <class ELFT>
static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) {
  if (!From)
    return;
  if (From->ShAddrAlign)
    To.sh_addralign = *From->ShAddrAlign;
  if (From->ShFlags)
    To.sh_flags = *From->ShFlags;
  if (From->ShName)
    To.sh_name = *From->ShName;
  if (From->ShOffset)
    To.sh_offset = *From->ShOffset;
  if (From->ShSize)
    To.sh_size = *From->ShSize;
  if (From->ShType)
    To.sh_type = *From->ShType;
}

template <class ELFT>
bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA,
                                        Elf_Shdr &Header, StringRef SecName,
                                        ELFYAML::Section *YAMLSec) {
  // Check if the header was already initialized.
  if (Header.sh_offset)
    return false;

  if (SecName == ".strtab")
    initStrtabSectionHeader(Header, SecName, DotStrtab, CBA, YAMLSec);
  else if (SecName == ".dynstr")
    initStrtabSectionHeader(Header, SecName, DotDynstr, CBA, YAMLSec);
  else if (SecName == SectionHeaderStringTableName)
    initStrtabSectionHeader(Header, SecName, *ShStrtabStrings, CBA, YAMLSec);
  else if (SecName == ".symtab")
    initSymtabSectionHeader(Header, SymtabType::Static, CBA, YAMLSec);
  else if (SecName == ".dynsym")
    initSymtabSectionHeader(Header, SymtabType::Dynamic, CBA, YAMLSec);
  else if (SecName.startswith(".debug_")) {
    // If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we
    // will not treat it as a debug section.
    if (YAMLSec && !isa<ELFYAML::RawContentSection>(YAMLSec))
      return false;
    initDWARFSectionHeader(Header, SecName, CBA, YAMLSec);
  } else
    return false;

  LocationCounter += Header.sh_size;

  // Override section fields if requested.
  overrideFields<ELFT>(YAMLSec, Header);
  return true;
}

constexpr char SuffixStart = '(';
constexpr char SuffixEnd = ')';

std::string llvm::ELFYAML::appendUniqueSuffix(StringRef Name,
                                              const Twine &Msg) {
  // Do not add a space when a Name is empty.
  std::string Ret = Name.empty() ? "" : Name.str() + ' ';
  return Ret + (Twine(SuffixStart) + Msg + Twine(SuffixEnd)).str();
}

StringRef llvm::ELFYAML::dropUniqueSuffix(StringRef S) {
  if (S.empty() || S.back() != SuffixEnd)
    return S;

  // A special case for empty names. See appendUniqueSuffix() above.
  size_t SuffixPos = S.rfind(SuffixStart);
  if (SuffixPos == 0)
    return "";

  if (SuffixPos == StringRef::npos || S[SuffixPos - 1] != ' ')
    return S;
  return S.substr(0, SuffixPos - 1);
}

template <class ELFT>
uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) {
  // If a section is excluded from section headers, we do not save its name in
  // the string table.
  if (ExcludedSectionHeaders.count(Name))
    return 0;
  return ShStrtabStrings->getOffset(Name);
}

static uint64_t writeContent(ContiguousBlobAccumulator &CBA,
                             const Optional<yaml::BinaryRef> &Content,
                             const Optional<llvm::yaml::Hex64> &Size) {
  size_t ContentSize = 0;
  if (Content) {
    CBA.writeAsBinary(*Content);
    ContentSize = Content->binary_size();
  }

  if (!Size)
    return ContentSize;

  CBA.writeZeros(*Size - ContentSize);
  return *Size;
}

static StringRef getDefaultLinkSec(unsigned SecType) {
  switch (SecType) {
  case ELF::SHT_REL:
  case ELF::SHT_RELA:
  case ELF::SHT_GROUP:
  case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
  case ELF::SHT_LLVM_ADDRSIG:
    return ".symtab";
  case ELF::SHT_GNU_versym:
  case ELF::SHT_HASH:
  case ELF::SHT_GNU_HASH:
    return ".dynsym";
  case ELF::SHT_DYNSYM:
  case ELF::SHT_GNU_verdef:
  case ELF::SHT_GNU_verneed:
    return ".dynstr";
  case ELF::SHT_SYMTAB:
    return ".strtab";
  default:
    return "";
  }
}

template <class ELFT>
void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
                                        ContiguousBlobAccumulator &CBA) {
  // Ensure SHN_UNDEF entry is present. An all-zero section header is a
  // valid SHN_UNDEF entry since SHT_NULL == 0.
  SHeaders.resize(Doc.getSections().size());

  for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) {
    if (ELFYAML::Fill *S = dyn_cast<ELFYAML::Fill>(D.get())) {
      S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset);
      writeFill(*S, CBA);
      LocationCounter += S->Size;
      continue;
    }

    if (ELFYAML::SectionHeaderTable *S =
            dyn_cast<ELFYAML::SectionHeaderTable>(D.get())) {
      if (S->NoHeaders.getValueOr(false))
        continue;

      if (!S->Offset)
        S->Offset = alignToOffset(CBA, sizeof(typename ELFT::uint),
                                  /*Offset=*/None);
      else
        S->Offset = alignToOffset(CBA, /*Align=*/1, S->Offset);

      uint64_t Size = S->getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr);
      // The full section header information might be not available here, so
      // fill the space with zeroes as a placeholder.
      CBA.writeZeros(Size);
      LocationCounter += Size;
      continue;
    }

    ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get());
    bool IsFirstUndefSection = Sec == Doc.getSections().front();
    if (IsFirstUndefSection && Sec->IsImplicit)
      continue;

    Elf_Shdr &SHeader = SHeaders[SN2I.get(Sec->Name)];
    if (Sec->Link) {
      SHeader.sh_link = toSectionIndex(*Sec->Link, Sec->Name);
    } else {
      StringRef LinkSec = getDefaultLinkSec(Sec->Type);
      unsigned Link = 0;
      if (!LinkSec.empty() && !ExcludedSectionHeaders.count(LinkSec) &&
          SN2I.lookup(LinkSec, Link))
        SHeader.sh_link = Link;
    }

    if (Sec->EntSize)
      SHeader.sh_entsize = *Sec->EntSize;
    else
      SHeader.sh_entsize = ELFYAML::getDefaultShEntSize<ELFT>(
          Doc.Header.Machine.getValueOr(ELF::EM_NONE), Sec->Type, Sec->Name);

    // We have a few sections like string or symbol tables that are usually
    // added implicitly to the end. However, if they are explicitly specified
    // in the YAML, we need to write them here. This ensures the file offset
    // remains correct.
    if (initImplicitHeader(CBA, SHeader, Sec->Name,
                           Sec->IsImplicit ? nullptr : Sec))
      continue;

    assert(Sec && "It can't be null unless it is an implicit section. But all "
                  "implicit sections should already have been handled above.");

    SHeader.sh_name =
        getSectionNameOffset(ELFYAML::dropUniqueSuffix(Sec->Name));
    SHeader.sh_type = Sec->Type;
    if (Sec->Flags)
      SHeader.sh_flags = *Sec->Flags;
    SHeader.sh_addralign = Sec->AddressAlign;

    // Set the offset for all sections, except the SHN_UNDEF section with index
    // 0 when not explicitly requested.
    if (!IsFirstUndefSection || Sec->Offset)
      SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign, Sec->Offset);

    assignSectionAddress(SHeader, Sec);

    if (IsFirstUndefSection) {
      if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
        // We do not write any content for special SHN_UNDEF section.
        if (RawSec->Size)
          SHeader.sh_size = *RawSec->Size;
        if (RawSec->Info)
          SHeader.sh_info = *RawSec->Info;
      }

      LocationCounter += SHeader.sh_size;
      overrideFields<ELFT>(Sec, SHeader);
      continue;
    }

    if (!isa<ELFYAML::NoBitsSection>(Sec) && (Sec->Content || Sec->Size))
      SHeader.sh_size = writeContent(CBA, Sec->Content, Sec->Size);

    if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::RelrSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::GroupSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::ARMIndexTableSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::DynamicSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::SymverSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::StackSizesSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::HashSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::LinkerOptionsSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::NoteSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::GnuHashSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::DependentLibrariesSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::CallGraphProfileSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else if (auto S = dyn_cast<ELFYAML::BBAddrMapSection>(Sec)) {
      writeSectionContent(SHeader, *S, CBA);
    } else {
      llvm_unreachable("Unknown section type");
    }

    LocationCounter += SHeader.sh_size;

    // Override section fields if requested.
    overrideFields<ELFT>(Sec, SHeader);
  }
}

template <class ELFT>
void ELFState<ELFT>::assignSectionAddress(Elf_Shdr &SHeader,
                                          ELFYAML::Section *YAMLSec) {
  if (YAMLSec && YAMLSec->Address) {
    SHeader.sh_addr = *YAMLSec->Address;
    LocationCounter = *YAMLSec->Address;
    return;
  }

  // sh_addr represents the address in the memory image of a process. Sections
  // in a relocatable object file or non-allocatable sections do not need
  // sh_addr assignment.
  if (Doc.Header.Type.value == ELF::ET_REL ||
      !(SHeader.sh_flags & ELF::SHF_ALLOC))
    return;

  LocationCounter =
      alignTo(LocationCounter, SHeader.sh_addralign ? SHeader.sh_addralign : 1);
  SHeader.sh_addr = LocationCounter;
}

static size_t findFirstNonGlobal(ArrayRef<ELFYAML::Symbol> Symbols) {
  for (size_t I = 0; I < Symbols.size(); ++I)
    if (Symbols[I].Binding.value != ELF::STB_LOCAL)
      return I;
  return Symbols.size();
}

template <class ELFT>
std::vector<typename ELFT::Sym>
ELFState<ELFT>::toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols,
                             const StringTableBuilder &Strtab) {
  std::vector<Elf_Sym> Ret;
  Ret.resize(Symbols.size() + 1);

  size_t I = 0;
  for (const ELFYAML::Symbol &Sym : Symbols) {
    Elf_Sym &Symbol = Ret[++I];

    // If NameIndex, which contains the name offset, is explicitly specified, we
    // use it. This is useful for preparing broken objects. Otherwise, we add
    // the specified Name to the string table builder to get its offset.
    if (Sym.StName)
      Symbol.st_name = *Sym.StName;
    else if (!Sym.Name.empty())
      Symbol.st_name = Strtab.getOffset(ELFYAML::dropUniqueSuffix(Sym.Name));

    Symbol.setBindingAndType(Sym.Binding, Sym.Type);
    if (Sym.Section)
      Symbol.st_shndx = toSectionIndex(*Sym.Section, "", Sym.Name);
    else if (Sym.Index)
      Symbol.st_shndx = *Sym.Index;

    Symbol.st_value = Sym.Value.getValueOr(yaml::Hex64(0));
    Symbol.st_other = Sym.Other ? *Sym.Other : 0;
    Symbol.st_size = Sym.Size.getValueOr(yaml::Hex64(0));
  }

  return Ret;
}

template <class ELFT>
void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
                                             SymtabType STType,
                                             ContiguousBlobAccumulator &CBA,
                                             ELFYAML::Section *YAMLSec) {

  bool IsStatic = STType == SymtabType::Static;
  ArrayRef<ELFYAML::Symbol> Symbols;
  if (IsStatic && Doc.Symbols)
    Symbols = *Doc.Symbols;
  else if (!IsStatic && Doc.DynamicSymbols)
    Symbols = *Doc.DynamicSymbols;

  ELFYAML::RawContentSection *RawSec =
      dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);
  if (RawSec && (RawSec->Content || RawSec->Size)) {
    bool HasSymbolsDescription =
        (IsStatic && Doc.Symbols) || (!IsStatic && Doc.DynamicSymbols);
    if (HasSymbolsDescription) {
      StringRef Property = (IsStatic ? "`Symbols`" : "`DynamicSymbols`");
      if (RawSec->Content)
        reportError("cannot specify both `Content` and " + Property +
                    " for symbol table section '" + RawSec->Name + "'");
      if (RawSec->Size)
        reportError("cannot specify both `Size` and " + Property +
                    " for symbol table section '" + RawSec->Name + "'");
      return;
    }
  }

  SHeader.sh_name = getSectionNameOffset(IsStatic ? ".symtab" : ".dynsym");

  if (YAMLSec)
    SHeader.sh_type = YAMLSec->Type;
  else
    SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM;

  if (YAMLSec && YAMLSec->Flags)
    SHeader.sh_flags = *YAMLSec->Flags;
  else if (!IsStatic)
    SHeader.sh_flags = ELF::SHF_ALLOC;

  // If the symbol table section is explicitly described in the YAML
  // then we should set the fields requested.
  SHeader.sh_info = (RawSec && RawSec->Info) ? (unsigned)(*RawSec->Info)
                                             : findFirstNonGlobal(Symbols) + 1;
  SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 8;

  assignSectionAddress(SHeader, YAMLSec);

  SHeader.sh_offset =
      alignToOffset(CBA, SHeader.sh_addralign, RawSec ? RawSec->Offset : None);

  if (RawSec && (RawSec->Content || RawSec->Size)) {
    assert(Symbols.empty());
    SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size);
    return;
  }

  std::vector<Elf_Sym> Syms =
      toELFSymbols(Symbols, IsStatic ? DotStrtab : DotDynstr);
  SHeader.sh_size = Syms.size() * sizeof(Elf_Sym);
  CBA.write((const char *)Syms.data(), SHeader.sh_size);
}

template <class ELFT>
void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
                                             StringTableBuilder &STB,
                                             ContiguousBlobAccumulator &CBA,
                                             ELFYAML::Section *YAMLSec) {
  SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));
  SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB;
  SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;

  ELFYAML::RawContentSection *RawSec =
      dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);

  SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,
                                    YAMLSec ? YAMLSec->Offset : None);

  if (RawSec && (RawSec->Content || RawSec->Size)) {
    SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size);
  } else {
    if (raw_ostream *OS = CBA.getRawOS(STB.getSize()))
      STB.write(*OS);
    SHeader.sh_size = STB.getSize();
  }

  if (RawSec && RawSec->Info)
    SHeader.sh_info = *RawSec->Info;

  if (YAMLSec && YAMLSec->Flags)
    SHeader.sh_flags = *YAMLSec->Flags;
  else if (Name == ".dynstr")
    SHeader.sh_flags = ELF::SHF_ALLOC;

  assignSectionAddress(SHeader, YAMLSec);
}

static bool shouldEmitDWARF(DWARFYAML::Data &DWARF, StringRef Name) {
  SetVector<StringRef> DebugSecNames = DWARF.getNonEmptySectionNames();
  return Name.consume_front(".") && DebugSecNames.count(Name);
}

template <class ELFT>
Expected<uint64_t> emitDWARF(typename ELFT::Shdr &SHeader, StringRef Name,
                             const DWARFYAML::Data &DWARF,
                             ContiguousBlobAccumulator &CBA) {
  // We are unable to predict the size of debug data, so we request to write 0
  // bytes. This should always return us an output stream unless CBA is already
  // in an error state.
  raw_ostream *OS = CBA.getRawOS(0);
  if (!OS)
    return 0;

  uint64_t BeginOffset = CBA.tell();

  auto EmitFunc = DWARFYAML::getDWARFEmitterByName(Name.substr(1));
  if (Error Err = EmitFunc(*OS, DWARF))
    return std::move(Err);

  return CBA.tell() - BeginOffset;
}

template <class ELFT>
void ELFState<ELFT>::initDWARFSectionHeader(Elf_Shdr &SHeader, StringRef Name,
                                            ContiguousBlobAccumulator &CBA,
                                            ELFYAML::Section *YAMLSec) {
  SHeader.sh_name = getSectionNameOffset(ELFYAML::dropUniqueSuffix(Name));
  SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS;
  SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1;
  SHeader.sh_offset = alignToOffset(CBA, SHeader.sh_addralign,
                                    YAMLSec ? YAMLSec->Offset : None);

  ELFYAML::RawContentSection *RawSec =
      dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec);
  if (Doc.DWARF && shouldEmitDWARF(*Doc.DWARF, Name)) {
    if (RawSec && (RawSec->Content || RawSec->Size))
      reportError("cannot specify section '" + Name +
                  "' contents in the 'DWARF' entry and the 'Content' "
                  "or 'Size' in the 'Sections' entry at the same time");
    else {
      if (Expected<uint64_t> ShSizeOrErr =
              emitDWARF<ELFT>(SHeader, Name, *Doc.DWARF, CBA))
        SHeader.sh_size = *ShSizeOrErr;
      else
        reportError(ShSizeOrErr.takeError());
    }
  } else if (RawSec)
    SHeader.sh_size = writeContent(CBA, RawSec->Content, RawSec->Size);
  else
    llvm_unreachable("debug sections can only be initialized via the 'DWARF' "
                     "entry or a RawContentSection");

  if (RawSec && RawSec->Info)
    SHeader.sh_info = *RawSec->Info;

  if (YAMLSec && YAMLSec->Flags)
    SHeader.sh_flags = *YAMLSec->Flags;
  else if (Name == ".debug_str")
    SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS;

  assignSectionAddress(SHeader, YAMLSec);
}

template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) {
  ErrHandler(Msg);
  HasError = true;
}

template <class ELFT> void ELFState<ELFT>::reportError(Error Err) {
  handleAllErrors(std::move(Err), [&](const ErrorInfoBase &Err) {
    reportError(Err.message());
  });
}

template <class ELFT>
std::vector<Fragment>
ELFState<ELFT>::getPhdrFragments(const ELFYAML::ProgramHeader &Phdr,
                                 ArrayRef<Elf_Shdr> SHeaders) {
  std::vector<Fragment> Ret;
  for (const ELFYAML::Chunk *C : Phdr.Chunks) {
    if (const ELFYAML::Fill *F = dyn_cast<ELFYAML::Fill>(C)) {
      Ret.push_back({*F->Offset, F->Size, llvm::ELF::SHT_PROGBITS,
                     /*ShAddrAlign=*/1});
      continue;
    }

    const ELFYAML::Section *S = cast<ELFYAML::Section>(C);
    const Elf_Shdr &H = SHeaders[SN2I.get(S->Name)];
    Ret.push_back({H.sh_offset, H.sh_size, H.sh_type, H.sh_addralign});
  }
  return Ret;
}

template <class ELFT>
void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
                                            std::vector<Elf_Shdr> &SHeaders) {
  uint32_t PhdrIdx = 0;
  for (auto &YamlPhdr : Doc.ProgramHeaders) {
    Elf_Phdr &PHeader = PHeaders[PhdrIdx++];
    std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders);
    if (!llvm::is_sorted(Fragments, [](const Fragment &A, const Fragment &B) {
          return A.Offset < B.Offset;
        }))
      reportError("sections in the program header with index " +
                  Twine(PhdrIdx) + " are not sorted by their file offset");

    if (YamlPhdr.Offset) {
      if (!Fragments.empty() && *YamlPhdr.Offset > Fragments.front().Offset)
        reportError("'Offset' for segment with index " + Twine(PhdrIdx) +
                    " must be less than or equal to the minimum file offset of "
                    "all included sections (0x" +
                    Twine::utohexstr(Fragments.front().Offset) + ")");
      PHeader.p_offset = *YamlPhdr.Offset;
    } else if (!Fragments.empty()) {
      PHeader.p_offset = Fragments.front().Offset;
    }

    // Set the file size if not set explicitly.
    if (YamlPhdr.FileSize) {
      PHeader.p_filesz = *YamlPhdr.FileSize;
    } else if (!Fragments.empty()) {
      uint64_t FileSize = Fragments.back().Offset - PHeader.p_offset;
      // SHT_NOBITS sections occupy no physical space in a file, we should not
      // take their sizes into account when calculating the file size of a
      // segment.
      if (Fragments.back().Type != llvm::ELF::SHT_NOBITS)
        FileSize += Fragments.back().Size;
      PHeader.p_filesz = FileSize;
    }

    // Find the maximum offset of the end of a section in order to set p_memsz.
    uint64_t MemOffset = PHeader.p_offset;
    for (const Fragment &F : Fragments)
      MemOffset = std::max(MemOffset, F.Offset + F.Size);
    // Set the memory size if not set explicitly.
    PHeader.p_memsz = YamlPhdr.MemSize ? uint64_t(*YamlPhdr.MemSize)
                                       : MemOffset - PHeader.p_offset;

    if (YamlPhdr.Align) {
      PHeader.p_align = *YamlPhdr.Align;
    } else {
      // Set the alignment of the segment to be the maximum alignment of the
      // sections so that by default the segment has a valid and sensible
      // alignment.
      PHeader.p_align = 1;
      for (const Fragment &F : Fragments)
        PHeader.p_align = std::max((uint64_t)PHeader.p_align, F.AddrAlign);
    }
  }
}

bool llvm::ELFYAML::shouldAllocateFileSpace(
    ArrayRef<ELFYAML::ProgramHeader> Phdrs, const ELFYAML::NoBitsSection &S) {
  for (const ELFYAML::ProgramHeader &PH : Phdrs) {
    auto It = llvm::find_if(
        PH.Chunks, [&](ELFYAML::Chunk *C) { return C->Name == S.Name; });
    if (std::any_of(It, PH.Chunks.end(), [](ELFYAML::Chunk *C) {
          return (isa<ELFYAML::Fill>(C) ||
                  cast<ELFYAML::Section>(C)->Type != ELF::SHT_NOBITS);
        }))
      return true;
  }
  return false;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::NoBitsSection &S,
                                         ContiguousBlobAccumulator &CBA) {
  if (!S.Size)
    return;

  SHeader.sh_size = *S.Size;

  // When a nobits section is followed by a non-nobits section or fill
  // in the same segment, we allocate the file space for it. This behavior
  // matches linkers.
  if (shouldAllocateFileSpace(Doc.ProgramHeaders, S))
    CBA.writeZeros(*S.Size);
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (Section.Info)
    SHeader.sh_info = *Section.Info;
}

static bool isMips64EL(const ELFYAML::Object &Obj) {
  return Obj.getMachine() == llvm::ELF::EM_MIPS &&
         Obj.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) &&
         Obj.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section,
    ContiguousBlobAccumulator &CBA) {
  assert((Section.Type == llvm::ELF::SHT_REL ||
          Section.Type == llvm::ELF::SHT_RELA) &&
         "Section type is not SHT_REL nor SHT_RELA");

  if (!Section.RelocatableSec.empty())
    SHeader.sh_info = toSectionIndex(Section.RelocatableSec, Section.Name);

  if (!Section.Relocations)
    return;

  const bool IsRela = Section.Type == llvm::ELF::SHT_RELA;
  for (const ELFYAML::Relocation &Rel : *Section.Relocations) {
    const bool IsDynamic = Section.Link && (*Section.Link == ".dynsym");
    unsigned SymIdx =
        Rel.Symbol ? toSymbolIndex(*Rel.Symbol, Section.Name, IsDynamic) : 0;
    if (IsRela) {
      Elf_Rela REntry;
      zero(REntry);
      REntry.r_offset = Rel.Offset;
      REntry.r_addend = Rel.Addend;
      REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
      CBA.write((const char *)&REntry, sizeof(REntry));
    } else {
      Elf_Rel REntry;
      zero(REntry);
      REntry.r_offset = Rel.Offset;
      REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
      CBA.write((const char *)&REntry, sizeof(REntry));
    }
  }

  SHeader.sh_size = (IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)) *
                    Section.Relocations->size();
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::RelrSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (!Section.Entries)
    return;

  for (llvm::yaml::Hex64 E : *Section.Entries) {
    if (!ELFT::Is64Bits && E > UINT32_MAX)
      reportError(Section.Name + ": the value is too large for 32-bits: 0x" +
                  Twine::utohexstr(E));
    CBA.write<uintX_t>(E, ELFT::TargetEndianness);
  }

  SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size();
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx,
    ContiguousBlobAccumulator &CBA) {
  if (Shndx.Content || Shndx.Size) {
    SHeader.sh_size = writeContent(CBA, Shndx.Content, Shndx.Size);
    return;
  }

  if (!Shndx.Entries)
    return;

  for (uint32_t E : *Shndx.Entries)
    CBA.write<uint32_t>(E, ELFT::TargetEndianness);
  SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::GroupSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  assert(Section.Type == llvm::ELF::SHT_GROUP &&
         "Section type is not SHT_GROUP");

  if (Section.Signature)
    SHeader.sh_info =
        toSymbolIndex(*Section.Signature, Section.Name, /*IsDynamic=*/false);

  if (!Section.Members)
    return;

  for (const ELFYAML::SectionOrType &Member : *Section.Members) {
    unsigned int SectionIndex = 0;
    if (Member.sectionNameOrType == "GRP_COMDAT")
      SectionIndex = llvm::ELF::GRP_COMDAT;
    else
      SectionIndex = toSectionIndex(Member.sectionNameOrType, Section.Name);
    CBA.write<uint32_t>(SectionIndex, ELFT::TargetEndianness);
  }
  SHeader.sh_size = SHeader.sh_entsize * Section.Members->size();
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::SymverSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (!Section.Entries)
    return;

  for (uint16_t Version : *Section.Entries)
    CBA.write<uint16_t>(Version, ELFT::TargetEndianness);
  SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (!Section.Entries)
    return;

  for (const ELFYAML::StackSizeEntry &E : *Section.Entries) {
    CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness);
    SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(E.Size);
  }
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::BBAddrMapSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (!Section.Entries)
    return;

  for (const ELFYAML::BBAddrMapEntry &E : *Section.Entries) {
    // Write the address of the function.
    CBA.write<uintX_t>(E.Address, ELFT::TargetEndianness);
    // Write number of BBEntries (number of basic blocks in the function). This
    // is overridden by the 'NumBlocks' YAML field when specified.
    uint64_t NumBlocks =
        E.NumBlocks.getValueOr(E.BBEntries ? E.BBEntries->size() : 0);
    SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks);
    // Write all BBEntries.
    if (!E.BBEntries)
      continue;
    for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *E.BBEntries)
      SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset) +
                         CBA.writeULEB128(BBE.Size) +
                         CBA.writeULEB128(BBE.Metadata);
  }
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (!Section.Options)
    return;

  for (const ELFYAML::LinkerOption &LO : *Section.Options) {
    CBA.write(LO.Key.data(), LO.Key.size());
    CBA.write('\0');
    CBA.write(LO.Value.data(), LO.Value.size());
    CBA.write('\0');
    SHeader.sh_size += (LO.Key.size() + LO.Value.size() + 2);
  }
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::DependentLibrariesSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (!Section.Libs)
    return;

  for (StringRef Lib : *Section.Libs) {
    CBA.write(Lib.data(), Lib.size());
    CBA.write('\0');
    SHeader.sh_size += Lib.size() + 1;
  }
}

template <class ELFT>
uint64_t
ELFState<ELFT>::alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align,
                              llvm::Optional<llvm::yaml::Hex64> Offset) {
  uint64_t CurrentOffset = CBA.getOffset();
  uint64_t AlignedOffset;

  if (Offset) {
    if ((uint64_t)*Offset < CurrentOffset) {
      reportError("the 'Offset' value (0x" +
                  Twine::utohexstr((uint64_t)*Offset) + ") goes backward");
      return CurrentOffset;
    }

    // We ignore an alignment when an explicit offset has been requested.
    AlignedOffset = *Offset;
  } else {
    AlignedOffset = alignTo(CurrentOffset, std::max(Align, (uint64_t)1));
  }

  CBA.writeZeros(AlignedOffset - CurrentOffset);
  return AlignedOffset;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::CallGraphProfileSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (!Section.Entries)
    return;

  for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) {
    CBA.write<uint64_t>(E.Weight, ELFT::TargetEndianness);
    SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl<ELFT>);
  }
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::HashSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (!Section.Bucket)
    return;

  CBA.write<uint32_t>(
      Section.NBucket.getValueOr(llvm::yaml::Hex64(Section.Bucket->size())),
      ELFT::TargetEndianness);
  CBA.write<uint32_t>(
      Section.NChain.getValueOr(llvm::yaml::Hex64(Section.Chain->size())),
      ELFT::TargetEndianness);

  for (uint32_t Val : *Section.Bucket)
    CBA.write<uint32_t>(Val, ELFT::TargetEndianness);
  for (uint32_t Val : *Section.Chain)
    CBA.write<uint32_t>(Val, ELFT::TargetEndianness);

  SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::VerdefSection &Section,
                                         ContiguousBlobAccumulator &CBA) {

  if (Section.Info)
    SHeader.sh_info = *Section.Info;
  else if (Section.Entries)
    SHeader.sh_info = Section.Entries->size();

  if (!Section.Entries)
    return;

  uint64_t AuxCnt = 0;
  for (size_t I = 0; I < Section.Entries->size(); ++I) {
    const ELFYAML::VerdefEntry &E = (*Section.Entries)[I];

    Elf_Verdef VerDef;
    VerDef.vd_version = E.Version.getValueOr(1);
    VerDef.vd_flags = E.Flags.getValueOr(0);
    VerDef.vd_ndx = E.VersionNdx.getValueOr(0);
    VerDef.vd_hash = E.Hash.getValueOr(0);
    VerDef.vd_aux = sizeof(Elf_Verdef);
    VerDef.vd_cnt = E.VerNames.size();
    if (I == Section.Entries->size() - 1)
      VerDef.vd_next = 0;
    else
      VerDef.vd_next =
          sizeof(Elf_Verdef) + E.VerNames.size() * sizeof(Elf_Verdaux);
    CBA.write((const char *)&VerDef, sizeof(Elf_Verdef));

    for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) {
      Elf_Verdaux VernAux;
      VernAux.vda_name = DotDynstr.getOffset(E.VerNames[J]);
      if (J == E.VerNames.size() - 1)
        VernAux.vda_next = 0;
      else
        VernAux.vda_next = sizeof(Elf_Verdaux);
      CBA.write((const char *)&VernAux, sizeof(Elf_Verdaux));
    }
  }

  SHeader.sh_size = Section.Entries->size() * sizeof(Elf_Verdef) +
                    AuxCnt * sizeof(Elf_Verdaux);
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::VerneedSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (Section.Info)
    SHeader.sh_info = *Section.Info;
  else if (Section.VerneedV)
    SHeader.sh_info = Section.VerneedV->size();

  if (!Section.VerneedV)
    return;

  uint64_t AuxCnt = 0;
  for (size_t I = 0; I < Section.VerneedV->size(); ++I) {
    const ELFYAML::VerneedEntry &VE = (*Section.VerneedV)[I];

    Elf_Verneed VerNeed;
    VerNeed.vn_version = VE.Version;
    VerNeed.vn_file = DotDynstr.getOffset(VE.File);
    if (I == Section.VerneedV->size() - 1)
      VerNeed.vn_next = 0;
    else
      VerNeed.vn_next =
          sizeof(Elf_Verneed) + VE.AuxV.size() * sizeof(Elf_Vernaux);
    VerNeed.vn_cnt = VE.AuxV.size();
    VerNeed.vn_aux = sizeof(Elf_Verneed);
    CBA.write((const char *)&VerNeed, sizeof(Elf_Verneed));

    for (size_t J = 0; J < VE.AuxV.size(); ++J, ++AuxCnt) {
      const ELFYAML::VernauxEntry &VAuxE = VE.AuxV[J];

      Elf_Vernaux VernAux;
      VernAux.vna_hash = VAuxE.Hash;
      VernAux.vna_flags = VAuxE.Flags;
      VernAux.vna_other = VAuxE.Other;
      VernAux.vna_name = DotDynstr.getOffset(VAuxE.Name);
      if (J == VE.AuxV.size() - 1)
        VernAux.vna_next = 0;
      else
        VernAux.vna_next = sizeof(Elf_Vernaux);
      CBA.write((const char *)&VernAux, sizeof(Elf_Vernaux));
    }
  }

  SHeader.sh_size = Section.VerneedV->size() * sizeof(Elf_Verneed) +
                    AuxCnt * sizeof(Elf_Vernaux);
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(
    Elf_Shdr &SHeader, const ELFYAML::ARMIndexTableSection &Section,
    ContiguousBlobAccumulator &CBA) {
  if (!Section.Entries)
    return;

  for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) {
    CBA.write<uint32_t>(E.Offset, ELFT::TargetEndianness);
    CBA.write<uint32_t>(E.Value, ELFT::TargetEndianness);
  }
  SHeader.sh_size = Section.Entries->size() * 8;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::MipsABIFlags &Section,
                                         ContiguousBlobAccumulator &CBA) {
  assert(Section.Type == llvm::ELF::SHT_MIPS_ABIFLAGS &&
         "Section type is not SHT_MIPS_ABIFLAGS");

  object::Elf_Mips_ABIFlags<ELFT> Flags;
  zero(Flags);
  SHeader.sh_size = SHeader.sh_entsize;

  Flags.version = Section.Version;
  Flags.isa_level = Section.ISALevel;
  Flags.isa_rev = Section.ISARevision;
  Flags.gpr_size = Section.GPRSize;
  Flags.cpr1_size = Section.CPR1Size;
  Flags.cpr2_size = Section.CPR2Size;
  Flags.fp_abi = Section.FpABI;
  Flags.isa_ext = Section.ISAExtension;
  Flags.ases = Section.ASEs;
  Flags.flags1 = Section.Flags1;
  Flags.flags2 = Section.Flags2;
  CBA.write((const char *)&Flags, sizeof(Flags));
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::DynamicSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  assert(Section.Type == llvm::ELF::SHT_DYNAMIC &&
         "Section type is not SHT_DYNAMIC");

  if (!Section.Entries)
    return;

  for (const ELFYAML::DynamicEntry &DE : *Section.Entries) {
    CBA.write<uintX_t>(DE.Tag, ELFT::TargetEndianness);
    CBA.write<uintX_t>(DE.Val, ELFT::TargetEndianness);
  }
  SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size();
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::AddrsigSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (!Section.Symbols)
    return;

  for (StringRef Sym : *Section.Symbols)
    SHeader.sh_size +=
        CBA.writeULEB128(toSymbolIndex(Sym, Section.Name, /*IsDynamic=*/false));
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::NoteSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (!Section.Notes)
    return;

  uint64_t Offset = CBA.tell();
  for (const ELFYAML::NoteEntry &NE : *Section.Notes) {
    // Write name size.
    if (NE.Name.empty())
      CBA.write<uint32_t>(0, ELFT::TargetEndianness);
    else
      CBA.write<uint32_t>(NE.Name.size() + 1, ELFT::TargetEndianness);

    // Write description size.
    if (NE.Desc.binary_size() == 0)
      CBA.write<uint32_t>(0, ELFT::TargetEndianness);
    else
      CBA.write<uint32_t>(NE.Desc.binary_size(), ELFT::TargetEndianness);

    // Write type.
    CBA.write<uint32_t>(NE.Type, ELFT::TargetEndianness);

    // Write name, null terminator and padding.
    if (!NE.Name.empty()) {
      CBA.write(NE.Name.data(), NE.Name.size());
      CBA.write('\0');
      CBA.padToAlignment(4);
    }

    // Write description and padding.
    if (NE.Desc.binary_size() != 0) {
      CBA.writeAsBinary(NE.Desc);
      CBA.padToAlignment(4);
    }
  }

  SHeader.sh_size = CBA.tell() - Offset;
}

template <class ELFT>
void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
                                         const ELFYAML::GnuHashSection &Section,
                                         ContiguousBlobAccumulator &CBA) {
  if (!Section.HashBuckets)
    return;

  if (!Section.Header)
    return;

  // We write the header first, starting with the hash buckets count. Normally
  // it is the number of entries in HashBuckets, but the "NBuckets" property can
  // be used to override this field, which is useful for producing broken
  // objects.
  if (Section.Header->NBuckets)
    CBA.write<uint32_t>(*Section.Header->NBuckets, ELFT::TargetEndianness);
  else
    CBA.write<uint32_t>(Section.HashBuckets->size(), ELFT::TargetEndianness);

  // Write the index of the first symbol in the dynamic symbol table accessible
  // via the hash table.
  CBA.write<uint32_t>(Section.Header->SymNdx, ELFT::TargetEndianness);

  // Write the number of words in the Bloom filter. As above, the "MaskWords"
  // property can be used to set this field to any value.
  if (Section.Header->MaskWords)
    CBA.write<uint32_t>(*Section.Header->MaskWords, ELFT::TargetEndianness);
  else
    CBA.write<uint32_t>(Section.BloomFilter->size(), ELFT::TargetEndianness);

  // Write the shift constant used by the Bloom filter.
  CBA.write<uint32_t>(Section.Header->Shift2, ELFT::TargetEndianness);

  // We've finished writing the header. Now write the Bloom filter.
  for (llvm::yaml::Hex64 Val : *Section.BloomFilter)
    CBA.write<uintX_t>(Val, ELFT::TargetEndianness);

  // Write an array of hash buckets.
  for (llvm::yaml::Hex32 Val : *Section.HashBuckets)
    CBA.write<uint32_t>(Val, ELFT::TargetEndianness);

  // Write an array of hash values.
  for (llvm::yaml::Hex32 Val : *Section.HashValues)
    CBA.write<uint32_t>(Val, ELFT::TargetEndianness);

  SHeader.sh_size = 16 /*Header size*/ +
                    Section.BloomFilter->size() * sizeof(typename ELFT::uint) +
                    Section.HashBuckets->size() * 4 +
                    Section.HashValues->size() * 4;
}

template <class ELFT>
void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill,
                               ContiguousBlobAccumulator &CBA) {
  size_t PatternSize = Fill.Pattern ? Fill.Pattern->binary_size() : 0;
  if (!PatternSize) {
    CBA.writeZeros(Fill.Size);
    return;
  }

  // Fill the content with the specified pattern.
  uint64_t Written = 0;
  for (; Written + PatternSize <= Fill.Size; Written += PatternSize)
    CBA.writeAsBinary(*Fill.Pattern);
  CBA.writeAsBinary(*Fill.Pattern, Fill.Size - Written);
}

template <class ELFT>
DenseMap<StringRef, size_t> ELFState<ELFT>::buildSectionHeaderReorderMap() {
  const ELFYAML::SectionHeaderTable &SectionHeaders =
      Doc.getSectionHeaderTable();
  if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders ||
      SectionHeaders.isDefault())
    return DenseMap<StringRef, size_t>();

  DenseMap<StringRef, size_t> Ret;
  size_t SecNdx = 0;
  StringSet<> Seen;

  auto AddSection = [&](const ELFYAML::SectionHeader &Hdr) {
    if (!Ret.try_emplace(Hdr.Name, ++SecNdx).second)
      reportError("repeated section name: '" + Hdr.Name +
                  "' in the section header description");
    Seen.insert(Hdr.Name);
  };

  if (SectionHeaders.Sections)
    for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Sections)
      AddSection(Hdr);

  if (SectionHeaders.Excluded)
    for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded)
      AddSection(Hdr);

  for (const ELFYAML::Section *S : Doc.getSections()) {
    // Ignore special first SHT_NULL section.
    if (S == Doc.getSections().front())
      continue;
    if (!Seen.count(S->Name))
      reportError("section '" + S->Name +
                  "' should be present in the 'Sections' or 'Excluded' lists");
    Seen.erase(S->Name);
  }

  for (const auto &It : Seen)
    reportError("section header contains undefined section '" + It.getKey() +
                "'");
  return Ret;
}

template <class ELFT> void ELFState<ELFT>::buildSectionIndex() {
  // A YAML description can have an explicit section header declaration that
  // allows to change the order of section headers.
  DenseMap<StringRef, size_t> ReorderMap = buildSectionHeaderReorderMap();

  if (HasError)
    return;

  // Build excluded section headers map.
  std::vector<ELFYAML::Section *> Sections = Doc.getSections();
  const ELFYAML::SectionHeaderTable &SectionHeaders =
      Doc.getSectionHeaderTable();
  if (SectionHeaders.Excluded)
    for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded)
      if (!ExcludedSectionHeaders.insert(Hdr.Name).second)
        llvm_unreachable("buildSectionIndex() failed");

  if (SectionHeaders.NoHeaders.getValueOr(false))
    for (const ELFYAML::Section *S : Sections)
      if (!ExcludedSectionHeaders.insert(S->Name).second)
        llvm_unreachable("buildSectionIndex() failed");

  size_t SecNdx = -1;
  for (const ELFYAML::Section *S : Sections) {
    ++SecNdx;

    size_t Index = ReorderMap.empty() ? SecNdx : ReorderMap.lookup(S->Name);
    if (!SN2I.addName(S->Name, Index))
      llvm_unreachable("buildSectionIndex() failed");

    if (!ExcludedSectionHeaders.count(S->Name))
      ShStrtabStrings->add(ELFYAML::dropUniqueSuffix(S->Name));
  }
}

template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() {
  auto Build = [this](ArrayRef<ELFYAML::Symbol> V, NameToIdxMap &Map) {
    for (size_t I = 0, S = V.size(); I < S; ++I) {
      const ELFYAML::Symbol &Sym = V[I];
      if (!Sym.Name.empty() && !Map.addName(Sym.Name, I + 1))
        reportError("repeated symbol name: '" + Sym.Name + "'");
    }
  };

  if (Doc.Symbols)
    Build(*Doc.Symbols, SymN2I);
  if (Doc.DynamicSymbols)
    Build(*Doc.DynamicSymbols, DynSymN2I);
}

template <class ELFT> void ELFState<ELFT>::finalizeStrings() {
  // Add the regular symbol names to .strtab section.
  if (Doc.Symbols)
    for (const ELFYAML::Symbol &Sym : *Doc.Symbols)
      DotStrtab.add(ELFYAML::dropUniqueSuffix(Sym.Name));
  DotStrtab.finalize();

  // Add the dynamic symbol names to .dynstr section.
  if (Doc.DynamicSymbols)
    for (const ELFYAML::Symbol &Sym : *Doc.DynamicSymbols)
      DotDynstr.add(ELFYAML::dropUniqueSuffix(Sym.Name));

  // SHT_GNU_verdef and SHT_GNU_verneed sections might also
  // add strings to .dynstr section.
  for (const ELFYAML::Chunk *Sec : Doc.getSections()) {
    if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec)) {
      if (VerNeed->VerneedV) {
        for (const ELFYAML::VerneedEntry &VE : *VerNeed->VerneedV) {
          DotDynstr.add(VE.File);
          for (const ELFYAML::VernauxEntry &Aux : VE.AuxV)
            DotDynstr.add(Aux.Name);
        }
      }
    } else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec)) {
      if (VerDef->Entries)
        for (const ELFYAML::VerdefEntry &E : *VerDef->Entries)
          for (StringRef Name : E.VerNames)
            DotDynstr.add(Name);
    }
  }

  DotDynstr.finalize();

  // Don't finalize the section header string table a second time if it has
  // already been finalized due to being one of the symbol string tables.
  if (ShStrtabStrings != &DotStrtab && ShStrtabStrings != &DotDynstr)
    ShStrtabStrings->finalize();
}

template <class ELFT>
bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc,
                              yaml::ErrorHandler EH, uint64_t MaxSize) {
  ELFState<ELFT> State(Doc, EH);
  if (State.HasError)
    return false;

  // Build the section index, which adds sections to the section header string
  // table first, so that we can finalize the section header string table.
  State.buildSectionIndex();
  State.buildSymbolIndexes();

  // Finalize section header string table and the .strtab and .dynstr sections.
  // We do this early because we want to finalize the string table builders
  // before writing the content of the sections that might want to use them.
  State.finalizeStrings();

  if (State.HasError)
    return false;

  std::vector<Elf_Phdr> PHeaders;
  State.initProgramHeaders(PHeaders);

  // XXX: This offset is tightly coupled with the order that we write
  // things to `OS`.
  const size_t SectionContentBeginOffset =
      sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
  // It is quite easy to accidentally create output with yaml2obj that is larger
  // than intended, for example, due to an issue in the YAML description.
  // We limit the maximum allowed output size, but also provide a command line
  // option to change this limitation.
  ContiguousBlobAccumulator CBA(SectionContentBeginOffset, MaxSize);

  std::vector<Elf_Shdr> SHeaders;
  State.initSectionHeaders(SHeaders, CBA);

  // Now we can decide segment offsets.
  State.setProgramHeaderLayout(PHeaders, SHeaders);

  bool ReachedLimit = CBA.getOffset() > MaxSize;
  if (Error E = CBA.takeLimitError()) {
    // We report a custom error message instead below.
    consumeError(std::move(E));
    ReachedLimit = true;
  }

  if (ReachedLimit)
    State.reportError(
        "the desired output size is greater than permitted. Use the "
        "--max-size option to change the limit");

  if (State.HasError)
    return false;

  State.writeELFHeader(OS);
  writeArrayData(OS, makeArrayRef(PHeaders));

  const ELFYAML::SectionHeaderTable &SHT = Doc.getSectionHeaderTable();
  if (!SHT.NoHeaders.getValueOr(false))
    CBA.updateDataAt(*SHT.Offset, SHeaders.data(),
                     SHT.getNumHeaders(SHeaders.size()) * sizeof(Elf_Shdr));

  CBA.writeBlobToStream(OS);
  return true;
}

namespace llvm {
namespace yaml {

bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH,
              uint64_t MaxSize) {
  bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
  bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
  if (Is64Bit) {
    if (IsLE)
      return ELFState<object::ELF64LE>::writeELF(Out, Doc, EH, MaxSize);
    return ELFState<object::ELF64BE>::writeELF(Out, Doc, EH, MaxSize);
  }
  if (IsLE)
    return ELFState<object::ELF32LE>::writeELF(Out, Doc, EH, MaxSize);
  return ELFState<object::ELF32BE>::writeELF(Out, Doc, EH, MaxSize);
}

} // namespace yaml
} // namespace llvm
