//===- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp ---------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// PE/COFF file consists of DOS Header, PE Header, COFF Header and Section
/// Tables followed by raw section data.
///
/// This writer is responsible for writing Core Linker results to an Windows
/// executable file.
///
/// This writer currently supports 32 bit PE/COFF for x86 processor only.
///
//===----------------------------------------------------------------------===//

#include "Atoms.h"
#include "WriterImportLibrary.h"
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/ReaderWriter/AtomLayout.h"
#include "lld/ReaderWriter/PECOFFLinkingContext.h"
#include "lld/ReaderWriter/Writer.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Format.h"
#include <algorithm>
#include <cstdlib>
#include <map>
#include <time.h>
#include <vector>

#define DEBUG_TYPE "WriterPECOFF"

using llvm::COFF::DataDirectoryIndex;
using llvm::object::coff_runtime_function_x64;
using llvm::support::ulittle16_t;
using llvm::support::ulittle32_t;
using llvm::support::ulittle64_t;

namespace lld {
namespace pecoff {

// Disk sector size. Some data needs to be aligned at disk sector boundary in
// file.
static const int SECTOR_SIZE = 512;

namespace {
class SectionChunk;

/// A Chunk is an abstract contiguous range in an output file.
class Chunk {
public:
  enum Kind {
    kindHeader,
    kindSection,
    kindStringTable,
    kindAtomChunk
  };

  explicit Chunk(Kind kind) : _kind(kind), _size(0) {}
  virtual ~Chunk() {}
  virtual void write(uint8_t *buffer) = 0;
  virtual uint64_t size() const { return _size; }
  virtual uint64_t onDiskSize() const { return size(); }
  virtual uint64_t align() const { return 1; }

  uint64_t fileOffset() const { return _fileOffset; }
  void setFileOffset(uint64_t fileOffset) { _fileOffset = fileOffset; }
  Kind getKind() const { return _kind; }

protected:
  Kind _kind;
  uint64_t _size;
  uint64_t _fileOffset;
};

/// A HeaderChunk is an abstract class to represent a file header for
/// PE/COFF. The data in the header chunk is metadata about program and will
/// be consumed by the windows loader. HeaderChunks are not mapped to memory
/// when executed.
class HeaderChunk : public Chunk {
public:
  HeaderChunk() : Chunk(kindHeader) {}

  static bool classof(const Chunk *c) { return c->getKind() == kindHeader; }
};

/// A DOSStubChunk represents the DOS compatible header at the beginning
/// of PE/COFF files.
class DOSStubChunk : public HeaderChunk {
public:
  explicit DOSStubChunk(const PECOFFLinkingContext &ctx)
      : HeaderChunk(), _context(ctx) {
    // Minimum size of DOS stub is 64 bytes. The next block (PE header) needs to
    // be aligned on 8 byte boundary.
    size_t size = std::max(_context.getDosStub().size(), (size_t)64);
    _size = llvm::RoundUpToAlignment(size, 8);
  }

  void write(uint8_t *buffer) override {
    ArrayRef<uint8_t> array = _context.getDosStub();
    std::memcpy(buffer, array.data(), array.size());
    auto *header = reinterpret_cast<llvm::object::dos_header *>(buffer);
    header->AddressOfRelocationTable = sizeof(llvm::object::dos_header);
    header->AddressOfNewExeHeader = _size;
  }

private:
  const PECOFFLinkingContext &_context;
};

/// A PEHeaderChunk represents PE header including COFF header.
template <class PEHeader>
class PEHeaderChunk : public HeaderChunk {
public:
  explicit PEHeaderChunk(const PECOFFLinkingContext &ctx);

  void write(uint8_t *buffer) override;

  void setSizeOfHeaders(uint64_t size) {
    // Must be multiple of FileAlignment.
    _peHeader.SizeOfHeaders = llvm::RoundUpToAlignment(size, SECTOR_SIZE);
  }

  void setSizeOfCode(uint64_t size) { _peHeader.SizeOfCode = size; }
  void setBaseOfCode(uint32_t rva) { _peHeader.BaseOfCode = rva; }
  void setBaseOfData(uint32_t rva);
  void setSizeOfImage(uint32_t size) { _peHeader.SizeOfImage = size; }

  void setSizeOfInitializedData(uint64_t size) {
    _peHeader.SizeOfInitializedData = size;
  }

  void setSizeOfUninitializedData(uint64_t size) {
    _peHeader.SizeOfUninitializedData = size;
  }

  void setNumberOfSections(uint32_t num) { _coffHeader.NumberOfSections = num; }

  void setAddressOfEntryPoint(uint32_t address) {
    _peHeader.AddressOfEntryPoint = address;
  }

  void setPointerToSymbolTable(uint32_t rva) {
    _coffHeader.PointerToSymbolTable = rva;
  }

private:
  llvm::object::coff_file_header _coffHeader;
  PEHeader _peHeader;
};

/// A SectionHeaderTableChunk represents Section Table Header of PE/COFF
/// format, which is a list of section headers.
class SectionHeaderTableChunk : public HeaderChunk {
public:
  SectionHeaderTableChunk() : HeaderChunk() {}
  void addSection(SectionChunk *chunk);
  uint64_t size() const override;
  void write(uint8_t *buffer) override;

private:
  static llvm::object::coff_section createSectionHeader(SectionChunk *chunk);

  std::vector<SectionChunk *> _sections;
};

class StringTableChunk : public Chunk {
public:
  StringTableChunk() : Chunk(kindStringTable) {}

  static bool classof(const Chunk *c) {
    return c->getKind() == kindStringTable;
  }

  uint32_t addSectionName(StringRef sectionName) {
    if (_stringTable.empty())
      _stringTable.insert(_stringTable.begin(), 4, 0);
    uint32_t offset = _stringTable.size();
    _stringTable.insert(_stringTable.end(), sectionName.begin(),
                        sectionName.end());
    _stringTable.push_back('\0');
    return offset;
  }

  uint64_t size() const override { return _stringTable.size(); }

