//===- yaml2xcoff - Convert YAML to a xcoff 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 xcoff component of yaml2obj.
///
//===----------------------------------------------------------------------===//

#include "llvm/ADT/DenseMap.h"
#include "llvm/BinaryFormat/XCOFF.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/XCOFFObjectFile.h"
#include "llvm/ObjectYAML/ObjectYAML.h"
#include "llvm/ObjectYAML/yaml2obj.h"
#include "llvm/Support/EndianStream.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

namespace {

constexpr unsigned DefaultSectionAlign = 4;
constexpr int16_t MaxSectionIndex = INT16_MAX;
constexpr uint32_t MaxRawDataSize = UINT32_MAX;

class XCOFFWriter {
public:
  XCOFFWriter(XCOFFYAML::Object &Obj, raw_ostream &OS, yaml::ErrorHandler EH)
      : Obj(Obj), W(OS, support::big), ErrHandler(EH),
        StrTblBuilder(StringTableBuilder::XCOFF) {
    Is64Bit = Obj.Header.Magic == (llvm::yaml::Hex16)XCOFF::XCOFF64;
  }
  bool writeXCOFF();

private:
  bool nameShouldBeInStringTable(StringRef SymbolName);
  bool initFileHeader(uint64_t CurrentOffset);
  void initAuxFileHeader();
  bool initSectionHeader(uint64_t &CurrentOffset);
  bool initRelocations(uint64_t &CurrentOffset);
  bool initStringTable();
  bool assignAddressesAndIndices();

  void writeFileHeader();
  void writeAuxFileHeader();
  void writeSectionHeader();
  bool writeSectionData();
  bool writeRelocations();
  bool writeSymbols();
  void writeStringTable();

  void writeAuxSymbol(const XCOFFYAML::CsectAuxEnt &AuxSym);
  void writeAuxSymbol(const XCOFFYAML::FileAuxEnt &AuxSym);
  void writeAuxSymbol(const XCOFFYAML::FunctionAuxEnt &AuxSym);
  void writeAuxSymbol(const XCOFFYAML::ExcpetionAuxEnt &AuxSym);
  void writeAuxSymbol(const XCOFFYAML::BlockAuxEnt &AuxSym);
  void writeAuxSymbol(const XCOFFYAML::SectAuxEntForDWARF &AuxSym);
  void writeAuxSymbol(const XCOFFYAML::SectAuxEntForStat &AuxSym);
  void writeAuxSymbol(const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym);

  XCOFFYAML::Object &Obj;
  bool Is64Bit = false;
  support::endian::Writer W;
  yaml::ErrorHandler ErrHandler;
  StringTableBuilder StrTblBuilder;
  uint64_t StartOffset;
  // Map the section name to its corrresponding section index.
  DenseMap<StringRef, int16_t> SectionIndexMap = {
      {StringRef("N_DEBUG"), XCOFF::N_DEBUG},
      {StringRef("N_ABS"), XCOFF::N_ABS},
      {StringRef("N_UNDEF"), XCOFF::N_UNDEF}};
  XCOFFYAML::FileHeader InitFileHdr = Obj.Header;
  XCOFFYAML::AuxiliaryHeader InitAuxFileHdr;
  std::vector<XCOFFYAML::Section> InitSections = Obj.Sections;
};

static void writeName(StringRef StrName, support::endian::Writer W) {
  char Name[XCOFF::NameSize];
  memset(Name, 0, XCOFF::NameSize);
  char SrcName[] = "";
  memcpy(Name, StrName.size() ? StrName.data() : SrcName, StrName.size());
  ArrayRef<char> NameRef(Name, XCOFF::NameSize);
  W.write(NameRef);
}

bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) {
  // For XCOFF64: The symbol name is always in the string table.
  return (SymbolName.size() > XCOFF::NameSize) || Is64Bit;
}

bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) {
  for (XCOFFYAML::Section &InitSection : InitSections) {
    if (!InitSection.Relocations.empty()) {
      InitSection.NumberOfRelocations = InitSection.Relocations.size();
      InitSection.FileOffsetToRelocations = CurrentOffset;
      uint64_t RelSize = Is64Bit ? XCOFF::RelocationSerializationSize64
                                 : XCOFF::RelocationSerializationSize32;
      CurrentOffset += InitSection.NumberOfRelocations * RelSize;
      if (CurrentOffset > MaxRawDataSize) {
        ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
                   "exceeded when writing relocation data");
        return false;
      }
    }
  }
  return true;
}

