//===-- WindowsResource.cpp -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the .res file class.
//
//===----------------------------------------------------------------------===//

#include "llvm/Object/WindowsResource.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ScopedPrinter.h"
#include <ctime>
#include <queue>
#include <system_error>

using namespace llvm;
using namespace object;

namespace llvm {
namespace object {

#define RETURN_IF_ERROR(X)                                                     \
  if (auto EC = X)                                                             \
    return EC;

#define UNWRAP_REF_OR_RETURN(Name, Expr)                                       \
  auto Name##OrErr = Expr;                                                     \
  if (!Name##OrErr)                                                            \
    return Name##OrErr.takeError();                                            \
  const auto &Name = *Name##OrErr;

#define UNWRAP_OR_RETURN(Name, Expr)                                           \
  auto Name##OrErr = Expr;                                                     \
  if (!Name##OrErr)                                                            \
    return Name##OrErr.takeError();                                            \
  auto Name = *Name##OrErr;

const uint32_t MIN_HEADER_SIZE = 7 * sizeof(uint32_t) + 2 * sizeof(uint16_t);

// COFF files seem to be inconsistent with alignment between sections, just use
// 8-byte because it makes everyone happy.
const uint32_t SECTION_ALIGNMENT = sizeof(uint64_t);

WindowsResource::WindowsResource(MemoryBufferRef Source)
    : Binary(Binary::ID_WinRes, Source) {
  size_t LeadingSize = WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE;
  BBS = BinaryByteStream(Data.getBuffer().drop_front(LeadingSize),
                         support::little);
}

// static
Expected<std::unique_ptr<WindowsResource>>
WindowsResource::createWindowsResource(MemoryBufferRef Source) {
  if (Source.getBufferSize() < WIN_RES_MAGIC_SIZE + WIN_RES_NULL_ENTRY_SIZE)
    return make_error<GenericBinaryError>(
        Source.getBufferIdentifier() + ": too small to be a resource file",
        object_error::invalid_file_type);
  std::unique_ptr<WindowsResource> Ret(new WindowsResource(Source));
  return std::move(Ret);
}

Expected<ResourceEntryRef> WindowsResource::getHeadEntry() {
  if (BBS.getLength() < sizeof(WinResHeaderPrefix) + sizeof(WinResHeaderSuffix))
    return make_error<EmptyResError>(getFileName() + " contains no entries",
                                     object_error::unexpected_eof);
  return ResourceEntryRef::create(BinaryStreamRef(BBS), this);
}

ResourceEntryRef::ResourceEntryRef(BinaryStreamRef Ref,
                                   const WindowsResource *Owner)
    : Reader(Ref), Owner(Owner) {}

Expected<ResourceEntryRef>
ResourceEntryRef::create(BinaryStreamRef BSR, const WindowsResource *Owner) {
  auto Ref = ResourceEntryRef(BSR, Owner);
  if (auto E = Ref.loadNext())
    return std::move(E);
  return Ref;
}

Error ResourceEntryRef::moveNext(bool &End) {
  // Reached end of all the entries.
  if (Reader.bytesRemaining() == 0) {
    End = true;
    return Error::success();
  }
  RETURN_IF_ERROR(loadNext());

  return Error::success();
}

static Error readStringOrId(BinaryStreamReader &Reader, uint16_t &ID,
                            ArrayRef<UTF16> &Str, bool &IsString) {
  uint16_t IDFlag;
  RETURN_IF_ERROR(Reader.readInteger(IDFlag));
  IsString = IDFlag != 0xffff;

  if (IsString) {
    Reader.setOffset(
        Reader.getOffset() -
        sizeof(uint16_t)); // Re-read the bytes which we used to check the flag.
    RETURN_IF_ERROR(Reader.readWideString(Str));
  } else
    RETURN_IF_ERROR(Reader.readInteger(ID));

  return Error::success();
}

Error ResourceEntryRef::loadNext() {
  const WinResHeaderPrefix *Prefix;
  RETURN_IF_ERROR(Reader.readObject(Prefix));

  if (Prefix->HeaderSize < MIN_HEADER_SIZE)
    return make_error<GenericBinaryError>(Owner->getFileName() +
                                              ": header size too small",
                                          object_error::parse_failed);

  RETURN_IF_ERROR(readStringOrId(Reader, TypeID, Type, IsStringType));

  RETURN_IF_ERROR(readStringOrId(Reader, NameID, Name, IsStringName));

  RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_HEADER_ALIGNMENT));

  RETURN_IF_ERROR(Reader.readObject(Suffix));

  RETURN_IF_ERROR(Reader.readArray(Data, Prefix->DataSize));

  RETURN_IF_ERROR(Reader.padToAlignment(WIN_RES_DATA_ALIGNMENT));

  return Error::success();
}

WindowsResourceParser::WindowsResourceParser(bool MinGW)
    : Root(false), MinGW(MinGW) {}

void printResourceTypeName(uint16_t TypeID, raw_ostream &OS) {
  switch (TypeID) {
  case  1: OS << "CURSOR (ID 1)"; break;
  case  2: OS << "BITMAP (ID 2)"; break;
  case  3: OS << "ICON (ID 3)"; break;
  case  4: OS << "MENU (ID 4)"; break;
  case  5: OS << "DIALOG (ID 5)"; break;
  case  6: OS << "STRINGTABLE (ID 6)"; break;
  case  7: OS << "FONTDIR (ID 7)"; break;
  case  8: OS << "FONT (ID 8)"; break;
  case  9: OS << "ACCELERATOR (ID 9)"; break;
  case 10: OS << "RCDATA (ID 10)"; break;
  case 11: OS << "MESSAGETABLE (ID 11)"; break;
  case 12: OS << "GROUP_CURSOR (ID 12)"; break;
  case 14: OS << "GROUP_ICON (ID 14)"; break;
  case 16: OS << "VERSIONINFO (ID 16)"; break;
  case 17: OS << "DLGINCLUDE (ID 17)"; break;
  case 19: OS << "PLUGPLAY (ID 19)"; break;
  case 20: OS << "VXD (ID 20)"; break;
  case 21: OS << "ANICURSOR (ID 21)"; break;
  case 22: OS << "ANIICON (ID 22)"; break;
  case 23: OS << "HTML (ID 23)"; break;
  case 24: OS << "MANIFEST (ID 24)"; break;
  default: OS << "ID " << TypeID; break;
  }
}

static bool convertUTF16LEToUTF8String(ArrayRef<UTF16> Src, std::string &Out) {
  if (!sys::IsBigEndianHost)
    return convertUTF16ToUTF8String(Src, Out);

  std::vector<UTF16> EndianCorrectedSrc;
  EndianCorrectedSrc.resize(Src.size() + 1);
  llvm::copy(Src, EndianCorrectedSrc.begin() + 1);
  EndianCorrectedSrc[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;
  return convertUTF16ToUTF8String(makeArrayRef(EndianCorrectedSrc), Out);
}

static std::string makeDuplicateResourceError(
    const ResourceEntryRef &Entry, StringRef File1, StringRef File2) {
  std::string Ret;
  raw_string_ostream OS(Ret);

  OS << "duplicate resource:";

  OS << " type ";
  if (Entry.checkTypeString()) {
    std::string UTF8;
    if (!convertUTF16LEToUTF8String(Entry.getTypeString(), UTF8))
      UTF8 = "(failed conversion from UTF16)";
    OS << '\"' << UTF8 << '\"';
  } else
    printResourceTypeName(Entry.getTypeID(), OS);

  OS << "/name ";
  if (Entry.checkNameString()) {
    std::string UTF8;
    if (!convertUTF16LEToUTF8String(Entry.getNameString(), UTF8))
      UTF8 = "(failed conversion from UTF16)";
    OS << '\"' << UTF8 << '\"';
  } else {
    OS << "ID " << Entry.getNameID();
  }

  OS << "/language " << Entry.getLanguage() << ", in " << File1 << " and in "
     << File2;

  return OS.str();
}

static void printStringOrID(const WindowsResourceParser::StringOrID &S,
                            raw_string_ostream &OS, bool IsType, bool IsID) {
  if (S.IsString) {
    std::string UTF8;
    if (!convertUTF16LEToUTF8String(S.String, UTF8))
      UTF8 = "(failed conversion from UTF16)";
    OS << '\"' << UTF8 << '\"';
  } else if (IsType)
    printResourceTypeName(S.ID, OS);
  else if (IsID)
    OS << "ID " << S.ID;
  else
    OS << S.ID;
}

static std::string makeDuplicateResourceError(
    const std::vector<WindowsResourceParser::StringOrID> &Context,
    StringRef File1, StringRef File2) {
  std::string Ret;
  raw_string_ostream OS(Ret);

  OS << "duplicate resource:";

  if (Context.size() >= 1) {
    OS << " type ";
    printStringOrID(Context[0], OS, /* IsType */ true, /* IsID */ true);
  }

  if (Context.size() >= 2) {
    OS << "/name ";
    printStringOrID(Context[1], OS, /* IsType */ false, /* IsID */ true);
  }

  if (Context.size() >= 3) {
    OS << "/language ";
    printStringOrID(Context[2], OS, /* IsType */ false, /* IsID */ false);
  }
  OS << ", in " << File1 << " and in " << File2;

  return OS.str();
}

// MinGW specific. Remove default manifests (with language zero) if there are
// other manifests present, and report an error if there are more than one
// manifest with a non-zero language code.
// GCC has the concept of a default manifest resource object, which gets
// linked in implicitly if present. This default manifest has got language
// id zero, and should be dropped silently if there's another manifest present.
// If the user resources surprisignly had a manifest with language id zero,
// we should also ignore the duplicate default manifest.
void WindowsResourceParser::cleanUpManifests(
    std::vector<std::string> &Duplicates) {
  auto TypeIt = Root.IDChildren.find(/* RT_MANIFEST */ 24);
  if (TypeIt == Root.IDChildren.end())
    return;

  TreeNode *TypeNode = TypeIt->second.get();
  auto NameIt =
      TypeNode->IDChildren.find(/* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 1);
  if (NameIt == TypeNode->IDChildren.end())
    return;

  TreeNode *NameNode = NameIt->second.get();
  if (NameNode->IDChildren.size() <= 1)
    return; // None or one manifest present, all good.

  // If we have more than one manifest, drop the language zero one if present,
  // and check again.
  auto LangZeroIt = NameNode->IDChildren.find(0);
  if (LangZeroIt != NameNode->IDChildren.end() &&
      LangZeroIt->second->IsDataNode) {
    uint32_t RemovedIndex = LangZeroIt->second->DataIndex;
    NameNode->IDChildren.erase(LangZeroIt);
    Data.erase(Data.begin() + RemovedIndex);
    Root.shiftDataIndexDown(RemovedIndex);

    // If we're now down to one manifest, all is good.
    if (NameNode->IDChildren.size() <= 1)
      return;
  }

  // More than one non-language-zero manifest
  auto FirstIt = NameNode->IDChildren.begin();
  uint32_t FirstLang = FirstIt->first;
  TreeNode *FirstNode = FirstIt->second.get();
  auto LastIt = NameNode->IDChildren.rbegin();
  uint32_t LastLang = LastIt->first;
  TreeNode *LastNode = LastIt->second.get();
  Duplicates.push_back(
      ("duplicate non-default manifests with languages " + Twine(FirstLang) +
       " in " + InputFilenames[FirstNode->Origin] + " and " + Twine(LastLang) +
       " in " + InputFilenames[LastNode->Origin])
          .str());
}

// Ignore duplicates of manifests with language zero (the default manifest),
// in case the user has provided a manifest with that language id. See
// the function comment above for context. Only returns true if MinGW is set
// to true.
bool WindowsResourceParser::shouldIgnoreDuplicate(
    const ResourceEntryRef &Entry) const {
  return MinGW && !Entry.checkTypeString() &&
         Entry.getTypeID() == /* RT_MANIFEST */ 24 &&
         !Entry.checkNameString() &&
         Entry.getNameID() == /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 1 &&
         Entry.getLanguage() == 0;
}

bool WindowsResourceParser::shouldIgnoreDuplicate(
    const std::vector<StringOrID> &Context) const {
  return MinGW && Context.size() == 3 && !Context[0].IsString &&
         Context[0].ID == /* RT_MANIFEST */ 24 && !Context[1].IsString &&
         Context[1].ID == /* CREATEPROCESS_MANIFEST_RESOURCE_ID */ 1 &&
         !Context[2].IsString && Context[2].ID == 0;
}

Error WindowsResourceParser::parse(WindowsResource *WR,
                                   std::vector<std::string> &Duplicates) {
  auto EntryOrErr = WR->getHeadEntry();
  if (!EntryOrErr) {
    auto E = EntryOrErr.takeError();
    if (E.isA<EmptyResError>()) {
      // Check if the .res file contains no entries.  In this case we don't have
      // to throw an error but can rather just return without parsing anything.
      // This applies for files which have a valid PE header magic and the
      // mandatory empty null resource entry.  Files which do not fit this
      // criteria would have already been filtered out by
      // WindowsResource::createWindowsResource().
      consumeError(std::move(E));
      return Error::success();
    }
    return E;
  }

  ResourceEntryRef Entry = EntryOrErr.get();
  uint32_t Origin = InputFilenames.size();
  InputFilenames.push_back(WR->getFileName());
  bool End = false;
  while (!End) {

    TreeNode *Node;
    bool IsNewNode = Root.addEntry(Entry, Origin, Data, StringTable, Node);
    if (!IsNewNode) {
      if (!shouldIgnoreDuplicate(Entry))
        Duplicates.push_back(makeDuplicateResourceError(
            Entry, InputFilenames[Node->Origin], WR->getFileName()));
    }

    RETURN_IF_ERROR(Entry.moveNext(End));
  }

  return Error::success();
}

Error WindowsResourceParser::parse(ResourceSectionRef &RSR, StringRef Filename,
                                   std::vector<std::string> &Duplicates) {
  UNWRAP_REF_OR_RETURN(BaseTable, RSR.getBaseTable());
  uint32_t Origin = InputFilenames.size();
  InputFilenames.push_back(Filename);
  std::vector<StringOrID> Context;
  return addChildren(Root, RSR, BaseTable, Origin, Context, Duplicates);
}

void WindowsResourceParser::printTree(raw_ostream &OS) const {
  ScopedPrinter Writer(OS);
  Root.print(Writer, "Resource Tree");
}

bool WindowsResourceParser::TreeNode::addEntry(
    const ResourceEntryRef &Entry, uint32_t Origin,
    std::vector<std::vector<uint8_t>> &Data,
    std::vector<std::vector<UTF16>> &StringTable, TreeNode *&Result) {
  TreeNode &TypeNode = addTypeNode(Entry, StringTable);
  TreeNode &NameNode = TypeNode.addNameNode(Entry, StringTable);
  return NameNode.addLanguageNode(Entry, Origin, Data, Result);
}

Error WindowsResourceParser::addChildren(TreeNode &Node,
                                         ResourceSectionRef &RSR,
                                         const coff_resource_dir_table &Table,
                                         uint32_t Origin,
                                         std::vector<StringOrID> &Context,
                                         std::vector<std::string> &Duplicates) {

  for (int i = 0; i < Table.NumberOfNameEntries + Table.NumberOfIDEntries;
       i++) {
    UNWRAP_REF_OR_RETURN(Entry, RSR.getTableEntry(Table, i));
    TreeNode *Child;

    if (Entry.Offset.isSubDir()) {

      // Create a new subdirectory and recurse
      if (i < Table.NumberOfNameEntries) {
        UNWRAP_OR_RETURN(NameString, RSR.getEntryNameString(Entry));
        Child = &Node.addNameChild(NameString, StringTable);
        Context.push_back(StringOrID(NameString));
      } else {
        Child = &Node.addIDChild(Entry.Identifier.ID);
        Context.push_back(StringOrID(Entry.Identifier.ID));
      }

      UNWRAP_REF_OR_RETURN(NextTable, RSR.getEntrySubDir(Entry));
      Error E =
          addChildren(*Child, RSR, NextTable, Origin, Context, Duplicates);
      if (E)
        return E;
      Context.pop_back();

    } else {

      // Data leaves are supposed to have a numeric ID as identifier (language).
      if (Table.NumberOfNameEntries > 0)
        return createStringError(object_error::parse_failed,
                                 "unexpected string key for data object");

      // Try adding a data leaf
      UNWRAP_REF_OR_RETURN(DataEntry, RSR.getEntryData(Entry));
      TreeNode *Child;
      Context.push_back(StringOrID(Entry.Identifier.ID));
      bool Added = Node.addDataChild(Entry.Identifier.ID, Table.MajorVersion,
                                     Table.MinorVersion, Table.Characteristics,
                                     Origin, Data.size(), Child);
      if (Added) {
        UNWRAP_OR_RETURN(Contents, RSR.getContents(DataEntry));
        Data.push_back(ArrayRef<uint8_t>(
            reinterpret_cast<const uint8_t *>(Contents.data()),
            Contents.size()));
      } else {
        if (!shouldIgnoreDuplicate(Context))
          Duplicates.push_back(makeDuplicateResourceError(
              Context, InputFilenames[Child->Origin], InputFilenames.back()));
      }
      Context.pop_back();

    }
  }
  return Error::success();
}

WindowsResourceParser::TreeNode::TreeNode(uint32_t StringIndex)
    : StringIndex(StringIndex) {}

WindowsResourceParser::TreeNode::TreeNode(uint16_t MajorVersion,
                                          uint16_t MinorVersion,
                                          uint32_t Characteristics,
                                          uint32_t Origin, uint32_t DataIndex)
    : IsDataNode(true), DataIndex(DataIndex), MajorVersion(MajorVersion),
      MinorVersion(MinorVersion), Characteristics(Characteristics),
      Origin(Origin) {}

std::unique_ptr<WindowsResourceParser::TreeNode>
WindowsResourceParser::TreeNode::createStringNode(uint32_t Index) {
  return std::unique_ptr<TreeNode>(new TreeNode(Index));
}

std::unique_ptr<WindowsResourceParser::TreeNode>
WindowsResourceParser::TreeNode::createIDNode() {
  return std::unique_ptr<TreeNode>(new TreeNode(0));
}

std::unique_ptr<WindowsResourceParser::TreeNode>
WindowsResourceParser::TreeNode::createDataNode(uint16_t MajorVersion,
                                                uint16_t MinorVersion,
                                                uint32_t Characteristics,
                                                uint32_t Origin,
                                                uint32_t DataIndex) {
  return std::unique_ptr<TreeNode>(new TreeNode(
      MajorVersion, MinorVersion, Characteristics, Origin, DataIndex));
}

WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addTypeNode(
    const ResourceEntryRef &Entry,
    std::vector<std::vector<UTF16>> &StringTable) {
  if (Entry.checkTypeString())
    return addNameChild(Entry.getTypeString(), StringTable);
  else
    return addIDChild(Entry.getTypeID());
}

WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addNameNode(
    const ResourceEntryRef &Entry,
    std::vector<std::vector<UTF16>> &StringTable) {
  if (Entry.checkNameString())
    return addNameChild(Entry.getNameString(), StringTable);
  else
    return addIDChild(Entry.getNameID());
}

bool WindowsResourceParser::TreeNode::addLanguageNode(
    const ResourceEntryRef &Entry, uint32_t Origin,
    std::vector<std::vector<uint8_t>> &Data, TreeNode *&Result) {
  bool Added = addDataChild(Entry.getLanguage(), Entry.getMajorVersion(),
                            Entry.getMinorVersion(), Entry.getCharacteristics(),
                            Origin, Data.size(), Result);
  if (Added)
    Data.push_back(Entry.getData());
  return Added;
}

bool WindowsResourceParser::TreeNode::addDataChild(
    uint32_t ID, uint16_t MajorVersion, uint16_t MinorVersion,
    uint32_t Characteristics, uint32_t Origin, uint32_t DataIndex,
    TreeNode *&Result) {
  auto NewChild = createDataNode(MajorVersion, MinorVersion, Characteristics,
                                 Origin, DataIndex);
  auto ElementInserted = IDChildren.emplace(ID, std::move(NewChild));
  Result = ElementInserted.first->second.get();
  return ElementInserted.second;
}

WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addIDChild(
    uint32_t ID) {
  auto Child = IDChildren.find(ID);
  if (Child == IDChildren.end()) {
    auto NewChild = createIDNode();
    WindowsResourceParser::TreeNode &Node = *NewChild;
    IDChildren.emplace(ID, std::move(NewChild));
    return Node;
  } else
    return *(Child->second);
}

WindowsResourceParser::TreeNode &WindowsResourceParser::TreeNode::addNameChild(
    ArrayRef<UTF16> NameRef, std::vector<std::vector<UTF16>> &StringTable) {
  std::string NameString;
  convertUTF16LEToUTF8String(NameRef, NameString);

  auto Child = StringChildren.find(NameString);
  if (Child == StringChildren.end()) {
    auto NewChild = createStringNode(StringTable.size());
    StringTable.push_back(NameRef);
    WindowsResourceParser::TreeNode &Node = *NewChild;
    StringChildren.emplace(NameString, std::move(NewChild));
    return Node;
  } else
    return *(Child->second);
}

void WindowsResourceParser::TreeNode::print(ScopedPrinter &Writer,
                                            StringRef Name) const {
  ListScope NodeScope(Writer, Name);
  for (auto const &Child : StringChildren) {
    Child.second->print(Writer, Child.first);
  }
  for (auto const &Child : IDChildren) {
    Child.second->print(Writer, to_string(Child.first));
  }
}

// This function returns the size of the entire resource tree, including
// directory tables, directory entries, and data entries.  It does not include
// the directory strings or the relocations of the .rsrc section.
uint32_t WindowsResourceParser::TreeNode::getTreeSize() const {
  uint32_t Size = (IDChildren.size() + StringChildren.size()) *
                  sizeof(coff_resource_dir_entry);

  // Reached a node pointing to a data entry.
  if (IsDataNode) {
    Size += sizeof(coff_resource_data_entry);
    return Size;
  }

  // If the node does not point to data, it must have a directory table pointing
  // to other nodes.
  Size += sizeof(coff_resource_dir_table);

  for (auto const &Child : StringChildren) {
    Size += Child.second->getTreeSize();
  }
  for (auto const &Child : IDChildren) {
    Size += Child.second->getTreeSize();
  }
  return Size;
}

// Shift DataIndex of all data children with an Index greater or equal to the
// given one, to fill a gap from removing an entry from the Data vector.
void WindowsResourceParser::TreeNode::shiftDataIndexDown(uint32_t Index) {
  if (IsDataNode && DataIndex >= Index) {
    DataIndex--;
  } else {
    for (auto &Child : IDChildren)
      Child.second->shiftDataIndexDown(Index);
    for (auto &Child : StringChildren)
      Child.second->shiftDataIndexDown(Index);
  }
}

class WindowsResourceCOFFWriter {
public:
  WindowsResourceCOFFWriter(COFF::MachineTypes MachineType,
                            const WindowsResourceParser &Parser, Error &E);
  std::unique_ptr<MemoryBuffer> write(uint32_t TimeDateStamp);

private:
  void performFileLayout();
  void performSectionOneLayout();
  void performSectionTwoLayout();
  void writeCOFFHeader(uint32_t TimeDateStamp);
  void writeFirstSectionHeader();
  void writeSecondSectionHeader();
  void writeFirstSection();
  void writeSecondSection();
  void writeSymbolTable();
  void writeStringTable();
  void writeDirectoryTree();
  void writeDirectoryStringTable();
  void writeFirstSectionRelocations();
  std::unique_ptr<WritableMemoryBuffer> OutputBuffer;
  char *BufferStart;
  uint64_t CurrentOffset = 0;
  COFF::MachineTypes MachineType;
  const WindowsResourceParser::TreeNode &Resources;
  const ArrayRef<std::vector<uint8_t>> Data;
  uint64_t FileSize;
  uint32_t SymbolTableOffset;
  uint32_t SectionOneSize;
  uint32_t SectionOneOffset;
  uint32_t SectionOneRelocations;
  uint32_t SectionTwoSize;
  uint32_t SectionTwoOffset;
  const ArrayRef<std::vector<UTF16>> StringTable;
  std::vector<uint32_t> StringTableOffsets;
  std::vector<uint32_t> DataOffsets;
  std::vector<uint32_t> RelocationAddresses;
};

WindowsResourceCOFFWriter::WindowsResourceCOFFWriter(
    COFF::MachineTypes MachineType, const WindowsResourceParser &Parser,
    Error &E)
    : MachineType(MachineType), Resources(Parser.getTree()),
      Data(Parser.getData()), StringTable(Parser.getStringTable()) {
  performFileLayout();

  OutputBuffer = WritableMemoryBuffer::getNewMemBuffer(
      FileSize, "internal .obj file created from .res files");
}

void WindowsResourceCOFFWriter::performFileLayout() {
  // Add size of COFF header.
  FileSize = COFF::Header16Size;

  // one .rsrc section header for directory tree, another for resource data.
  FileSize += 2 * COFF::SectionSize;

  performSectionOneLayout();
  performSectionTwoLayout();

  // We have reached the address of the symbol table.
  SymbolTableOffset = FileSize;

  FileSize += COFF::Symbol16Size;     // size of the @feat.00 symbol.
  FileSize += 4 * COFF::Symbol16Size; // symbol + aux for each section.
  FileSize += Data.size() * COFF::Symbol16Size; // 1 symbol per resource.
  FileSize += 4; // four null bytes for the string table.
}

void WindowsResourceCOFFWriter::performSectionOneLayout() {
  SectionOneOffset = FileSize;

  SectionOneSize = Resources.getTreeSize();
  uint32_t CurrentStringOffset = SectionOneSize;
  uint32_t TotalStringTableSize = 0;
  for (auto const &String : StringTable) {
    StringTableOffsets.push_back(CurrentStringOffset);
    uint32_t StringSize = String.size() * sizeof(UTF16) + sizeof(uint16_t);
    CurrentStringOffset += StringSize;
    TotalStringTableSize += StringSize;
  }
  SectionOneSize += alignTo(TotalStringTableSize, sizeof(uint32_t));

  // account for the relocations of section one.
  SectionOneRelocations = FileSize + SectionOneSize;
  FileSize += SectionOneSize;
  FileSize +=
      Data.size() * COFF::RelocationSize; // one relocation for each resource.
  FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}

void WindowsResourceCOFFWriter::performSectionTwoLayout() {
  // add size of .rsrc$2 section, which contains all resource data on 8-byte
  // alignment.
  SectionTwoOffset = FileSize;
  SectionTwoSize = 0;
  for (auto const &Entry : Data) {
    DataOffsets.push_back(SectionTwoSize);
    SectionTwoSize += alignTo(Entry.size(), sizeof(uint64_t));
  }
  FileSize += SectionTwoSize;
  FileSize = alignTo(FileSize, SECTION_ALIGNMENT);
}

std::unique_ptr<MemoryBuffer>
WindowsResourceCOFFWriter::write(uint32_t TimeDateStamp) {
  BufferStart = OutputBuffer->getBufferStart();

  writeCOFFHeader(TimeDateStamp);
  writeFirstSectionHeader();
  writeSecondSectionHeader();
  writeFirstSection();
  writeSecondSection();
  writeSymbolTable();
  writeStringTable();

  return std::move(OutputBuffer);
}

// According to COFF specification, if the Src has a size equal to Dest,
// it's okay to *not* copy the trailing zero.
static void coffnamecpy(char (&Dest)[COFF::NameSize], StringRef Src) {
  assert(Src.size() <= COFF::NameSize &&
         "Src is not larger than COFF::NameSize");
  strncpy(Dest, Src.data(), (size_t)COFF::NameSize);
}

void WindowsResourceCOFFWriter::writeCOFFHeader(uint32_t TimeDateStamp) {
  // Write the COFF header.
  auto *Header = reinterpret_cast<coff_file_header *>(BufferStart);
  Header->Machine = MachineType;
  Header->NumberOfSections = 2;
  Header->TimeDateStamp = TimeDateStamp;
  Header->PointerToSymbolTable = SymbolTableOffset;
  // One symbol for every resource plus 2 for each section and 1 for @feat.00
  Header->NumberOfSymbols = Data.size() + 5;
  Header->SizeOfOptionalHeader = 0;
  // cvtres.exe sets 32BIT_MACHINE even for 64-bit machine types. Match it.
  Header->Characteristics = COFF::IMAGE_FILE_32BIT_MACHINE;
}

void WindowsResourceCOFFWriter::writeFirstSectionHeader() {
  // Write the first section header.
  CurrentOffset += sizeof(coff_file_header);
  auto *SectionOneHeader =
      reinterpret_cast<coff_section *>(BufferStart + CurrentOffset);
  coffnamecpy(SectionOneHeader->Name, ".rsrc$01");
  SectionOneHeader->VirtualSize = 0;
  SectionOneHeader->VirtualAddress = 0;
  SectionOneHeader->SizeOfRawData = SectionOneSize;
  SectionOneHeader->PointerToRawData = SectionOneOffset;
  SectionOneHeader->PointerToRelocations = SectionOneRelocations;
  SectionOneHeader->PointerToLinenumbers = 0;
  SectionOneHeader->NumberOfRelocations = Data.size();
  SectionOneHeader->NumberOfLinenumbers = 0;
  SectionOneHeader->Characteristics += COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
  SectionOneHeader->Characteristics += COFF::IMAGE_SCN_MEM_READ;
}

void WindowsResourceCOFFWriter::writeSecondSectionHeader() {
  // Write the second section header.
  CurrentOffset += sizeof(coff_section);
  auto *SectionTwoHeader =
      reinterpret_cast<coff_section *>(BufferStart + CurrentOffset);
  coffnamecpy(SectionTwoHeader->Name, ".rsrc$02");
  SectionTwoHeader->VirtualSize = 0;
  SectionTwoHeader->VirtualAddress = 0;
  SectionTwoHeader->SizeOfRawData = SectionTwoSize;
  SectionTwoHeader->PointerToRawData = SectionTwoOffset;
  SectionTwoHeader->PointerToRelocations = 0;
  SectionTwoHeader->PointerToLinenumbers = 0;
  SectionTwoHeader->NumberOfRelocations = 0;
  SectionTwoHeader->NumberOfLinenumbers = 0;
  SectionTwoHeader->Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
  SectionTwoHeader->Characteristics += COFF::IMAGE_SCN_MEM_READ;
}

void WindowsResourceCOFFWriter::writeFirstSection() {
  // Write section one.
  CurrentOffset += sizeof(coff_section);

  writeDirectoryTree();
  writeDirectoryStringTable();
  writeFirstSectionRelocations();

  CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT);
}

void WindowsResourceCOFFWriter::writeSecondSection() {
  // Now write the .rsrc$02 section.
  for (auto const &RawDataEntry : Data) {
    llvm::copy(RawDataEntry, BufferStart + CurrentOffset);
    CurrentOffset += alignTo(RawDataEntry.size(), sizeof(uint64_t));
  }

  CurrentOffset = alignTo(CurrentOffset, SECTION_ALIGNMENT);
}

void WindowsResourceCOFFWriter::writeSymbolTable() {
  // Now write the symbol table.
  // First, the feat symbol.
  auto *Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
  coffnamecpy(Symbol->Name.ShortName, "@feat.00");
  Symbol->Value = 0x11;
  Symbol->SectionNumber = 0xffff;
  Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
  Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
  Symbol->NumberOfAuxSymbols = 0;
  CurrentOffset += sizeof(coff_symbol16);

  // Now write the .rsrc1 symbol + aux.
  Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
  coffnamecpy(Symbol->Name.ShortName, ".rsrc$01");
  Symbol->Value = 0;
  Symbol->SectionNumber = 1;
  Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
  Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
  Symbol->NumberOfAuxSymbols = 1;
  CurrentOffset += sizeof(coff_symbol16);
  auto *Aux = reinterpret_cast<coff_aux_section_definition *>(BufferStart +
                                                              CurrentOffset);
  Aux->Length = SectionOneSize;
  Aux->NumberOfRelocations = Data.size();
  Aux->NumberOfLinenumbers = 0;
  Aux->CheckSum = 0;
  Aux->NumberLowPart = 0;
  Aux->Selection = 0;
  CurrentOffset += sizeof(coff_aux_section_definition);

  // Now write the .rsrc2 symbol + aux.
  Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
  coffnamecpy(Symbol->Name.ShortName, ".rsrc$02");
  Symbol->Value = 0;
  Symbol->SectionNumber = 2;
  Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
  Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
  Symbol->NumberOfAuxSymbols = 1;
  CurrentOffset += sizeof(coff_symbol16);
  Aux = reinterpret_cast<coff_aux_section_definition *>(BufferStart +
                                                        CurrentOffset);
  Aux->Length = SectionTwoSize;
  Aux->NumberOfRelocations = 0;
  Aux->NumberOfLinenumbers = 0;
  Aux->CheckSum = 0;
  Aux->NumberLowPart = 0;
  Aux->Selection = 0;
  CurrentOffset += sizeof(coff_aux_section_definition);

  // Now write a symbol for each relocation.
  for (unsigned i = 0; i < Data.size(); i++) {
    auto RelocationName = formatv("$R{0:X-6}", i & 0xffffff).sstr<COFF::NameSize>();
    Symbol = reinterpret_cast<coff_symbol16 *>(BufferStart + CurrentOffset);
    coffnamecpy(Symbol->Name.ShortName, RelocationName);
    Symbol->Value = DataOffsets[i];
    Symbol->SectionNumber = 2;
    Symbol->Type = COFF::IMAGE_SYM_DTYPE_NULL;
    Symbol->StorageClass = COFF::IMAGE_SYM_CLASS_STATIC;
    Symbol->NumberOfAuxSymbols = 0;
    CurrentOffset += sizeof(coff_symbol16);
  }
}

void WindowsResourceCOFFWriter::writeStringTable() {
  // Just 4 null bytes for the string table.
  auto COFFStringTable = reinterpret_cast<void *>(BufferStart + CurrentOffset);
  memset(COFFStringTable, 0, 4);
}

void WindowsResourceCOFFWriter::writeDirectoryTree() {
  // Traverse parsed resource tree breadth-first and write the corresponding
  // COFF objects.
  std::queue<const WindowsResourceParser::TreeNode *> Queue;
  Queue.push(&Resources);
  uint32_t NextLevelOffset =
      sizeof(coff_resource_dir_table) + (Resources.getStringChildren().size() +
                                         Resources.getIDChildren().size()) *
                                            sizeof(coff_resource_dir_entry);
  std::vector<const WindowsResourceParser::TreeNode *> DataEntriesTreeOrder;
  uint32_t CurrentRelativeOffset = 0;

  while (!Queue.empty()) {
    auto CurrentNode = Queue.front();
    Queue.pop();
    auto *Table = reinterpret_cast<coff_resource_dir_table *>(BufferStart +
                                                              CurrentOffset);
    Table->Characteristics = CurrentNode->getCharacteristics();
    Table->TimeDateStamp = 0;
    Table->MajorVersion = CurrentNode->getMajorVersion();
    Table->MinorVersion = CurrentNode->getMinorVersion();
    auto &IDChildren = CurrentNode->getIDChildren();
    auto &StringChildren = CurrentNode->getStringChildren();
    Table->NumberOfNameEntries = StringChildren.size();
    Table->NumberOfIDEntries = IDChildren.size();
    CurrentOffset += sizeof(coff_resource_dir_table);
    CurrentRelativeOffset += sizeof(coff_resource_dir_table);

    // Write the directory entries immediately following each directory table.
    for (auto const &Child : StringChildren) {
      auto *Entry = reinterpret_cast<coff_resource_dir_entry *>(BufferStart +
                                                                CurrentOffset);
      Entry->Identifier.setNameOffset(
          StringTableOffsets[Child.second->getStringIndex()]);
      if (Child.second->checkIsDataNode()) {
        Entry->Offset.DataEntryOffset = NextLevelOffset;
        NextLevelOffset += sizeof(coff_resource_data_entry);
        DataEntriesTreeOrder.push_back(Child.second.get());
      } else {
        Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
        NextLevelOffset += sizeof(coff_resource_dir_table) +
                           (Child.second->getStringChildren().size() +
                            Child.second->getIDChildren().size()) *
                               sizeof(coff_resource_dir_entry);
        Queue.push(Child.second.get());
      }
      CurrentOffset += sizeof(coff_resource_dir_entry);
      CurrentRelativeOffset += sizeof(coff_resource_dir_entry);
    }
    for (auto const &Child : IDChildren) {
      auto *Entry = reinterpret_cast<coff_resource_dir_entry *>(BufferStart +
                                                                CurrentOffset);
      Entry->Identifier.ID = Child.first;
      if (Child.second->checkIsDataNode()) {
        Entry->Offset.DataEntryOffset = NextLevelOffset;
        NextLevelOffset += sizeof(coff_resource_data_entry);
        DataEntriesTreeOrder.push_back(Child.second.get());
      } else {
        Entry->Offset.SubdirOffset = NextLevelOffset + (1 << 31);
        NextLevelOffset += sizeof(coff_resource_dir_table) +
                           (Child.second->getStringChildren().size() +
                            Child.second->getIDChildren().size()) *
                               sizeof(coff_resource_dir_entry);
        Queue.push(Child.second.get());
      }
      CurrentOffset += sizeof(coff_resource_dir_entry);
      CurrentRelativeOffset += sizeof(coff_resource_dir_entry);
    }
  }

  RelocationAddresses.resize(Data.size());
  // Now write all the resource data entries.
  for (auto DataNodes : DataEntriesTreeOrder) {
    auto *Entry = reinterpret_cast<coff_resource_data_entry *>(BufferStart +
                                                               CurrentOffset);
    RelocationAddresses[DataNodes->getDataIndex()] = CurrentRelativeOffset;
    Entry->DataRVA = 0; // Set to zero because it is a relocation.
    Entry->DataSize = Data[DataNodes->getDataIndex()].size();
    Entry->Codepage = 0;
    Entry->Reserved = 0;
    CurrentOffset += sizeof(coff_resource_data_entry);
    CurrentRelativeOffset += sizeof(coff_resource_data_entry);
  }
}

void WindowsResourceCOFFWriter::writeDirectoryStringTable() {
  // Now write the directory string table for .rsrc$01
  uint32_t TotalStringTableSize = 0;
  for (auto &String : StringTable) {
    uint16_t Length = String.size();
    support::endian::write16le(BufferStart + CurrentOffset, Length);
    CurrentOffset += sizeof(uint16_t);
    auto *Start = reinterpret_cast<UTF16 *>(BufferStart + CurrentOffset);
    llvm::copy(String, Start);
    CurrentOffset += Length * sizeof(UTF16);
    TotalStringTableSize += Length * sizeof(UTF16) + sizeof(uint16_t);
  }
  CurrentOffset +=
      alignTo(TotalStringTableSize, sizeof(uint32_t)) - TotalStringTableSize;
}

void WindowsResourceCOFFWriter::writeFirstSectionRelocations() {

  // Now write the relocations for .rsrc$01
  // Five symbols already in table before we start, @feat.00 and 2 for each
  // .rsrc section.
  uint32_t NextSymbolIndex = 5;
  for (unsigned i = 0; i < Data.size(); i++) {
    auto *Reloc =
        reinterpret_cast<coff_relocation *>(BufferStart + CurrentOffset);
    Reloc->VirtualAddress = RelocationAddresses[i];
    Reloc->SymbolTableIndex = NextSymbolIndex++;
    switch (MachineType) {
    case COFF::IMAGE_FILE_MACHINE_ARMNT:
      Reloc->Type = COFF::IMAGE_REL_ARM_ADDR32NB;
      break;
    case COFF::IMAGE_FILE_MACHINE_AMD64:
      Reloc->Type = COFF::IMAGE_REL_AMD64_ADDR32NB;
      break;
    case COFF::IMAGE_FILE_MACHINE_I386:
      Reloc->Type = COFF::IMAGE_REL_I386_DIR32NB;
      break;
    case COFF::IMAGE_FILE_MACHINE_ARM64:
      Reloc->Type = COFF::IMAGE_REL_ARM64_ADDR32NB;
      break;
    default:
      llvm_unreachable("unknown machine type");
    }
    CurrentOffset += sizeof(coff_relocation);
  }
}

Expected<std::unique_ptr<MemoryBuffer>>
writeWindowsResourceCOFF(COFF::MachineTypes MachineType,
                         const WindowsResourceParser &Parser,
                         uint32_t TimeDateStamp) {
  Error E = Error::success();
  WindowsResourceCOFFWriter Writer(MachineType, Parser, E);
  if (E)
    return std::move(E);
  return Writer.write(TimeDateStamp);
}

} // namespace object
} // namespace llvm