  void write(uint8_t *buffer) override {
    if (_stringTable.empty())
      return;
    *reinterpret_cast<ulittle32_t *>(_stringTable.data()) = _stringTable.size();
    std::memcpy(buffer, _stringTable.data(), _stringTable.size());
  }

private:
  std::vector<char> _stringTable;
};

class SectionChunk : public Chunk {
public:
  uint64_t onDiskSize() const override {
    if (_characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
      return 0;
    return llvm::RoundUpToAlignment(size(), SECTOR_SIZE);
  }

  uint64_t align() const override { return SECTOR_SIZE; }
  uint32_t getCharacteristics() const { return _characteristics; }
  StringRef getSectionName() const { return _sectionName; }
  virtual uint64_t memAlign() const { return _memAlign; }

  static bool classof(const Chunk *c) {
    Kind kind = c->getKind();
    return kind == kindSection || kind == kindAtomChunk;
  }

  uint64_t getVirtualAddress() { return _virtualAddress; }
  virtual void setVirtualAddress(uint32_t rva) { _virtualAddress = rva; }

  uint32_t getStringTableOffset() const { return _stringTableOffset; }
  void setStringTableOffset(uint32_t offset) { _stringTableOffset = offset; }

protected:
  SectionChunk(Kind kind, StringRef sectionName, uint32_t characteristics,
               const PECOFFLinkingContext &ctx)
      : Chunk(kind), _sectionName(sectionName),
        _characteristics(characteristics), _virtualAddress(0),
        _stringTableOffset(0), _memAlign(ctx.getPageSize()) {}

private:
  StringRef _sectionName;
  const uint32_t _characteristics;
  uint64_t _virtualAddress;
  uint32_t _stringTableOffset;
  uint64_t _memAlign;
};

/// An AtomChunk represents a section containing atoms.
class AtomChunk : public SectionChunk {
public:
  AtomChunk(const PECOFFLinkingContext &ctx, StringRef name,
            const std::vector<const DefinedAtom *> &atoms);

  void write(uint8_t *buffer) override;

  uint64_t memAlign() const override;
  void appendAtom(const DefinedAtom *atom);
  void buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const;

  void applyRelocationsARM(uint8_t *buffer,
                           std::map<const Atom *, uint64_t> &atomRva,
                           std::vector<uint64_t> &sectionRva,
                           uint64_t imageBaseAddress);
  void applyRelocationsX86(uint8_t *buffer,
                           std::map<const Atom *, uint64_t> &atomRva,
                           std::vector<uint64_t> &sectionRva,
                           uint64_t imageBaseAddress);
  void applyRelocationsX64(uint8_t *buffer,
                           std::map<const Atom *, uint64_t> &atomRva,
                           std::vector<uint64_t> &sectionRva,
                           uint64_t imageBaseAddress);

  void printAtomAddresses(uint64_t baseAddr) const;
  void addBaseRelocations(std::vector<uint64_t> &relocSites) const;

  void setVirtualAddress(uint32_t rva) override;
  uint64_t getAtomVirtualAddress(StringRef name) const;

  static bool classof(const Chunk *c) { return c->getKind() == kindAtomChunk; }

protected:
  std::vector<AtomLayout *> _atomLayouts;
  uint64_t _virtualAddress;

private:
  uint32_t
  computeCharacteristics(const PECOFFLinkingContext &ctx, StringRef name,
                         const std::vector<const DefinedAtom *> &atoms) const {
    return ctx.getSectionAttributes(name,
                                    getDefaultCharacteristics(name, atoms));
  }

  uint32_t getDefaultCharacteristics(
      StringRef name, const std::vector<const DefinedAtom *> &atoms) const;

  mutable llvm::BumpPtrAllocator _alloc;
  llvm::COFF::MachineTypes _machineType;
  const PECOFFLinkingContext &_ctx;
};

/// A DataDirectoryChunk represents data directory entries that follows the PE
/// header in the output file. An entry consists of an 8 byte field that
/// indicates a relative virtual address (the starting address of the entry data
/// in memory) and 8 byte entry data size.
class DataDirectoryChunk : public HeaderChunk {
public:
  DataDirectoryChunk()
      : HeaderChunk(), _data(std::vector<llvm::object::data_directory>(16)) {}

  uint64_t size() const override {
    return sizeof(llvm::object::data_directory) * _data.size();
  }

  void setField(DataDirectoryIndex index, uint32_t addr, uint32_t size);
  void write(uint8_t *buffer) override;

private:
  std::vector<llvm::object::data_directory> _data;
};

/// A BaseRelocChunk represents ".reloc" section.
///
/// .reloc section contains a list of addresses. If the PE/COFF loader decides
/// to load the binary at a memory address different from its preferred base
/// address, which is specified by ImageBase field in the COFF header, the
/// loader needs to relocate the binary, so that all the addresses in the binary
/// point to new locations. The loader will do that by fixing up the addresses
/// specified by .reloc section.
///
/// The executable is almost always loaded at the preferred base address because
/// it's loaded into an empty address space. The DLL is however an subject of
/// load-time relocation because it may conflict with other DLLs or the
/// executable.
class BaseRelocChunk : public SectionChunk {
  typedef std::vector<std::unique_ptr<Chunk> > ChunkVectorT;
  typedef std::map<uint64_t, std::vector<uint16_t> > PageOffsetT;

public:
  BaseRelocChunk(ChunkVectorT &chunks, const PECOFFLinkingContext &ctx)
      : SectionChunk(kindSection, ".reloc", characteristics, ctx),
        _ctx(ctx), _contents(createContents(chunks)) {}

  void write(uint8_t *buffer) override {
    std::memcpy(buffer, &_contents[0], _contents.size());
  }

  uint64_t size() const override { return _contents.size(); }

private:
  // When loaded into memory, reloc section should be readable and writable.
  static const uint32_t characteristics =
      llvm::COFF::IMAGE_SCN_MEM_READ |
      llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
      llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE;

  std::vector<uint8_t> createContents(ChunkVectorT &chunks) const;

  // Returns a list of RVAs that needs to be relocated if the binary is loaded
  // at an address different from its preferred one.
  std::vector<uint64_t> listRelocSites(ChunkVectorT &chunks) const;

  // Divide the given RVAs into blocks.
  PageOffsetT groupByPage(const std::vector<uint64_t> &relocSites) const;

  // Create the content of a relocation block.
  std::vector<uint8_t>
  createBaseRelocBlock(uint64_t pageAddr,
                       const std::vector<uint16_t> &offsets) const;