bool XCOFFWriter::initSectionHeader(uint64_t &CurrentOffset) {
  uint64_t CurrentSecAddr = 0;
  for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
    if (CurrentOffset > MaxRawDataSize) {
      ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
                 "exceeded when writing section data");
      return false;
    }

    // Assign indices for sections.
    if (InitSections[I].SectionName.size() &&
        !SectionIndexMap[InitSections[I].SectionName]) {
      // The section index starts from 1.
      SectionIndexMap[InitSections[I].SectionName] = I + 1;
      if ((I + 1) > MaxSectionIndex) {
        ErrHandler("exceeded the maximum permitted section index of " +
                   Twine(MaxSectionIndex));
        return false;
      }
    }

    // Calculate the physical/virtual address. This field should contain 0 for
    // all sections except the text, data and bss sections.
    if (InitSections[I].Flags != XCOFF::STYP_TEXT &&
        InitSections[I].Flags != XCOFF::STYP_DATA &&
        InitSections[I].Flags != XCOFF::STYP_BSS)
      InitSections[I].Address = 0;
    else
      InitSections[I].Address = CurrentSecAddr;

    // Calculate the FileOffsetToData and data size for sections.
    if (InitSections[I].SectionData.binary_size()) {
      InitSections[I].FileOffsetToData = CurrentOffset;
      CurrentOffset += InitSections[I].SectionData.binary_size();
      // Ensure the offset is aligned to DefaultSectionAlign.
      CurrentOffset = alignTo(CurrentOffset, DefaultSectionAlign);
      InitSections[I].Size = CurrentOffset - InitSections[I].FileOffsetToData;
      CurrentSecAddr += InitSections[I].Size;
    }
  }
  return initRelocations(CurrentOffset);
}

bool XCOFFWriter::initStringTable() {
  if (Obj.StrTbl.RawContent) {
    size_t RawSize = Obj.StrTbl.RawContent->binary_size();
    if (Obj.StrTbl.Strings || Obj.StrTbl.Length) {
      ErrHandler(
          "can't specify Strings or Length when RawContent is specified");
      return false;
    }
    if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < RawSize) {
      ErrHandler("specified ContentSize (" + Twine(*Obj.StrTbl.ContentSize) +
                 ") is less than the RawContent data size (" + Twine(RawSize) +
                 ")");
      return false;
    }
    return true;
  }
  if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize <= 3) {
    ErrHandler("ContentSize shouldn't be less than 4 without RawContent");
    return false;
  }

  // Build the string table.
  StrTblBuilder.clear();

  if (Obj.StrTbl.Strings) {
    // All specified strings should be added to the string table.
    for (StringRef StringEnt : *Obj.StrTbl.Strings)
      StrTblBuilder.add(StringEnt);

    size_t StrTblIdx = 0;
    size_t NumOfStrings = Obj.StrTbl.Strings->size();
    for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
      if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
        if (StrTblIdx < NumOfStrings) {
          // Overwrite the symbol name with the specified string.
          YamlSym.SymbolName = (*Obj.StrTbl.Strings)[StrTblIdx];
          ++StrTblIdx;
        } else
          // Names that are not overwritten are still stored in the string
          // table.
          StrTblBuilder.add(YamlSym.SymbolName);
      }
    }
  } else {
    for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
      if (nameShouldBeInStringTable(YamlSym.SymbolName))
        StrTblBuilder.add(YamlSym.SymbolName);
    }
  }

  // Check if the file name in the File Auxiliary Entry should be added to the
  // string table.
  for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
    for (const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
         YamlSym.AuxEntries) {
      if (auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
        if (nameShouldBeInStringTable(AS->FileNameOrString.value_or("")))
          StrTblBuilder.add(AS->FileNameOrString.value_or(""));
    }
  }

  StrTblBuilder.finalize();

  size_t StrTblSize = StrTblBuilder.getSize();
  if (Obj.StrTbl.ContentSize && *Obj.StrTbl.ContentSize < StrTblSize) {
    ErrHandler("specified ContentSize (" + Twine(*Obj.StrTbl.ContentSize) +
               ") is less than the size of the data that would otherwise be "
               "written (" +
               Twine(StrTblSize) + ")");
    return false;
  }

  return true;
}