  const PECOFFLinkingContext &_ctx;
  std::vector<uint8_t> _contents;
};

template <class PEHeader>
PEHeaderChunk<PEHeader>::PEHeaderChunk(const PECOFFLinkingContext &ctx)
    : HeaderChunk() {
  // Set the size of the chunk and initialize the header with null bytes.
  _size = sizeof(llvm::COFF::PEMagic) + sizeof(_coffHeader) + sizeof(_peHeader);
  std::memset(&_coffHeader, 0, sizeof(_coffHeader));
  std::memset(&_peHeader, 0, sizeof(_peHeader));

  _coffHeader.Machine = ctx.getMachineType();
  _coffHeader.TimeDateStamp = time(nullptr);

  // Attributes of the executable.
  uint16_t characteristics = llvm::COFF::IMAGE_FILE_EXECUTABLE_IMAGE;
  if (!ctx.is64Bit())
    characteristics |= llvm::COFF::IMAGE_FILE_32BIT_MACHINE;
  if (ctx.isDll())
    characteristics |= llvm::COFF::IMAGE_FILE_DLL;
  if (ctx.getLargeAddressAware() || ctx.is64Bit())
    characteristics |= llvm::COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE;
  if (ctx.getSwapRunFromCD())
    characteristics |= llvm::COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
  if (ctx.getSwapRunFromNet())
    characteristics |= llvm::COFF::IMAGE_FILE_NET_RUN_FROM_SWAP;
  if (!ctx.getBaseRelocationEnabled())
    characteristics |= llvm::COFF::IMAGE_FILE_RELOCS_STRIPPED;

  _coffHeader.Characteristics = characteristics;

  _peHeader.Magic = ctx.is64Bit() ? llvm::COFF::PE32Header::PE32_PLUS
                                  : llvm::COFF::PE32Header::PE32;

  // The address of the executable when loaded into memory. The default for
  // DLLs is 0x10000000. The default for executables is 0x400000.
  _peHeader.ImageBase = ctx.getBaseAddress();

  // Sections should be page-aligned when loaded into memory, which is 4KB on
  // x86.
  _peHeader.SectionAlignment = ctx.getSectionDefaultAlignment();

  // Sections in an executable file on disk should be sector-aligned (512 byte).
  _peHeader.FileAlignment = SECTOR_SIZE;

  // The version number of the resultant executable/DLL. The number is purely
  // informative, and neither the linker nor the loader won't use it. User can
  // set the value using /version command line option. Default is 0.0.
  PECOFFLinkingContext::Version imageVersion = ctx.getImageVersion();
  _peHeader.MajorImageVersion = imageVersion.majorVersion;
  _peHeader.MinorImageVersion = imageVersion.minorVersion;

  // The required Windows version number. This is the internal version and
  // shouldn't be confused with product name. Windows 7 is version 6.1 and
  // Windows 8 is 6.2, for example.
  PECOFFLinkingContext::Version minOSVersion = ctx.getMinOSVersion();
  _peHeader.MajorOperatingSystemVersion = minOSVersion.majorVersion;
  _peHeader.MinorOperatingSystemVersion = minOSVersion.minorVersion;
  _peHeader.MajorSubsystemVersion = minOSVersion.majorVersion;
  _peHeader.MinorSubsystemVersion = minOSVersion.minorVersion;

  _peHeader.Subsystem = ctx.getSubsystem();

  // Despite its name, DLL characteristics field has meaning both for
  // executables and DLLs. We are not very sure if the following bits must
  // be set, but regular binaries seem to have these bits, so we follow
  // them.
  uint16_t dllCharacteristics = 0;
  if (ctx.noSEH())
    dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_SEH;
  if (ctx.isTerminalServerAware())
    dllCharacteristics |=
        llvm::COFF::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
  if (ctx.isNxCompat())
    dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
  if (ctx.getDynamicBaseEnabled())
    dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
  if (!ctx.getAllowBind())
    dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_BIND;
  if (!ctx.getAllowIsolation())
    dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
  if (ctx.getHighEntropyVA() && ctx.is64Bit())
    dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
  _peHeader.DLLCharacteristics = dllCharacteristics;

  _peHeader.SizeOfStackReserve = ctx.getStackReserve();
  _peHeader.SizeOfStackCommit = ctx.getStackCommit();
  _peHeader.SizeOfHeapReserve = ctx.getHeapReserve();
  _peHeader.SizeOfHeapCommit = ctx.getHeapCommit();

  // The number of data directory entries. We always have 16 entries.
  _peHeader.NumberOfRvaAndSize = 16;

  // The size of PE header including optional data directory.
  _coffHeader.SizeOfOptionalHeader = sizeof(PEHeader) +
      _peHeader.NumberOfRvaAndSize * sizeof(llvm::object::data_directory);
}

template <>
void PEHeaderChunk<llvm::object::pe32_header>::setBaseOfData(uint32_t rva) {
  _peHeader.BaseOfData = rva;
}

template <>
void PEHeaderChunk<llvm::object::pe32plus_header>::setBaseOfData(uint32_t rva) {
  // BaseOfData field does not exist in PE32+ header.
}

template <class PEHeader>
void PEHeaderChunk<PEHeader>::write(uint8_t *buffer) {
  std::memcpy(buffer, llvm::COFF::PEMagic, sizeof(llvm::COFF::PEMagic));
  buffer += sizeof(llvm::COFF::PEMagic);
  std::memcpy(buffer, &_coffHeader, sizeof(_coffHeader));
  buffer += sizeof(_coffHeader);
  std::memcpy(buffer, &_peHeader, sizeof(_peHeader));
}

AtomChunk::AtomChunk(const PECOFFLinkingContext &ctx, StringRef sectionName,
                     const std::vector<const DefinedAtom *> &atoms)
    : SectionChunk(kindAtomChunk, sectionName,
                   computeCharacteristics(ctx, sectionName, atoms), ctx),
      _virtualAddress(0), _machineType(ctx.getMachineType()), _ctx(ctx) {
  for (auto *a : atoms)
    appendAtom(a);
}

void AtomChunk::write(uint8_t *buffer) {
  if (_atomLayouts.empty())
    return;
  if (getCharacteristics() & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
    return;
  if (getCharacteristics() & llvm::COFF::IMAGE_SCN_CNT_CODE) {
    // Fill the section with INT 3 (0xCC) rather than NUL, so that the
    // disassembler will not interpret a garbage between atoms as the beginning
    // of multi-byte machine code. This does not change the behavior of
    // resulting binary but help debugging.
    uint8_t *start = buffer + _atomLayouts.front()->_fileOffset;
    uint8_t *end = buffer + _atomLayouts.back()->_fileOffset;
    memset(start, 0xCC, end - start);
  }

  for (const auto *layout : _atomLayouts) {
    const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
    ArrayRef<uint8_t> rawContent = atom->rawContent();
    std::memcpy(buffer + layout->_fileOffset, rawContent.data(),
                rawContent.size());
  }
}

// Add all atoms to the given map. This data will be used to do relocation.
void
AtomChunk::buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const {
  for (const auto *layout : _atomLayouts)
    atomRva[layout->_atom] = layout->_virtualAddr;
}

static int getSectionIndex(uint64_t targetAddr,
                           const std::vector<uint64_t> &sectionRva) {
  int i = 1;
  for (uint64_t rva : sectionRva) {
    if (targetAddr < rva)
      return i;
    ++i;
  }
  return i;
}

static uint32_t getSectionStartAddr(uint64_t targetAddr,
                                    const std::vector<uint64_t> &sectionRva) {
  // Scan the list of section start addresses to find the section start address
  // for the given RVA.
  for (int i = 0, e = sectionRva.size(); i < e; ++i)
    if (i == e - 1 || (sectionRva[i] <= targetAddr && targetAddr < sectionRva[i + 1]))
      return sectionRva[i];
  llvm_unreachable("Section missing");
}

static void applyThumbMoveImmediate(ulittle16_t *mov, uint16_t imm) {
  // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
  //            imm32 = zext imm4:i:imm3:imm8
  // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
  //            imm16 = imm4:i:imm3:imm8
  mov[0] =
      mov[0] | (((imm & 0x0800) >> 11) << 10) | (((imm & 0xf000) >> 12) << 0);
  mov[1] =
      mov[1] | (((imm & 0x0700) >> 8) << 12) | (((imm & 0x00ff) >> 0) << 0);
}

void AtomChunk::applyRelocationsARM(uint8_t *Buffer,
                                    std::map<const Atom *, uint64_t> &AtomRVA,
                                    std::vector<uint64_t> &SectionRVA,
                                    uint64_t ImageBase) {
  Buffer = Buffer + _fileOffset;
  for (const auto *Layout : _atomLayouts) {
    const DefinedAtom *Atom = cast<DefinedAtom>(Layout->_atom);
    for (const Reference *R : *Atom) {
      if (R->kindNamespace() != Reference::KindNamespace::COFF)
        continue;

      const auto AtomOffset = R->offsetInAtom();
      const auto FileOffset = Layout->_fileOffset;
      const auto TargetAddr = AtomRVA[R->target()];
      auto RelocSite16 =
          reinterpret_cast<ulittle16_t *>(Buffer + FileOffset + AtomOffset);
      auto RelocSite32 =
          reinterpret_cast<ulittle32_t *>(Buffer + FileOffset + AtomOffset);

      switch (R->kindValue()) {
      default: llvm_unreachable("unsupported relocation type");
      case llvm::COFF::IMAGE_REL_ARM_ADDR32:
        *RelocSite32 = *RelocSite32 + TargetAddr + ImageBase;
        break;
      case llvm::COFF::IMAGE_REL_ARM_MOV32T:
        applyThumbMoveImmediate(&RelocSite16[0], (TargetAddr + ImageBase) >>  0);
        applyThumbMoveImmediate(&RelocSite16[2], (TargetAddr + ImageBase) >> 16);
        break;
      }
    }
  }
}

void AtomChunk::applyRelocationsX86(uint8_t *buffer,
                                    std::map<const Atom *, uint64_t> &atomRva,
                                    std::vector<uint64_t> &sectionRva,
                                    uint64_t imageBaseAddress) {
  buffer += _fileOffset;
  for (const auto *layout : _atomLayouts) {
    const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
    for (const Reference *ref : *atom) {
      // Skip if this reference is not for COFF relocation.
      if (ref->kindNamespace() != Reference::KindNamespace::COFF)
        continue;
      auto relocSite32 = reinterpret_cast<ulittle32_t *>(
          buffer + layout->_fileOffset + ref->offsetInAtom());
      auto relocSite16 = reinterpret_cast<ulittle16_t *>(relocSite32);
      uint64_t targetAddr = atomRva[ref->target()];
      // Also account for whatever offset is already stored at the relocation
      // site.
      switch (ref->kindValue()) {
      case llvm::COFF::IMAGE_REL_I386_ABSOLUTE:
        // This relocation is no-op.
        break;
      case llvm::COFF::IMAGE_REL_I386_DIR32:
        // Set target's 32-bit VA.
        *relocSite32 += targetAddr + imageBaseAddress;
        break;
      case llvm::COFF::IMAGE_REL_I386_DIR32NB:
        // Set target's 32-bit RVA.
        *relocSite32 += targetAddr;
        break;
      case llvm::COFF::IMAGE_REL_I386_REL32: {
        // Set 32-bit relative address of the target. This relocation is
        // usually used for relative branch or call instruction.
        uint32_t disp = atomRva[atom] + ref->offsetInAtom() + 4;
        *relocSite32 += targetAddr - disp;
        break;
      }
      case llvm::COFF::IMAGE_REL_I386_SECTION:
        // The 16-bit section index that contains the target symbol.
        *relocSite16 += getSectionIndex(targetAddr, sectionRva);
        break;
      case llvm::COFF::IMAGE_REL_I386_SECREL:
        // The 32-bit relative address from the beginning of the section that
        // contains the target symbol.
        *relocSite32 +=
            targetAddr - getSectionStartAddr(targetAddr, sectionRva);
        break;
      default:
        llvm::report_fatal_error("Unsupported relocation kind");
      }
    }
  }
}

void AtomChunk::applyRelocationsX64(uint8_t *buffer,
                                    std::map<const Atom *, uint64_t> &atomRva,
                                    std::vector<uint64_t> &sectionRva,
                                    uint64_t imageBase) {
  buffer += _fileOffset;
  for (const auto *layout : _atomLayouts) {
    const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
    for (const Reference *ref : *atom) {
      if (ref->kindNamespace() != Reference::KindNamespace::COFF)
        continue;

      uint8_t *loc = buffer + layout->_fileOffset + ref->offsetInAtom();
      auto relocSite16 = reinterpret_cast<ulittle16_t *>(loc);
      auto relocSite32 = reinterpret_cast<ulittle32_t *>(loc);
      auto relocSite64 = reinterpret_cast<ulittle64_t *>(loc);
      uint64_t targetAddr = atomRva[ref->target()];

      switch (ref->kindValue()) {
      case llvm::COFF::IMAGE_REL_AMD64_ADDR64:
        *relocSite64 += targetAddr + imageBase;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_ADDR32:
        *relocSite32 += targetAddr + imageBase;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_ADDR32NB:
        *relocSite32 += targetAddr;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_REL32:
        *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 4;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_REL32_1:
        *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 5;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_REL32_2:
        *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 6;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_REL32_3:
        *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 7;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_REL32_4:
        *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 8;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_REL32_5:
        *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 9;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_SECTION:
        *relocSite16 += getSectionIndex(targetAddr, sectionRva) - 1;
        break;
      case llvm::COFF::IMAGE_REL_AMD64_SECREL:
        *relocSite32 +=
            targetAddr - getSectionStartAddr(targetAddr, sectionRva);
        break;
      default:
        llvm::errs() << "Kind: " << (int)ref->kindValue() << "\n";
        llvm::report_fatal_error("Unsupported relocation kind");
      }
    }
  }
}

/// Print atom VAs. Used only for debugging.
void AtomChunk::printAtomAddresses(uint64_t baseAddr) const {
  for (const auto *layout : _atomLayouts) {
    const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
    uint64_t addr = layout->_virtualAddr;
    llvm::dbgs() << llvm::format("0x%08llx: ", addr + baseAddr)
                 << (atom->name().empty() ? "(anonymous)" : atom->name())
                 << "\n";
  }
}

/// List all virtual addresses (and not relative virtual addresses) that need
/// to be fixed up if image base is relocated. The only relocation type that
/// needs to be fixed is DIR32 on i386. REL32 is not (and should not be)
/// fixed up because it's PC-relative.
void AtomChunk::addBaseRelocations(std::vector<uint64_t> &relocSites) const {
  // TODO: llvm-objdump doesn't support parsing the base relocation table, so
  // we can't really test this at the moment. As a temporary solution, we
  // should output debug messages with atom names and addresses so that we
  // can inspect relocations, and fix the tests (base-reloc.test, maybe
  // others) to use those messages.

  int16_t relType = 0; /* IMAGE_REL_*_ABSOLUTE */
  switch (_machineType) {
  default: llvm_unreachable("unsupported machine type");
  case llvm::COFF::IMAGE_FILE_MACHINE_I386:
    relType = llvm::COFF::IMAGE_REL_I386_DIR32;
    break;
  case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
    relType = llvm::COFF::IMAGE_REL_AMD64_ADDR64;
    break;
  case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
    relType = llvm::COFF::IMAGE_REL_ARM_ADDR32;
    break;
  }

  for (const auto *layout : _atomLayouts) {
    const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
    for (const Reference *ref : *atom)
      if ((ref->kindNamespace() == Reference::KindNamespace::COFF) &&
          (ref->kindValue() == relType))
        relocSites.push_back(layout->_virtualAddr + ref->offsetInAtom());
  }
}

void AtomChunk::setVirtualAddress(uint32_t rva) {
  SectionChunk::setVirtualAddress(rva);
  for (AtomLayout *layout : _atomLayouts)
    layout->_virtualAddr += rva;
}

uint64_t AtomChunk::getAtomVirtualAddress(StringRef name) const {
  for (auto atomLayout : _atomLayouts)
    if (atomLayout->_atom->name() == name)
      return atomLayout->_virtualAddr;
  return 0;
}

void DataDirectoryChunk::setField(DataDirectoryIndex index, uint32_t addr,
                                  uint32_t size) {
  llvm::object::data_directory &dir = _data[index];
  dir.RelativeVirtualAddress = addr;
  dir.Size = size;
}

void DataDirectoryChunk::write(uint8_t *buffer) {
  std::memcpy(buffer, &_data[0], size());
}

uint64_t AtomChunk::memAlign() const {
  // ReaderCOFF propagated the section alignment to the first atom in
  // the section. We restore that here.
  if (_atomLayouts.empty())
    return _ctx.getPageSize();
  int align = _ctx.getPageSize();
  for (auto atomLayout : _atomLayouts) {
    auto *atom = cast<const DefinedAtom>(atomLayout->_atom);
    align = std::max(align, 1 << atom->alignment().powerOf2);
  }
  return align;
}

void AtomChunk::appendAtom(const DefinedAtom *atom) {
  // Atom may have to be at a proper alignment boundary. If so, move the
  // pointer to make a room after the last atom before adding new one.
  _size = llvm::RoundUpToAlignment(_size, 1 << atom->alignment().powerOf2);

  // Create an AtomLayout and move the current pointer.
  auto *layout = new (_alloc) AtomLayout(atom, _size, _size);
  _atomLayouts.push_back(layout);
  _size += atom->size();
}

uint32_t AtomChunk::getDefaultCharacteristics(
    StringRef name, const std::vector<const DefinedAtom *> &atoms) const {
  const uint32_t code = llvm::COFF::IMAGE_SCN_CNT_CODE;
  const uint32_t execute = llvm::COFF::IMAGE_SCN_MEM_EXECUTE;
  const uint32_t read = llvm::COFF::IMAGE_SCN_MEM_READ;
  const uint32_t write = llvm::COFF::IMAGE_SCN_MEM_WRITE;
  const uint32_t data = llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
  const uint32_t bss = llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
  if (name == ".text")
    return code | execute | read;
  if (name == ".data")
    return data | read | write;
  if (name == ".rdata")
    return data | read;
  if (name == ".bss")
    return bss | read | write;
  assert(atoms.size() > 0);
  switch (atoms[0]->permissions()) {
  case DefinedAtom::permR__:
    return data | read;
  case DefinedAtom::permRW_:
    return data | read | write;
  case DefinedAtom::permR_X:
    return code | execute | read;
  case DefinedAtom::permRWX:
    return code | execute | read | write;
  default:
    llvm_unreachable("Unsupported permission");
  }
}

void SectionHeaderTableChunk::addSection(SectionChunk *chunk) {
  _sections.push_back(chunk);
}

uint64_t SectionHeaderTableChunk::size() const {
  return _sections.size() * sizeof(llvm::object::coff_section);
}

void SectionHeaderTableChunk::write(uint8_t *buffer) {
  uint64_t offset = 0;
  for (SectionChunk *chunk : _sections) {
    llvm::object::coff_section header = createSectionHeader(chunk);
    std::memcpy(buffer + offset, &header, sizeof(header));
    offset += sizeof(header);
  }
}

llvm::object::coff_section
SectionHeaderTableChunk::createSectionHeader(SectionChunk *chunk) {
  llvm::object::coff_section header;

  // We have extended the COFF specification by allowing section names to be
  // greater than eight characters.  We achieve this by adding the section names
  // to the string table.  Binutils' linker, ld, performs the same trick.
  StringRef sectionName = chunk->getSectionName();
  std::memset(header.Name, 0, llvm::COFF::NameSize);
  if (uint32_t stringTableOffset = chunk->getStringTableOffset())
    sprintf(header.Name, "/%u", stringTableOffset);
  else
    std::strncpy(header.Name, sectionName.data(), sectionName.size());

  uint32_t characteristics = chunk->getCharacteristics();
  header.VirtualSize = chunk->size();
  header.VirtualAddress = chunk->getVirtualAddress();
  header.SizeOfRawData = chunk->onDiskSize();
  header.PointerToRelocations = 0;
  header.PointerToLinenumbers = 0;
  header.NumberOfRelocations = 0;
  header.NumberOfLinenumbers = 0;
  header.Characteristics = characteristics;

  if (characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
    header.PointerToRawData = 0;
  } else {
    header.PointerToRawData = chunk->fileOffset();
  }
  return header;
}

/// Creates .reloc section content from the other sections. The content of
/// .reloc is basically a list of relocation sites. The relocation sites are
/// divided into blocks. Each block represents the base relocation for a 4K
/// page.
///
/// By dividing 32 bit RVAs into blocks, COFF saves disk and memory space for
/// the base relocation. A block consists of a 32 bit page RVA and 16 bit
/// relocation entries which represent offsets in the page. That is a more
/// compact representation than a simple vector of 32 bit RVAs.
std::vector<uint8_t>
BaseRelocChunk::createContents(ChunkVectorT &chunks) const {
  std::vector<uint8_t> contents;
  std::vector<uint64_t> relocSites = listRelocSites(chunks);
  PageOffsetT blocks = groupByPage(relocSites);
  for (auto &i : blocks) {
    uint64_t pageAddr = i.first;
    const std::vector<uint16_t> &offsetsInPage = i.second;
    std::vector<uint8_t> block = createBaseRelocBlock(pageAddr, offsetsInPage);
    contents.insert(contents.end(), block.begin(), block.end());
  }
  return contents;
}

// Returns a list of RVAs that needs to be relocated if the binary is loaded
// at an address different from its preferred one.
std::vector<uint64_t>
BaseRelocChunk::listRelocSites(ChunkVectorT &chunks) const {
  std::vector<uint64_t> ret;
  for (auto &cp : chunks)
    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
      chunk->addBaseRelocations(ret);
  return ret;
}

// Divide the given RVAs into blocks.
BaseRelocChunk::PageOffsetT
BaseRelocChunk::groupByPage(const std::vector<uint64_t> &relocSites) const {
  PageOffsetT blocks;
  uint64_t mask = _ctx.getPageSize() - 1;
  for (uint64_t addr : relocSites)
    blocks[addr & ~mask].push_back(addr & mask);
  return blocks;
}

// Create the content of a relocation block.
std::vector<uint8_t> BaseRelocChunk::createBaseRelocBlock(
    uint64_t pageAddr, const std::vector<uint16_t> &offsets) const {
  // Relocation blocks should be padded with IMAGE_REL_I386_ABSOLUTE to be
  // aligned to a DWORD size boundary.
  uint32_t size = llvm::RoundUpToAlignment(
      sizeof(ulittle32_t) * 2 + sizeof(ulittle16_t) * offsets.size(),
      sizeof(ulittle32_t));
  std::vector<uint8_t> contents(size);
  uint8_t *ptr = &contents[0];

  // The first four bytes is the page RVA.
  *reinterpret_cast<ulittle32_t *>(ptr) = pageAddr;
  ptr += sizeof(ulittle32_t);

  // The second four bytes is the size of the block, including the the page
  // RVA and this size field.
  *reinterpret_cast<ulittle32_t *>(ptr) = size;
  ptr += sizeof(ulittle32_t);

  // The rest of the block consists of offsets in the page.
  uint16_t type = _ctx.is64Bit() ? llvm::COFF::IMAGE_REL_BASED_DIR64
                                 : llvm::COFF::IMAGE_REL_BASED_HIGHLOW;
  for (uint16_t offset : offsets) {
    assert(offset < _ctx.getPageSize());
    *reinterpret_cast<ulittle16_t *>(ptr) = (type << 12) | offset;
    ptr += sizeof(ulittle16_t);
  }
  return contents;
}

} // end anonymous namespace

class PECOFFWriter : public Writer {
public:
  explicit PECOFFWriter(const PECOFFLinkingContext &context)
      : _ctx(context), _numSections(0), _imageSizeInMemory(_ctx.getPageSize()),
        _imageSizeOnDisk(0) {}

  template <class PEHeader> void build(const File &linkedFile);
  std::error_code writeFile(const File &linkedFile, StringRef path) override;

private:
  void applyAllRelocations(uint8_t *bufferStart);
  void printAllAtomAddresses() const;
  void reorderSEHTableEntries(uint8_t *bufferStart);
  void reorderSEHTableEntriesX86(uint8_t *bufferStart);
  void reorderSEHTableEntriesX64(uint8_t *bufferStart);

  void addChunk(Chunk *chunk);
  void addSectionChunk(std::unique_ptr<SectionChunk> chunk,
                       SectionHeaderTableChunk *table,
                       StringTableChunk *stringTable);
  void setImageSizeOnDisk();
  uint64_t
  calcSectionSize(llvm::COFF::SectionCharacteristics sectionType) const;

  uint64_t calcSizeOfInitializedData() const {
    return calcSectionSize(llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA);
  }

  uint64_t calcSizeOfUninitializedData() const {
    return calcSectionSize(llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA);
  }

  uint64_t calcSizeOfCode() const {
    return calcSectionSize(llvm::COFF::IMAGE_SCN_CNT_CODE);
  }

  std::vector<std::unique_ptr<Chunk> > _chunks;
  const PECOFFLinkingContext &_ctx;
  uint32_t _numSections;