bool XCOFFWriter::initFileHeader(uint64_t CurrentOffset) {
  // The default format of the object file is XCOFF32.
  InitFileHdr.Magic = XCOFF::XCOFF32;
  InitFileHdr.NumberOfSections = Obj.Sections.size();
  InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size();

  for (XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
    uint32_t AuxCount = YamlSym.AuxEntries.size();
    if (YamlSym.NumberOfAuxEntries && *YamlSym.NumberOfAuxEntries < AuxCount) {
      ErrHandler("specified NumberOfAuxEntries " +
                 Twine(static_cast<uint32_t>(*YamlSym.NumberOfAuxEntries)) +
                 " is less than the actual number "
                 "of auxiliary entries " +
                 Twine(AuxCount));
      return false;
    }
    YamlSym.NumberOfAuxEntries = YamlSym.NumberOfAuxEntries.value_or(AuxCount);
    // Add the number of auxiliary symbols to the total number.
    InitFileHdr.NumberOfSymTableEntries += *YamlSym.NumberOfAuxEntries;
  }

  // Calculate SymbolTableOffset for the file header.
  if (InitFileHdr.NumberOfSymTableEntries) {
    InitFileHdr.SymbolTableOffset = CurrentOffset;
    CurrentOffset +=
        InitFileHdr.NumberOfSymTableEntries * XCOFF::SymbolTableEntrySize;
    if (CurrentOffset > MaxRawDataSize) {
      ErrHandler("maximum object size of" + Twine(MaxRawDataSize) +
                 "exceeded when writing symbols");
      return false;
    }
  }
  // TODO: Calculate FileOffsetToLineNumbers when line number supported.
  return true;
}

void XCOFFWriter::initAuxFileHeader() {
  InitAuxFileHdr = *Obj.AuxHeader;
  // In general, an object file might contain multiple sections of a given type,
  // but in a loadable module, there must be exactly one .text, .data, .bss, and
  // .loader section. A loadable object might also have one .tdata section and
  // one .tbss section.
  // Set these section-related values if not set explicitly. We assume that the
  // input YAML matches the format of the loadable object, but if multiple input
  // sections still have the same type, the first section with that type
  // prevails.
  for (uint16_t I = 0, E = InitSections.size(); I < E; ++I) {
    switch (InitSections[I].Flags) {
    case XCOFF::STYP_TEXT:
      if (!InitAuxFileHdr.TextSize)
        InitAuxFileHdr.TextSize = InitSections[I].Size;
      if (!InitAuxFileHdr.TextStartAddr)
        InitAuxFileHdr.TextStartAddr = InitSections[I].Address;
      if (!InitAuxFileHdr.SecNumOfText)
        InitAuxFileHdr.SecNumOfText = I + 1;
      break;
    case XCOFF::STYP_DATA:
      if (!InitAuxFileHdr.InitDataSize)
        InitAuxFileHdr.InitDataSize = InitSections[I].Size;
      if (!InitAuxFileHdr.DataStartAddr)
        InitAuxFileHdr.DataStartAddr = InitSections[I].Address;
      if (!InitAuxFileHdr.SecNumOfData)
        InitAuxFileHdr.SecNumOfData = I + 1;
      break;
    case XCOFF::STYP_BSS:
      if (!InitAuxFileHdr.BssDataSize)
        InitAuxFileHdr.BssDataSize = InitSections[I].Size;
      if (!InitAuxFileHdr.SecNumOfBSS)
        InitAuxFileHdr.SecNumOfBSS = I + 1;
      break;
    case XCOFF::STYP_TDATA:
      if (!InitAuxFileHdr.SecNumOfTData)
        InitAuxFileHdr.SecNumOfTData = I + 1;
      break;
    case XCOFF::STYP_TBSS:
      if (!InitAuxFileHdr.SecNumOfTBSS)
        InitAuxFileHdr.SecNumOfTBSS = I + 1;
      break;
    case XCOFF::STYP_LOADER:
      if (!InitAuxFileHdr.SecNumOfLoader)
        InitAuxFileHdr.SecNumOfLoader = I + 1;
      break;
    default:
      break;
    }
  }
}