  // The size of the image in memory. This is initialized with
  // _ctx.getPageSize(), as the first page starting at ImageBase is usually left
  // unmapped. IIUC there's no technical reason to do so, but we'll follow that
  // convention so that we don't produce odd-looking binary.
  uint32_t _imageSizeInMemory;

  // The size of the image on disk. This is basically the sum of all chunks in
  // the output file with paddings between them.
  uint32_t _imageSizeOnDisk;

  // The map from atom to its relative virtual address.
  std::map<const Atom *, uint64_t> _atomRva;
};

StringRef customSectionName(const DefinedAtom *atom) {
  assert(atom->sectionChoice() == DefinedAtom::sectionCustomRequired);
  StringRef s = atom->customSectionName();
  size_t pos = s.find('$');
  return (pos == StringRef::npos) ? s : s.substr(0, pos);
}

StringRef chooseSectionByContent(const DefinedAtom *atom) {
  switch (atom->contentType()) {
  case DefinedAtom::typeCode:
    return ".text";
  case DefinedAtom::typeZeroFill:
    return ".bss";
  case DefinedAtom::typeData:
    if (atom->permissions() == DefinedAtom::permR__)
      return ".rdata";
    if (atom->permissions() == DefinedAtom::permRW_)
      return ".data";
    break;
  default:
    break;
  }
  llvm::errs() << "Atom: contentType=" << atom->contentType()
               << " permission=" << atom->permissions() << "\n";
  llvm::report_fatal_error("Failed to choose section based on content");
}

typedef std::map<StringRef, std::vector<const DefinedAtom *> > AtomVectorMap;

void groupAtoms(const PECOFFLinkingContext &ctx, const File &file,
                AtomVectorMap &result) {
  for (const DefinedAtom *atom : file.defined()) {
    if (atom->sectionChoice() == DefinedAtom::sectionCustomRequired) {
      StringRef section = customSectionName(atom);
      result[ctx.getOutputSectionName(section)].push_back(atom);
      continue;
    }
    if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
      StringRef section = chooseSectionByContent(atom);
      result[ctx.getOutputSectionName(section)].push_back(atom);
      continue;
    }
    llvm_unreachable("Unknown section choice");
  }
}

static const DefinedAtom *findTLSUsedSymbol(const PECOFFLinkingContext &ctx,
                                            const File &file) {
  StringRef sym = ctx.decorateSymbol("_tls_used");
  for (const DefinedAtom *atom : file.defined())
    if (atom->name() == sym)
      return atom;
  return nullptr;
}

// Create all chunks that consist of the output file.
template <class PEHeader>
void PECOFFWriter::build(const File &linkedFile) {
  AtomVectorMap atoms;
  groupAtoms(_ctx, linkedFile, atoms);

  // Create file chunks and add them to the list.
  auto *dosStub = new DOSStubChunk(_ctx);
  auto *peHeader = new PEHeaderChunk<PEHeader>(_ctx);
  auto *dataDirectory = new DataDirectoryChunk();
  auto *sectionTable = new SectionHeaderTableChunk();
  auto *stringTable = new StringTableChunk();
  addChunk(dosStub);
  addChunk(peHeader);
  addChunk(dataDirectory);
  addChunk(sectionTable);
  addChunk(stringTable);

  // Create sections and add the atoms to them.
  for (auto i : atoms) {
    StringRef sectionName = i.first;
    std::vector<const DefinedAtom *> &contents = i.second;
    std::unique_ptr<SectionChunk> section(
        new AtomChunk(_ctx, sectionName, contents));
    if (section->size() > 0)
      addSectionChunk(std::move(section), sectionTable, stringTable);
  }

  // Build atom to its RVA map.
  for (std::unique_ptr<Chunk> &cp : _chunks)
    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
      chunk->buildAtomRvaMap(_atomRva);

  // We know the addresses of all defined atoms that needs to be
  // relocated. So we can create the ".reloc" section which contains
  // all the relocation sites.
  if (_ctx.getBaseRelocationEnabled()) {
    std::unique_ptr<SectionChunk> baseReloc(new BaseRelocChunk(_chunks, _ctx));
    if (baseReloc->size()) {
      SectionChunk &ref = *baseReloc;
      addSectionChunk(std::move(baseReloc), sectionTable, stringTable);
      dataDirectory->setField(DataDirectoryIndex::BASE_RELOCATION_TABLE,
                              ref.getVirtualAddress(), ref.size());
    }
  }

  setImageSizeOnDisk();
  // N.B. Currently released versions of dumpbin do not appropriately handle
  // symbol tables which NumberOfSymbols set to zero but a non-zero
  // PointerToSymbolTable.
  if (stringTable->size())
    peHeader->setPointerToSymbolTable(stringTable->fileOffset());

  for (std::unique_ptr<Chunk> &chunk : _chunks) {
    SectionChunk *section = dyn_cast<SectionChunk>(chunk.get());
    if (!section)
      continue;
    if (section->getSectionName() == ".text") {
      peHeader->setBaseOfCode(section->getVirtualAddress());

      // Find the virtual address of the entry point symbol if any.  PECOFF spec
      // says that entry point for dll images is optional, in which case it must
      // be set to 0.
      if (_ctx.hasEntry()) {
        uint64_t entryPointAddress =
            dyn_cast<AtomChunk>(section)
                ->getAtomVirtualAddress(_ctx.getEntrySymbolName());
        if (entryPointAddress != 0)
          peHeader->setAddressOfEntryPoint(entryPointAddress);
      } else {
        peHeader->setAddressOfEntryPoint(0);
      }
    }
    StringRef name = section->getSectionName();
    if (name == ".data") {
      peHeader->setBaseOfData(section->getVirtualAddress());
      continue;
    }
    DataDirectoryIndex ignore = DataDirectoryIndex(-1);
    DataDirectoryIndex idx = llvm::StringSwitch<DataDirectoryIndex>(name)
        .Case(".pdata", DataDirectoryIndex::EXCEPTION_TABLE)
        .Case(".rsrc", DataDirectoryIndex::RESOURCE_TABLE)
        .Case(".idata.a", DataDirectoryIndex::IAT)
        .Case(".idata.d", DataDirectoryIndex::IMPORT_TABLE)
        .Case(".edata", DataDirectoryIndex::EXPORT_TABLE)
        .Case(".loadcfg", DataDirectoryIndex::LOAD_CONFIG_TABLE)
        .Case(".didat.d", DataDirectoryIndex::DELAY_IMPORT_DESCRIPTOR)
        .Default(ignore);
    if (idx == ignore)
      continue;
    dataDirectory->setField(idx, section->getVirtualAddress(), section->size());
  }

  if (const DefinedAtom *atom = findTLSUsedSymbol(_ctx, linkedFile)) {
    dataDirectory->setField(DataDirectoryIndex::TLS_TABLE, _atomRva[atom],
                            0x18);
  }

  // Now that we know the size and file offset of sections. Set the file
  // header accordingly.
  peHeader->setSizeOfCode(calcSizeOfCode());
  peHeader->setSizeOfInitializedData(calcSizeOfInitializedData());
  peHeader->setSizeOfUninitializedData(calcSizeOfUninitializedData());
  peHeader->setNumberOfSections(_numSections);
  peHeader->setSizeOfImage(_imageSizeInMemory);
  peHeader->setSizeOfHeaders(sectionTable->fileOffset() + sectionTable->size());
}

std::error_code PECOFFWriter::writeFile(const File &linkedFile,
                                        StringRef path) {
  if (_ctx.is64Bit()) {
    this->build<llvm::object::pe32plus_header>(linkedFile);
  } else {
    this->build<llvm::object::pe32_header>(linkedFile);
  }

  uint64_t totalSize =
      _chunks.back()->fileOffset() + _chunks.back()->onDiskSize();
  std::unique_ptr<llvm::FileOutputBuffer> buffer;
  std::error_code ec = llvm::FileOutputBuffer::create(
      path, totalSize, buffer, llvm::FileOutputBuffer::F_executable);
  if (ec)
    return ec;

  for (std::unique_ptr<Chunk> &chunk : _chunks)
    chunk->write(buffer->getBufferStart() + chunk->fileOffset());
  applyAllRelocations(buffer->getBufferStart());
  reorderSEHTableEntries(buffer->getBufferStart());
  DEBUG(printAllAtomAddresses());

  if (_ctx.isDll())
    writeImportLibrary(_ctx);

  return buffer->commit();
}

/// Apply relocations to the output file buffer. This two pass. In the first
/// pass, we visit all atoms to create a map from atom to its virtual
/// address. In the second pass, we visit all relocation references to fix
/// up addresses in the buffer.
void PECOFFWriter::applyAllRelocations(uint8_t *bufferStart) {
  // Create the list of section start addresses. It's needed for
  // relocations of SECREL type.
  std::vector<uint64_t> sectionRva;
  for (auto &cp : _chunks)
    if (SectionChunk *section = dyn_cast<SectionChunk>(&*cp))
      sectionRva.push_back(section->getVirtualAddress());

  uint64_t base = _ctx.getBaseAddress();
  for (auto &cp : _chunks) {
    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp)) {
      switch (_ctx.getMachineType()) {
      default: llvm_unreachable("unsupported machine type");
      case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
        chunk->applyRelocationsARM(bufferStart, _atomRva, sectionRva, base);
        break;
      case llvm::COFF::IMAGE_FILE_MACHINE_I386:
        chunk->applyRelocationsX86(bufferStart, _atomRva, sectionRva, base);
        break;
      case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
        chunk->applyRelocationsX64(bufferStart, _atomRva, sectionRva, base);
        break;
      }
    }
  }
}

/// Print atom VAs. Used only for debugging.
void PECOFFWriter::printAllAtomAddresses() const {
  for (auto &cp : _chunks)
    if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
      chunk->printAtomAddresses(_ctx.getBaseAddress());
}

void PECOFFWriter::reorderSEHTableEntries(uint8_t *bufferStart) {
  auto machineType = _ctx.getMachineType();
  if (machineType == llvm::COFF::IMAGE_FILE_MACHINE_I386)
    reorderSEHTableEntriesX86(bufferStart);
  if (machineType == llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
    reorderSEHTableEntriesX64(bufferStart);
}

/// It seems that the entries in .sxdata must be sorted. This function is called
/// after a COFF file image is created in memory and before it is written to
/// disk. It is safe to reorder entries at this stage because the contents of
/// the entries are RVAs and there's no reference to a .sxdata entry other than
/// to the beginning of the section.
void PECOFFWriter::reorderSEHTableEntriesX86(uint8_t *bufferStart) {
  for (std::unique_ptr<Chunk> &chunk : _chunks) {
    if (SectionChunk *section = dyn_cast<SectionChunk>(chunk.get())) {
      if (section->getSectionName() == ".sxdata") {
        int numEntries = section->size() / sizeof(ulittle32_t);
        ulittle32_t *begin = reinterpret_cast<ulittle32_t *>(bufferStart + section->fileOffset());
        ulittle32_t *end = begin + numEntries;
        std::sort(begin, end);
      }
    }
  }
}

/// The entries in .pdata must be sorted according to its BeginAddress field
/// value. It's safe to do it because of the same reason as .sxdata.
void PECOFFWriter::reorderSEHTableEntriesX64(uint8_t *bufferStart) {
  for (std::unique_ptr<Chunk> &chunk : _chunks) {
    if (SectionChunk *section = dyn_cast<SectionChunk>(chunk.get())) {
      if (section->getSectionName() != ".pdata")
        continue;
      int numEntries = section->size() / sizeof(coff_runtime_function_x64);
      coff_runtime_function_x64 *begin =
          (coff_runtime_function_x64 *)(bufferStart + section->fileOffset());
      coff_runtime_function_x64 *end = begin + numEntries;
      std::sort(begin, end, [](const coff_runtime_function_x64 &lhs,
                               const coff_runtime_function_x64 &rhs) {
        return lhs.BeginAddress < rhs.BeginAddress;
      });
    }
  }
}

void PECOFFWriter::addChunk(Chunk *chunk) {
  _chunks.push_back(std::unique_ptr<Chunk>(chunk));
}

void PECOFFWriter::addSectionChunk(std::unique_ptr<SectionChunk> chunk,
                                   SectionHeaderTableChunk *table,
                                   StringTableChunk *stringTable) {
  table->addSection(chunk.get());
  _numSections++;

  StringRef sectionName = chunk->getSectionName();
  if (sectionName.size() > llvm::COFF::NameSize) {
    uint32_t stringTableOffset = stringTable->addSectionName(sectionName);
    chunk->setStringTableOffset(stringTableOffset);
  }

  // Compute and set the starting address of sections when loaded in
  // memory. They are different from positions on disk because sections need
  // to be sector-aligned on disk but page-aligned in memory.
  _imageSizeInMemory = llvm::RoundUpToAlignment(
      _imageSizeInMemory, chunk->memAlign());
  chunk->setVirtualAddress(_imageSizeInMemory);
  _imageSizeInMemory = llvm::RoundUpToAlignment(
      _imageSizeInMemory + chunk->size(), _ctx.getPageSize());
  _chunks.push_back(std::move(chunk));
}

void PECOFFWriter::setImageSizeOnDisk() {
  for (auto &chunk : _chunks) {
    // Compute and set the offset of the chunk in the output file.
    _imageSizeOnDisk =
        llvm::RoundUpToAlignment(_imageSizeOnDisk, chunk->align());
    chunk->setFileOffset(_imageSizeOnDisk);
    _imageSizeOnDisk += chunk->onDiskSize();
  }
}

uint64_t PECOFFWriter::calcSectionSize(
    llvm::COFF::SectionCharacteristics sectionType) const {
  uint64_t ret = 0;
  for (auto &cp : _chunks)
    if (SectionChunk *chunk = dyn_cast<SectionChunk>(&*cp))
      if (chunk->getCharacteristics() & sectionType)
        ret += chunk->onDiskSize();
  return ret;
}

} // end namespace pecoff

std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &info) {
  return std::unique_ptr<Writer>(new pecoff::PECOFFWriter(info));
}

} // end namespace lld