bool XCOFFWriter::assignAddressesAndIndices() {
  uint64_t FileHdrSize =
      Is64Bit ? XCOFF::FileHeaderSize64 : XCOFF::FileHeaderSize32;
  uint64_t AuxFileHdrSize = 0;
  if (Obj.AuxHeader)
    AuxFileHdrSize = Obj.Header.AuxHeaderSize
                         ? Obj.Header.AuxHeaderSize
                         : (Is64Bit ? XCOFF::AuxFileHeaderSize64
                                    : XCOFF::AuxFileHeaderSize32);
  uint64_t SecHdrSize =
      Is64Bit ? XCOFF::SectionHeaderSize64 : XCOFF::SectionHeaderSize32;
  uint64_t CurrentOffset =
      FileHdrSize + AuxFileHdrSize + InitSections.size() * SecHdrSize;

  // Calculate section header info.
  if (!initSectionHeader(CurrentOffset))
    return false;
  InitFileHdr.AuxHeaderSize = AuxFileHdrSize;

  // Calculate file header info.
  if (!initFileHeader(CurrentOffset))
    return false;

  // Initialize the auxiliary file header.
  if (Obj.AuxHeader)
    initAuxFileHeader();

  // Initialize the string table.
  return initStringTable();
}

void XCOFFWriter::writeFileHeader() {
  W.write<uint16_t>(Obj.Header.Magic ? Obj.Header.Magic : InitFileHdr.Magic);
  W.write<uint16_t>(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections
                                                : InitFileHdr.NumberOfSections);
  W.write<int32_t>(Obj.Header.TimeStamp);
  if (Is64Bit) {
    W.write<uint64_t>(Obj.Header.SymbolTableOffset
                          ? Obj.Header.SymbolTableOffset
                          : InitFileHdr.SymbolTableOffset);
    W.write<uint16_t>(InitFileHdr.AuxHeaderSize);
    W.write<uint16_t>(Obj.Header.Flags);
    W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
                         ? Obj.Header.NumberOfSymTableEntries
                         : InitFileHdr.NumberOfSymTableEntries);
  } else {
    W.write<uint32_t>(Obj.Header.SymbolTableOffset
                          ? Obj.Header.SymbolTableOffset
                          : InitFileHdr.SymbolTableOffset);
    W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
                         ? Obj.Header.NumberOfSymTableEntries
                         : InitFileHdr.NumberOfSymTableEntries);
    W.write<uint16_t>(InitFileHdr.AuxHeaderSize);
    W.write<uint16_t>(Obj.Header.Flags);
  }
}

void XCOFFWriter::writeAuxFileHeader() {
  W.write<uint16_t>(InitAuxFileHdr.Magic.value_or(yaml::Hex16(1)));
  W.write<uint16_t>(InitAuxFileHdr.Version.value_or(yaml::Hex16(1)));
  if (Is64Bit) {
    W.OS.write_zeros(4); // Reserved for debugger.
    W.write<uint64_t>(InitAuxFileHdr.TextStartAddr.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.DataStartAddr.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.TOCAnchorAddr.value_or(yaml::Hex64(0)));
  } else {
    W.write<uint32_t>(InitAuxFileHdr.TextSize.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.InitDataSize.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.BssDataSize.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.EntryPointAddr.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.TextStartAddr.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.DataStartAddr.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.TOCAnchorAddr.value_or(yaml::Hex64(0)));
  }
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfEntryPoint.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfText.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfData.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfTOC.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfLoader.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfBSS.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.MaxAlignOfText.value_or(yaml::Hex16(0)));
  W.write<uint16_t>(InitAuxFileHdr.MaxAlignOfData.value_or(yaml::Hex16(0)));
  W.write<uint16_t>(InitAuxFileHdr.ModuleType.value_or(yaml::Hex16(0)));
  W.write<uint8_t>(InitAuxFileHdr.CpuFlag.value_or(yaml::Hex8(0)));
  W.write<uint8_t>(0); // Reserved for CPU type.
  if (Is64Bit) {
    W.write<uint8_t>(InitAuxFileHdr.TextPageSize.value_or(yaml::Hex8(0)));
    W.write<uint8_t>(InitAuxFileHdr.DataPageSize.value_or(yaml::Hex8(0)));
    W.write<uint8_t>(InitAuxFileHdr.StackPageSize.value_or(yaml::Hex8(0)));
    W.write<uint8_t>(
        InitAuxFileHdr.FlagAndTDataAlignment.value_or(yaml::Hex8(0x80)));
    W.write<uint64_t>(InitAuxFileHdr.TextSize.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.InitDataSize.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.BssDataSize.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.EntryPointAddr.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.MaxStackSize.value_or(yaml::Hex64(0)));
    W.write<uint64_t>(InitAuxFileHdr.MaxDataSize.value_or(yaml::Hex64(0)));
  } else {
    W.write<uint32_t>(InitAuxFileHdr.MaxStackSize.value_or(yaml::Hex64(0)));
    W.write<uint32_t>(InitAuxFileHdr.MaxDataSize.value_or(yaml::Hex64(0)));
    W.OS.write_zeros(4); // Reserved for debugger.
    W.write<uint8_t>(InitAuxFileHdr.TextPageSize.value_or(yaml::Hex8(0)));
    W.write<uint8_t>(InitAuxFileHdr.DataPageSize.value_or(yaml::Hex8(0)));
    W.write<uint8_t>(InitAuxFileHdr.StackPageSize.value_or(yaml::Hex8(0)));
    W.write<uint8_t>(
        InitAuxFileHdr.FlagAndTDataAlignment.value_or(yaml::Hex8(0)));
  }
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfTData.value_or(0));
  W.write<uint16_t>(InitAuxFileHdr.SecNumOfTBSS.value_or(0));
  if (Is64Bit) {
    W.write<uint16_t>(
        InitAuxFileHdr.Flag.value_or(yaml::Hex16(XCOFF::SHR_SYMTAB)));
    if (InitFileHdr.AuxHeaderSize > XCOFF::AuxFileHeaderSize64)
      W.OS.write_zeros(InitFileHdr.AuxHeaderSize - XCOFF::AuxFileHeaderSize64);
  } else if (InitFileHdr.AuxHeaderSize > XCOFF::AuxFileHeaderSize32) {
    W.OS.write_zeros(InitFileHdr.AuxHeaderSize - XCOFF::AuxFileHeaderSize32);
  }
}

void XCOFFWriter::writeSectionHeader() {
  for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
    XCOFFYAML::Section YamlSec = Obj.Sections[I];
    XCOFFYAML::Section DerivedSec = InitSections[I];
    writeName(YamlSec.SectionName, W);
    // Virtual address is the same as physical address.
    uint64_t SectionAddress =
        YamlSec.Address ? YamlSec.Address : DerivedSec.Address;
    if (Is64Bit) {
      W.write<uint64_t>(SectionAddress); // Physical address
      W.write<uint64_t>(SectionAddress); // Virtual address
      W.write<uint64_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
      W.write<uint64_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
                                                 : DerivedSec.FileOffsetToData);
      W.write<uint64_t>(YamlSec.FileOffsetToRelocations
                            ? YamlSec.FileOffsetToRelocations
                            : DerivedSec.FileOffsetToRelocations);
      W.write<uint64_t>(YamlSec.FileOffsetToLineNumbers);
      W.write<uint32_t>(YamlSec.NumberOfRelocations
                            ? YamlSec.NumberOfRelocations
                            : DerivedSec.NumberOfRelocations);
      W.write<uint32_t>(YamlSec.NumberOfLineNumbers);
      W.write<int32_t>(YamlSec.Flags);
      W.OS.write_zeros(4);
    } else {
      W.write<uint32_t>(SectionAddress); // Physical address
      W.write<uint32_t>(SectionAddress); // Virtual address
      W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
      W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
                                                 : DerivedSec.FileOffsetToData);
      W.write<uint32_t>(YamlSec.FileOffsetToRelocations
                            ? YamlSec.FileOffsetToRelocations
                            : DerivedSec.FileOffsetToRelocations);
      W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
      W.write<uint16_t>(YamlSec.NumberOfRelocations
                            ? YamlSec.NumberOfRelocations
                            : DerivedSec.NumberOfRelocations);
      W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
      W.write<int32_t>(YamlSec.Flags);
    }
  }
}

bool XCOFFWriter::writeSectionData() {
  for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
    XCOFFYAML::Section YamlSec = Obj.Sections[I];
    if (YamlSec.SectionData.binary_size()) {
      // Fill the padding size with zeros.
      int64_t PaddingSize =
          InitSections[I].FileOffsetToData - (W.OS.tell() - StartOffset);
      if (PaddingSize < 0) {
        ErrHandler("redundant data was written before section data");
        return false;
      }
      W.OS.write_zeros(PaddingSize);
      YamlSec.SectionData.writeAsBinary(W.OS);
    }
  }
  return true;
}

bool XCOFFWriter::writeRelocations() {
  for (uint16_t I = 0, E = Obj.Sections.size(); I < E; ++I) {
    XCOFFYAML::Section YamlSec = Obj.Sections[I];
    if (!YamlSec.Relocations.empty()) {
      int64_t PaddingSize =
          InitSections[I].FileOffsetToRelocations - (W.OS.tell() - StartOffset);
      if (PaddingSize < 0) {
        ErrHandler("redundant data was written before relocations");
        return false;
      }
      W.OS.write_zeros(PaddingSize);
      for (const XCOFFYAML::Relocation &YamlRel : YamlSec.Relocations) {
        if (Is64Bit)
          W.write<uint64_t>(YamlRel.VirtualAddress);
        else
          W.write<uint32_t>(YamlRel.VirtualAddress);
        W.write<uint32_t>(YamlRel.SymbolIndex);
        W.write<uint8_t>(YamlRel.Info);
        W.write<uint8_t>(YamlRel.Type);
      }
    }
  }
  return true;
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::CsectAuxEnt &AuxSym) {
  if (Is64Bit) {
    W.write<uint32_t>(AuxSym.SectionOrLengthLo.value_or(0));
    W.write<uint32_t>(AuxSym.ParameterHashIndex.value_or(0));
    W.write<uint16_t>(AuxSym.TypeChkSectNum.value_or(0));
    W.write<uint8_t>(AuxSym.SymbolAlignmentAndType.value_or(0));
    W.write<uint8_t>(AuxSym.StorageMappingClass.value_or(XCOFF::XMC_PR));
    W.write<uint32_t>(AuxSym.SectionOrLengthHi.value_or(0));
    W.write<uint8_t>(0);
    W.write<uint8_t>(XCOFF::AUX_CSECT);
  } else {
    W.write<uint32_t>(AuxSym.SectionOrLength.value_or(0));
    W.write<uint32_t>(AuxSym.ParameterHashIndex.value_or(0));
    W.write<uint16_t>(AuxSym.TypeChkSectNum.value_or(0));
    W.write<uint8_t>(AuxSym.SymbolAlignmentAndType.value_or(0));
    W.write<uint8_t>(AuxSym.StorageMappingClass.value_or(XCOFF::XMC_PR));
    W.write<uint32_t>(AuxSym.StabInfoIndex.value_or(0));
    W.write<uint16_t>(AuxSym.StabSectNum.value_or(0));
  }
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::ExcpetionAuxEnt &AuxSym) {
  assert(Is64Bit && "can't write the exception auxiliary symbol for XCOFF32");
  W.write<uint64_t>(AuxSym.OffsetToExceptionTbl.value_or(0));
  W.write<uint32_t>(AuxSym.SizeOfFunction.value_or(0));
  W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.value_or(0));
  W.write<uint8_t>(0);
  W.write<uint8_t>(XCOFF::AUX_EXCEPT);
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::FunctionAuxEnt &AuxSym) {
  if (Is64Bit) {
    W.write<uint64_t>(AuxSym.PtrToLineNum.value_or(0));
    W.write<uint32_t>(AuxSym.SizeOfFunction.value_or(0));
    W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.value_or(0));
    W.write<uint8_t>(0);
    W.write<uint8_t>(XCOFF::AUX_FCN);
  } else {
    W.write<uint32_t>(AuxSym.OffsetToExceptionTbl.value_or(0));
    W.write<uint32_t>(AuxSym.SizeOfFunction.value_or(0));
    W.write<uint32_t>(AuxSym.PtrToLineNum.value_or(0));
    W.write<uint32_t>(AuxSym.SymIdxOfNextBeyond.value_or(0));
    W.OS.write_zeros(2);
  }
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::FileAuxEnt &AuxSym) {
  StringRef FileName = AuxSym.FileNameOrString.value_or("");
  if (nameShouldBeInStringTable(FileName)) {
    W.write<int32_t>(0);
    W.write<uint32_t>(StrTblBuilder.getOffset(FileName));
  } else {
    writeName(FileName, W);
  }
  W.OS.write_zeros(XCOFF::FileNamePadSize);
  W.write<uint8_t>(AuxSym.FileStringType.value_or(XCOFF::XFT_FN));
  if (Is64Bit) {
    W.OS.write_zeros(2);
    W.write<uint8_t>(XCOFF::AUX_FILE);
  } else {
    W.OS.write_zeros(3);
  }
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::BlockAuxEnt &AuxSym) {
  if (Is64Bit) {
    W.write<uint32_t>(AuxSym.LineNum.value_or(0));
    W.OS.write_zeros(13);
    W.write<uint8_t>(XCOFF::AUX_SYM);
  } else {
    W.OS.write_zeros(2);
    W.write<uint16_t>(AuxSym.LineNumHi.value_or(0));
    W.write<uint16_t>(AuxSym.LineNumLo.value_or(0));
    W.OS.write_zeros(12);
  }
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::SectAuxEntForDWARF &AuxSym) {
  if (Is64Bit) {
    W.write<uint64_t>(AuxSym.LengthOfSectionPortion.value_or(0));
    W.write<uint64_t>(AuxSym.NumberOfRelocEnt.value_or(0));
    W.write<uint8_t>(0);
    W.write<uint8_t>(XCOFF::AUX_SECT);
  } else {
    W.write<uint32_t>(AuxSym.LengthOfSectionPortion.value_or(0));
    W.OS.write_zeros(4);
    W.write<uint32_t>(AuxSym.NumberOfRelocEnt.value_or(0));
    W.OS.write_zeros(6);
  }
}

void XCOFFWriter::writeAuxSymbol(const XCOFFYAML::SectAuxEntForStat &AuxSym) {
  assert(!Is64Bit && "can't write the stat auxiliary symbol for XCOFF64");
  W.write<uint32_t>(AuxSym.SectionLength.value_or(0));
  W.write<uint16_t>(AuxSym.NumberOfRelocEnt.value_or(0));
  W.write<uint16_t>(AuxSym.NumberOfLineNum.value_or(0));
  W.OS.write_zeros(10);
}

void XCOFFWriter::writeAuxSymbol(
    const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym) {
  if (auto AS = dyn_cast<XCOFFYAML::CsectAuxEnt>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else if (auto AS = dyn_cast<XCOFFYAML::FunctionAuxEnt>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else if (auto AS = dyn_cast<XCOFFYAML::ExcpetionAuxEnt>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else if (auto AS = dyn_cast<XCOFFYAML::FileAuxEnt>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else if (auto AS = dyn_cast<XCOFFYAML::BlockAuxEnt>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else if (auto AS = dyn_cast<XCOFFYAML::SectAuxEntForDWARF>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else if (auto AS = dyn_cast<XCOFFYAML::SectAuxEntForStat>(AuxSym.get()))
    writeAuxSymbol(*AS);
  else
    llvm_unreachable("unknown auxiliary symbol type");
}

bool XCOFFWriter::writeSymbols() {
  int64_t PaddingSize =
      (uint64_t)InitFileHdr.SymbolTableOffset - (W.OS.tell() - StartOffset);
  if (PaddingSize < 0) {
    ErrHandler("redundant data was written before symbols");
    return false;
  }
  W.OS.write_zeros(PaddingSize);
  for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) {
    if (Is64Bit) {
      W.write<uint64_t>(YamlSym.Value);
      W.write<uint32_t>(StrTblBuilder.getOffset(YamlSym.SymbolName));
    } else {
      if (nameShouldBeInStringTable(YamlSym.SymbolName)) {
        // For XCOFF32: A value of 0 indicates that the symbol name is in the
        // string table.
        W.write<int32_t>(0);
        W.write<uint32_t>(StrTblBuilder.getOffset(YamlSym.SymbolName));
      } else {
        writeName(YamlSym.SymbolName, W);
      }
      W.write<uint32_t>(YamlSym.Value);
    }
    if (YamlSym.SectionName) {
      if (!SectionIndexMap.count(*YamlSym.SectionName)) {
        ErrHandler("the SectionName " + *YamlSym.SectionName +
                   " specified in the symbol does not exist");
        return false;
      }
      if (YamlSym.SectionIndex &&
          SectionIndexMap[*YamlSym.SectionName] != *YamlSym.SectionIndex) {
        ErrHandler("the SectionName " + *YamlSym.SectionName +
                   " and the SectionIndex (" + Twine(*YamlSym.SectionIndex) +
                   ") refer to different sections");
        return false;
      }
      W.write<int16_t>(SectionIndexMap[*YamlSym.SectionName]);
    } else {
      W.write<int16_t>(YamlSym.SectionIndex ? *YamlSym.SectionIndex : 0);
    }
    W.write<uint16_t>(YamlSym.Type);
    W.write<uint8_t>(YamlSym.StorageClass);

    uint8_t NumOfAuxSym = YamlSym.NumberOfAuxEntries.value_or(0);
    W.write<uint8_t>(NumOfAuxSym);

    if (!NumOfAuxSym && !YamlSym.AuxEntries.size())
      continue;

    // Now write auxiliary entries.
    if (!YamlSym.AuxEntries.size()) {
      W.OS.write_zeros(XCOFF::SymbolTableEntrySize * NumOfAuxSym);
    } else {
      for (const std::unique_ptr<XCOFFYAML::AuxSymbolEnt> &AuxSym :
           YamlSym.AuxEntries) {
        writeAuxSymbol(AuxSym);
      }
      // Pad with zeros.
      if (NumOfAuxSym > YamlSym.AuxEntries.size())
        W.OS.write_zeros(XCOFF::SymbolTableEntrySize *
                         (NumOfAuxSym - YamlSym.AuxEntries.size()));
    }
  }
  return true;
}

void XCOFFWriter::writeStringTable() {
  if (Obj.StrTbl.RawContent) {
    Obj.StrTbl.RawContent->writeAsBinary(W.OS);
    if (Obj.StrTbl.ContentSize) {
      assert(*Obj.StrTbl.ContentSize >= Obj.StrTbl.RawContent->binary_size() &&
             "Specified ContentSize is less than the RawContent size.");
      W.OS.write_zeros(*Obj.StrTbl.ContentSize -
                       Obj.StrTbl.RawContent->binary_size());
    }
    return;
  }

  size_t StrTblBuilderSize = StrTblBuilder.getSize();
  // If neither Length nor ContentSize is specified, write the StrTblBuilder
  // directly, which contains the auto-generated Length value.
  if (!Obj.StrTbl.Length && !Obj.StrTbl.ContentSize) {
    if (StrTblBuilderSize <= 4)
      return;
    StrTblBuilder.write(W.OS);
    return;
  }

  // Serialize the string table's content to a temporary buffer.
  std::unique_ptr<WritableMemoryBuffer> Buf =
      WritableMemoryBuffer::getNewMemBuffer(StrTblBuilderSize);
  uint8_t *Ptr = reinterpret_cast<uint8_t *>(Buf->getBufferStart());
  StrTblBuilder.write(Ptr);
  // Replace the first 4 bytes, which contain the auto-generated Length value,
  // with the specified value.
  memset(Ptr, 0, 4);
  support::endian::write32be(Ptr, Obj.StrTbl.Length ? *Obj.StrTbl.Length
                                                    : *Obj.StrTbl.ContentSize);
  // Copy the buffer content to the actual output stream.
  W.OS.write(Buf->getBufferStart(), Buf->getBufferSize());
  // Add zeros as padding after strings.
  if (Obj.StrTbl.ContentSize) {
    assert(*Obj.StrTbl.ContentSize >= StrTblBuilderSize &&
           "Specified ContentSize is less than the StringTableBuilder size.");
    W.OS.write_zeros(*Obj.StrTbl.ContentSize - StrTblBuilderSize);
  }
}

bool XCOFFWriter::writeXCOFF() {
  if (!assignAddressesAndIndices())
    return false;
  StartOffset = W.OS.tell();
  writeFileHeader();
  if (Obj.AuxHeader)
    writeAuxFileHeader();
  if (!Obj.Sections.empty()) {
    writeSectionHeader();
    if (!writeSectionData())
      return false;
    if (!writeRelocations())
      return false;
  }
  if (!Obj.Symbols.empty() && !writeSymbols())
    return false;
  writeStringTable();
  return true;
}

} // end anonymous namespace

namespace llvm {
namespace yaml {

bool yaml2xcoff(XCOFFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
  XCOFFWriter Writer(Doc, Out, EH);
  return Writer.writeXCOFF();
}

} // namespace yaml
} // namespace llvm
