//===- Writer.cpp ---------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "Writer.h"
#include "Config.h"
#include "DLL.h"
#include "InputFiles.h"
#include "MapFile.h"
#include "PDB.h"
#include "SymbolTable.h"
#include "Symbols.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
#include "lld/Common/Threads.h"
#include "lld/Common/Timer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/FileOutputBuffer.h"
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RandomNumberGenerator.h"
#include "llvm/Support/xxhash.h"
#include <algorithm>
#include <cstdio>
#include <map>
#include <memory>
#include <utility>

using namespace llvm;
using namespace llvm::COFF;
using namespace llvm::object;
using namespace llvm::support;
using namespace llvm::support::endian;
using namespace lld;
using namespace lld::coff;

/* To re-generate DOSProgram:
$ cat > /tmp/DOSProgram.asm
org 0
        ; Copy cs to ds.
        push cs
        pop ds
        ; Point ds:dx at the $-terminated string.
        mov dx, str
        ; Int 21/AH=09h: Write string to standard output.
        mov ah, 0x9
        int 0x21
        ; Int 21/AH=4Ch: Exit with return code (in AL).
        mov ax, 0x4C01
        int 0x21
str:
        db 'This program cannot be run in DOS mode.$'
align 8, db 0
$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
$ xxd -i /tmp/DOSProgram.bin
*/
static unsigned char DOSProgram[] = {
  0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,
  0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
  0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
  0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00
};
static_assert(sizeof(DOSProgram) % 8 == 0,
              "DOSProgram size must be multiple of 8");

static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram);
static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8");

static const int NumberOfDataDirectory = 16;

// Global vector of all output sections. After output sections are finalized,
// this can be indexed by Chunk::getOutputSection.
static std::vector<OutputSection *> OutputSections;

OutputSection *Chunk::getOutputSection() const {
  return OSIdx == 0 ? nullptr : OutputSections[OSIdx - 1];
}

namespace {

class DebugDirectoryChunk : public NonSectionChunk {
public:
  DebugDirectoryChunk(const std::vector<Chunk *> &R, bool WriteRepro)
      : Records(R), WriteRepro(WriteRepro) {}

  size_t getSize() const override {
    return (Records.size() + int(WriteRepro)) * sizeof(debug_directory);
  }

  void writeTo(uint8_t *B) const override {
    auto *D = reinterpret_cast<debug_directory *>(B);

    for (const Chunk *Record : Records) {
      OutputSection *OS = Record->getOutputSection();
      uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA());
      fillEntry(D, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, Record->getSize(),
                Record->getRVA(), Offs);
      ++D;
    }

    if (WriteRepro) {
      // FIXME: The COFF spec allows either a 0-sized entry to just say
      // "the timestamp field is really a hash", or a 4-byte size field
      // followed by that many bytes containing a longer hash (with the
      // lowest 4 bytes usually being the timestamp in little-endian order).
      // Consider storing the full 8 bytes computed by xxHash64 here.
      fillEntry(D, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0);
    }
  }

  void setTimeDateStamp(uint32_t TimeDateStamp) {
    for (support::ulittle32_t *TDS : TimeDateStamps)
      *TDS = TimeDateStamp;
  }

private:
  void fillEntry(debug_directory *D, COFF::DebugType DebugType, size_t Size,
                 uint64_t RVA, uint64_t Offs) const {
    D->Characteristics = 0;
    D->TimeDateStamp = 0;
    D->MajorVersion = 0;
    D->MinorVersion = 0;
    D->Type = DebugType;
    D->SizeOfData = Size;
    D->AddressOfRawData = RVA;
    D->PointerToRawData = Offs;

    TimeDateStamps.push_back(&D->TimeDateStamp);
  }

  mutable std::vector<support::ulittle32_t *> TimeDateStamps;
  const std::vector<Chunk *> &Records;
  bool WriteRepro;
};

class CVDebugRecordChunk : public NonSectionChunk {
public:
  size_t getSize() const override {
    return sizeof(codeview::DebugInfo) + Config->PDBAltPath.size() + 1;
  }

  void writeTo(uint8_t *B) const override {
    // Save off the DebugInfo entry to backfill the file signature (build id)
    // in Writer::writeBuildId
    BuildId = reinterpret_cast<codeview::DebugInfo *>(B);

    // variable sized field (PDB Path)
    char *P = reinterpret_cast<char *>(B + sizeof(*BuildId));
    if (!Config->PDBAltPath.empty())
      memcpy(P, Config->PDBAltPath.data(), Config->PDBAltPath.size());
    P[Config->PDBAltPath.size()] = '\0';
  }

  mutable codeview::DebugInfo *BuildId = nullptr;
};

// PartialSection represents a group of chunks that contribute to an
// OutputSection. Collating a collection of PartialSections of same name and
// characteristics constitutes the OutputSection.
class PartialSectionKey {
public:
  StringRef Name;
  unsigned Characteristics;

  bool operator<(const PartialSectionKey &Other) const {
    int C = Name.compare(Other.Name);
    if (C == 1)
      return false;
    if (C == 0)
      return Characteristics < Other.Characteristics;
    return true;
  }
};

// The writer writes a SymbolTable result to a file.
class Writer {
public:
  Writer() : Buffer(errorHandler().OutputBuffer) {}
  void run();

private:
  void createSections();
  void createMiscChunks();
  void createImportTables();
  void appendImportThunks();
  void locateImportTables();
  void createExportTable();
  void mergeSections();
  void removeUnusedSections();
  void assignAddresses();
  void finalizeAddresses();
  void removeEmptySections();
  void assignOutputSectionIndices();
  void createSymbolAndStringTable();
  void openFile(StringRef OutputPath);
  template <typename PEHeaderTy> void writeHeader();
  void createSEHTable();
  void createRuntimePseudoRelocs();
  void insertCtorDtorSymbols();
  void createGuardCFTables();
  void markSymbolsForRVATable(ObjFile *File,
                              ArrayRef<SectionChunk *> SymIdxChunks,
                              SymbolRVASet &TableSymbols);
  void maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,
                        StringRef CountSym);
  void setSectionPermissions();
  void writeSections();
  void writeBuildId();
  void sortExceptionTable();
  void sortCRTSectionChunks(std::vector<Chunk *> &Chunks);
  void addSyntheticIdata();
  bool fixGnuImportChunks();
  PartialSection *createPartialSection(StringRef Name, uint32_t OutChars);
  PartialSection *findPartialSection(StringRef Name, uint32_t OutChars);

  llvm::Optional<coff_symbol16> createSymbol(Defined *D);
  size_t addEntryToStringTable(StringRef Str);

  OutputSection *findSection(StringRef Name);
  void addBaserels();
  void addBaserelBlocks(std::vector<Baserel> &V);

  uint32_t getSizeOfInitializedData();

  std::unique_ptr<FileOutputBuffer> &Buffer;
  std::map<PartialSectionKey, PartialSection *> PartialSections;
  std::vector<char> Strtab;
  std::vector<llvm::object::coff_symbol16> OutputSymtab;
  IdataContents Idata;
  Chunk *ImportTableStart = nullptr;
  uint64_t ImportTableSize = 0;
  Chunk *IATStart = nullptr;
  uint64_t IATSize = 0;
  DelayLoadContents DelayIdata;
  EdataContents Edata;
  bool SetNoSEHCharacteristic = false;

  DebugDirectoryChunk *DebugDirectory = nullptr;
  std::vector<Chunk *> DebugRecords;
  CVDebugRecordChunk *BuildId = nullptr;
  ArrayRef<uint8_t> SectionTable;

  uint64_t FileSize;
  uint32_t PointerToSymbolTable = 0;
  uint64_t SizeOfImage;
  uint64_t SizeOfHeaders;

  OutputSection *TextSec;
  OutputSection *RdataSec;
  OutputSection *BuildidSec;
  OutputSection *DataSec;
  OutputSection *PdataSec;
  OutputSection *IdataSec;
  OutputSection *EdataSec;
  OutputSection *DidatSec;
  OutputSection *RsrcSec;
  OutputSection *RelocSec;
  OutputSection *CtorsSec;
  OutputSection *DtorsSec;

  // The first and last .pdata sections in the output file.
  //
  // We need to keep track of the location of .pdata in whichever section it
  // gets merged into so that we can sort its contents and emit a correct data
  // directory entry for the exception table. This is also the case for some
  // other sections (such as .edata) but because the contents of those sections
  // are entirely linker-generated we can keep track of their locations using
  // the chunks that the linker creates. All .pdata chunks come from input
  // files, so we need to keep track of them separately.
  Chunk *FirstPdata = nullptr;
  Chunk *LastPdata;
};
} // anonymous namespace

namespace lld {
namespace coff {

static Timer CodeLayoutTimer("Code Layout", Timer::root());
static Timer DiskCommitTimer("Commit Output File", Timer::root());

void writeResult() { Writer().run(); }

void OutputSection::addChunk(Chunk *C) {
  Chunks.push_back(C);
}

void OutputSection::insertChunkAtStart(Chunk *C) {
  Chunks.insert(Chunks.begin(), C);
}

void OutputSection::setPermissions(uint32_t C) {
  Header.Characteristics &= ~PermMask;
  Header.Characteristics |= C;
}

void OutputSection::merge(OutputSection *Other) {
  Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end());
  Other->Chunks.clear();
  ContribSections.insert(ContribSections.end(), Other->ContribSections.begin(),
                         Other->ContribSections.end());
  Other->ContribSections.clear();
}

// Write the section header to a given buffer.
void OutputSection::writeHeaderTo(uint8_t *Buf) {
  auto *Hdr = reinterpret_cast<coff_section *>(Buf);
  *Hdr = Header;
  if (StringTableOff) {
    // If name is too long, write offset into the string table as a name.
    sprintf(Hdr->Name, "/%d", StringTableOff);
  } else {
    assert(!Config->Debug || Name.size() <= COFF::NameSize ||
           (Hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0);
    strncpy(Hdr->Name, Name.data(),
            std::min(Name.size(), (size_t)COFF::NameSize));
  }
}

void OutputSection::addContributingPartialSection(PartialSection *Sec) {
  ContribSections.push_back(Sec);
}

} // namespace coff
} // namespace lld

// Check whether the target address S is in range from a relocation
// of type RelType at address P.
static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) {
  if (Config->Machine == ARMNT) {
    int64_t Diff = AbsoluteDifference(S, P + 4) + Margin;
    switch (RelType) {
    case IMAGE_REL_ARM_BRANCH20T:
      return isInt<21>(Diff);
    case IMAGE_REL_ARM_BRANCH24T:
    case IMAGE_REL_ARM_BLX23T:
      return isInt<25>(Diff);
    default:
      return true;
    }
  } else if (Config->Machine == ARM64) {
    int64_t Diff = AbsoluteDifference(S, P) + Margin;
    switch (RelType) {
    case IMAGE_REL_ARM64_BRANCH26:
      return isInt<28>(Diff);
    case IMAGE_REL_ARM64_BRANCH19:
      return isInt<21>(Diff);
    case IMAGE_REL_ARM64_BRANCH14:
      return isInt<16>(Diff);
    default:
      return true;
    }
  } else {
    llvm_unreachable("Unexpected architecture");
  }
}

// Return the last thunk for the given target if it is in range,
// or create a new one.
static std::pair<Defined *, bool>
getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,
         uint16_t Type, int Margin) {
  Defined *&LastThunk = LastThunks[Target->getRVA()];
  if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin))
    return {LastThunk, false};
  Chunk *C;
  switch (Config->Machine) {
  case ARMNT:
    C = make<RangeExtensionThunkARM>(Target);
    break;
  case ARM64:
    C = make<RangeExtensionThunkARM64>(Target);
    break;
  default:
    llvm_unreachable("Unexpected architecture");
  }
  Defined *D = make<DefinedSynthetic>("", C);
  LastThunk = D;
  return {D, true};
}

// This checks all relocations, and for any relocation which isn't in range
// it adds a thunk after the section chunk that contains the relocation.
// If the latest thunk for the specific target is in range, that is used
// instead of creating a new thunk. All range checks are done with the
// specified margin, to make sure that relocations that originally are in
// range, but only barely, also get thunks - in case other added thunks makes
// the target go out of range.
//
// After adding thunks, we verify that all relocations are in range (with
// no extra margin requirements). If this failed, we restart (throwing away
// the previously created thunks) and retry with a wider margin.
static bool createThunks(OutputSection *OS, int Margin) {
  bool AddressesChanged = false;
  DenseMap<uint64_t, Defined *> LastThunks;
  DenseMap<std::pair<ObjFile *, Defined *>, uint32_t> ThunkSymtabIndices;
  size_t ThunksSize = 0;
  // Recheck Chunks.size() each iteration, since we can insert more
  // elements into it.
  for (size_t I = 0; I != OS->Chunks.size(); ++I) {
    SectionChunk *SC = dyn_cast_or_null<SectionChunk>(OS->Chunks[I]);
    if (!SC)
      continue;
    size_t ThunkInsertionSpot = I + 1;

    // Try to get a good enough estimate of where new thunks will be placed.
    // Offset this by the size of the new thunks added so far, to make the
    // estimate slightly better.
    size_t ThunkInsertionRVA = SC->getRVA() + SC->getSize() + ThunksSize;
    ObjFile *File = SC->File;
    std::vector<std::pair<uint32_t, uint32_t>> RelocReplacements;
    ArrayRef<coff_relocation> OriginalRelocs =
        File->getCOFFObj()->getRelocations(SC->Header);
    for (size_t J = 0, E = OriginalRelocs.size(); J < E; ++J) {
      const coff_relocation &Rel = OriginalRelocs[J];
      Symbol *RelocTarget = File->getSymbol(Rel.SymbolTableIndex);

      // The estimate of the source address P should be pretty accurate,
      // but we don't know whether the target Symbol address should be
      // offset by ThunkSize or not (or by some of ThunksSize but not all of
      // it), giving us some uncertainty once we have added one thunk.
      uint64_t P = SC->getRVA() + Rel.VirtualAddress + ThunksSize;

      Defined *Sym = dyn_cast_or_null<Defined>(RelocTarget);
      if (!Sym)
        continue;

      uint64_t S = Sym->getRVA();

      if (isInRange(Rel.Type, S, P, Margin))
        continue;

      // If the target isn't in range, hook it up to an existing or new
      // thunk.
      Defined *Thunk;
      bool WasNew;
      std::tie(Thunk, WasNew) = getThunk(LastThunks, Sym, P, Rel.Type, Margin);
      if (WasNew) {
        Chunk *ThunkChunk = Thunk->getChunk();
        ThunkChunk->setRVA(
            ThunkInsertionRVA); // Estimate of where it will be located.
        OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk);
        ThunkInsertionSpot++;
        ThunksSize += ThunkChunk->getSize();
        ThunkInsertionRVA += ThunkChunk->getSize();
        AddressesChanged = true;
      }

      // To redirect the relocation, add a symbol to the parent object file's
      // symbol table, and replace the relocation symbol table index with the
      // new index.
      auto Insertion = ThunkSymtabIndices.insert({{File, Thunk}, ~0U});
      uint32_t &ThunkSymbolIndex = Insertion.first->second;
      if (Insertion.second)
        ThunkSymbolIndex = File->addRangeThunkSymbol(Thunk);
      RelocReplacements.push_back({J, ThunkSymbolIndex});
    }

    // Get a writable copy of this section's relocations so they can be
    // modified. If the relocations point into the object file, allocate new
    // memory. Otherwise, this must be previously allocated memory that can be
    // modified in place.
    ArrayRef<coff_relocation> CurRelocs = SC->getRelocs();
    MutableArrayRef<coff_relocation> NewRelocs;
    if (OriginalRelocs.data() == CurRelocs.data()) {
      NewRelocs = makeMutableArrayRef(
          BAlloc.Allocate<coff_relocation>(OriginalRelocs.size()),
          OriginalRelocs.size());
    } else {
      NewRelocs = makeMutableArrayRef(
          const_cast<coff_relocation *>(CurRelocs.data()), CurRelocs.size());
    }

    // Copy each relocation, but replace the symbol table indices which need
    // thunks.
    auto NextReplacement = RelocReplacements.begin();
    auto EndReplacement = RelocReplacements.end();
    for (size_t I = 0, E = OriginalRelocs.size(); I != E; ++I) {
      NewRelocs[I] = OriginalRelocs[I];
      if (NextReplacement != EndReplacement && NextReplacement->first == I) {
        NewRelocs[I].SymbolTableIndex = NextReplacement->second;
        ++NextReplacement;
      }
    }

    SC->setRelocs(NewRelocs);
  }
  return AddressesChanged;
}

// Verify that all relocations are in range, with no extra margin requirements.
static bool verifyRanges(const std::vector<Chunk *> Chunks) {
  for (Chunk *C : Chunks) {
    SectionChunk *SC = dyn_cast_or_null<SectionChunk>(C);
    if (!SC)
      continue;

    ArrayRef<coff_relocation> Relocs = SC->getRelocs();
    for (size_t J = 0, E = Relocs.size(); J < E; ++J) {
      const coff_relocation &Rel = Relocs[J];
      Symbol *RelocTarget = SC->File->getSymbol(Rel.SymbolTableIndex);

      Defined *Sym = dyn_cast_or_null<Defined>(RelocTarget);
      if (!Sym)
        continue;

      uint64_t P = SC->getRVA() + Rel.VirtualAddress;
      uint64_t S = Sym->getRVA();

      if (!isInRange(Rel.Type, S, P, 0))
        return false;
    }
  }
  return true;
}

// Assign addresses and add thunks if necessary.
void Writer::finalizeAddresses() {
  assignAddresses();
  if (Config->Machine != ARMNT && Config->Machine != ARM64)
    return;

  size_t OrigNumChunks = 0;
  for (OutputSection *Sec : OutputSections) {
    Sec->OrigChunks = Sec->Chunks;
    OrigNumChunks += Sec->Chunks.size();
  }

  int Pass = 0;
  int Margin = 1024 * 100;
  while (true) {
    // First check whether we need thunks at all, or if the previous pass of
    // adding them turned out ok.
    bool RangesOk = true;
    size_t NumChunks = 0;
    for (OutputSection *Sec : OutputSections) {
      if (!verifyRanges(Sec->Chunks)) {
        RangesOk = false;
        break;
      }
      NumChunks += Sec->Chunks.size();
    }
    if (RangesOk) {
      if (Pass > 0)
        log("Added " + Twine(NumChunks - OrigNumChunks) + " thunks with " +
            "margin " + Twine(Margin) + " in " + Twine(Pass) + " passes");
      return;
    }

    if (Pass >= 10)
      fatal("adding thunks hasn't converged after " + Twine(Pass) + " passes");

    if (Pass > 0) {
      // If the previous pass didn't work out, reset everything back to the
      // original conditions before retrying with a wider margin. This should
      // ideally never happen under real circumstances.
      for (OutputSection *Sec : OutputSections)
        Sec->Chunks = Sec->OrigChunks;
      Margin *= 2;
    }

    // Try adding thunks everywhere where it is needed, with a margin
    // to avoid things going out of range due to the added thunks.
    bool AddressesChanged = false;
    for (OutputSection *Sec : OutputSections)
      AddressesChanged |= createThunks(Sec, Margin);
    // If the verification above thought we needed thunks, we should have
    // added some.
    assert(AddressesChanged);

    // Recalculate the layout for the whole image (and verify the ranges at
    // the start of the next round).
    assignAddresses();

    Pass++;
  }
}

// The main function of the writer.
void Writer::run() {
  ScopedTimer T1(CodeLayoutTimer);

  createImportTables();
  createSections();
  createMiscChunks();
  appendImportThunks();
  createExportTable();
  mergeSections();
  removeUnusedSections();
  finalizeAddresses();
  removeEmptySections();
  assignOutputSectionIndices();
  setSectionPermissions();
  createSymbolAndStringTable();

  if (FileSize > UINT32_MAX)
    fatal("image size (" + Twine(FileSize) + ") " +
        "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")");

  openFile(Config->OutputFile);
  if (Config->is64()) {
    writeHeader<pe32plus_header>();
  } else {
    writeHeader<pe32_header>();
  }
  writeSections();
  sortExceptionTable();

  T1.stop();

  if (!Config->PDBPath.empty() && Config->Debug) {
    assert(BuildId);
    createPDB(Symtab, OutputSections, SectionTable, BuildId->BuildId);
  }
  writeBuildId();

  writeMapFile(OutputSections);

  ScopedTimer T2(DiskCommitTimer);
  if (auto E = Buffer->commit())
    fatal("failed to write the output file: " + toString(std::move(E)));
}

static StringRef getOutputSectionName(StringRef Name) {
  StringRef S = Name.split('$').first;

  // Treat a later period as a separator for MinGW, for sections like
  // ".ctors.01234".
  return S.substr(0, S.find('.', 1));
}

// For /order.
static void sortBySectionOrder(std::vector<Chunk *> &Chunks) {
  auto GetPriority = [](const Chunk *C) {
    if (auto *Sec = dyn_cast<SectionChunk>(C))
      if (Sec->Sym)
        return Config->Order.lookup(Sec->Sym->getName());
    return 0;
  };

  llvm::stable_sort(Chunks, [=](const Chunk *A, const Chunk *B) {
    return GetPriority(A) < GetPriority(B);
  });
}

// Sort concrete section chunks from GNU import libraries.
//
// GNU binutils doesn't use short import files, but instead produces import
// libraries that consist of object files, with section chunks for the .idata$*
// sections. These are linked just as regular static libraries. Each import
// library consists of one header object, one object file for every imported
// symbol, and one trailer object. In order for the .idata tables/lists to
// be formed correctly, the section chunks within each .idata$* section need
// to be grouped by library, and sorted alphabetically within each library
// (which makes sure the header comes first and the trailer last).
bool Writer::fixGnuImportChunks() {
  uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;

  // Make sure all .idata$* section chunks are mapped as RDATA in order to
  // be sorted into the same sections as our own synthesized .idata chunks.
  for (auto It : PartialSections) {
    PartialSection *PSec = It.second;
    if (!PSec->Name.startswith(".idata"))
      continue;
    if (PSec->Characteristics == RDATA)
      continue;
    PartialSection *RDataSec = createPartialSection(PSec->Name, RDATA);
    RDataSec->Chunks.insert(RDataSec->Chunks.end(), PSec->Chunks.begin(),
                            PSec->Chunks.end());
    PSec->Chunks.clear();
  }

  bool HasIdata = false;
  // Sort all .idata$* chunks, grouping chunks from the same library,
  // with alphabetical ordering of the object fils within a library.
  for (auto It : PartialSections) {
    PartialSection *PSec = It.second;
    if (!PSec->Name.startswith(".idata"))
      continue;

    if (!PSec->Chunks.empty())
      HasIdata = true;
    llvm::stable_sort(PSec->Chunks, [&](Chunk *S, Chunk *T) {
      SectionChunk *SC1 = dyn_cast_or_null<SectionChunk>(S);
      SectionChunk *SC2 = dyn_cast_or_null<SectionChunk>(T);
      if (!SC1 || !SC2) {
        // if SC1, order them ascending. If SC2 or both null,
        // S is not less than T.
        return SC1 != nullptr;
      }
      // Make a string with "libraryname/objectfile" for sorting, achieving
      // both grouping by library and sorting of objects within a library,
      // at once.
      std::string Key1 =
          (SC1->File->ParentName + "/" + SC1->File->getName()).str();
      std::string Key2 =
          (SC2->File->ParentName + "/" + SC2->File->getName()).str();
      return Key1 < Key2;
    });
  }
  return HasIdata;
}

// Add generated idata chunks, for imported symbols and DLLs, and a
// terminator in .idata$2.
void Writer::addSyntheticIdata() {
  uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
  Idata.create();

  // Add the .idata content in the right section groups, to allow
  // chunks from other linked in object files to be grouped together.
  // See Microsoft PE/COFF spec 5.4 for details.
  auto Add = [&](StringRef N, std::vector<Chunk *> &V) {
    PartialSection *PSec = createPartialSection(N, RDATA);
    PSec->Chunks.insert(PSec->Chunks.end(), V.begin(), V.end());
  };

  // The loader assumes a specific order of data.
  // Add each type in the correct order.
  Add(".idata$2", Idata.Dirs);
  Add(".idata$4", Idata.Lookups);
  Add(".idata$5", Idata.Addresses);
  Add(".idata$6", Idata.Hints);
  Add(".idata$7", Idata.DLLNames);
}

// Locate the first Chunk and size of the import directory list and the
// IAT.
void Writer::locateImportTables() {
  uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;

  if (PartialSection *ImportDirs = findPartialSection(".idata$2", RDATA)) {
    if (!ImportDirs->Chunks.empty())
      ImportTableStart = ImportDirs->Chunks.front();
    for (Chunk *C : ImportDirs->Chunks)
      ImportTableSize += C->getSize();
  }

  if (PartialSection *ImportAddresses = findPartialSection(".idata$5", RDATA)) {
    if (!ImportAddresses->Chunks.empty())
      IATStart = ImportAddresses->Chunks.front();
    for (Chunk *C : ImportAddresses->Chunks)
      IATSize += C->getSize();
  }
}

// Create output section objects and add them to OutputSections.
void Writer::createSections() {
  // First, create the builtin sections.
  const uint32_t DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
  const uint32_t BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
  const uint32_t CODE = IMAGE_SCN_CNT_CODE;
  const uint32_t DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
  const uint32_t R = IMAGE_SCN_MEM_READ;
  const uint32_t W = IMAGE_SCN_MEM_WRITE;
  const uint32_t X = IMAGE_SCN_MEM_EXECUTE;

  SmallDenseMap<std::pair<StringRef, uint32_t>, OutputSection *> Sections;
  auto CreateSection = [&](StringRef Name, uint32_t OutChars) {
    OutputSection *&Sec = Sections[{Name, OutChars}];
    if (!Sec) {
      Sec = make<OutputSection>(Name, OutChars);
      OutputSections.push_back(Sec);
    }
    return Sec;
  };

  // Try to match the section order used by link.exe.
  TextSec = CreateSection(".text", CODE | R | X);
  CreateSection(".bss", BSS | R | W);
  RdataSec = CreateSection(".rdata", DATA | R);
  BuildidSec = CreateSection(".buildid", DATA | R);
  DataSec = CreateSection(".data", DATA | R | W);
  PdataSec = CreateSection(".pdata", DATA | R);
  IdataSec = CreateSection(".idata", DATA | R);
  EdataSec = CreateSection(".edata", DATA | R);
  DidatSec = CreateSection(".didat", DATA | R);
  RsrcSec = CreateSection(".rsrc", DATA | R);
  RelocSec = CreateSection(".reloc", DATA | DISCARDABLE | R);
  CtorsSec = CreateSection(".ctors", DATA | R | W);
  DtorsSec = CreateSection(".dtors", DATA | R | W);

  // Then bin chunks by name and output characteristics.
  for (Chunk *C : Symtab->getChunks()) {
    auto *SC = dyn_cast<SectionChunk>(C);
    if (SC && !SC->Live) {
      if (Config->Verbose)
        SC->printDiscardedMessage();
      continue;
    }
    PartialSection *PSec = createPartialSection(C->getSectionName(),
                                                C->getOutputCharacteristics());
    PSec->Chunks.push_back(C);
  }

  // Even in non MinGW cases, we might need to link against GNU import
  // libraries.
  bool HasIdata = fixGnuImportChunks();
  if (!Idata.empty())
    HasIdata = true;

  if (HasIdata)
    addSyntheticIdata();

  // Process an /order option.
  if (!Config->Order.empty())
    for (auto It : PartialSections)
      sortBySectionOrder(It.second->Chunks);

  if (HasIdata)
    locateImportTables();

  // Then create an OutputSection for each section.
  // '$' and all following characters in input section names are
  // discarded when determining output section. So, .text$foo
  // contributes to .text, for example. See PE/COFF spec 3.2.
  for (auto It : PartialSections) {
    PartialSection *PSec = It.second;
    StringRef Name = getOutputSectionName(PSec->Name);
    uint32_t OutChars = PSec->Characteristics;

    if (Name == ".CRT") {
      // In link.exe, there is a special case for the I386 target where .CRT
      // sections are treated as if they have output characteristics DATA | R if
      // their characteristics are DATA | R | W. This implements the same
      // special case for all architectures.
      OutChars = DATA | R;

      log("Processing section " + PSec->Name + " -> " + Name);

      sortCRTSectionChunks(PSec->Chunks);
    }

    OutputSection *Sec = CreateSection(Name, OutChars);
    for (Chunk *C : PSec->Chunks)
      Sec->addChunk(C);

    Sec->addContributingPartialSection(PSec);
  }

  // Finally, move some output sections to the end.
  auto SectionOrder = [&](const OutputSection *S) {
    // Move DISCARDABLE (or non-memory-mapped) sections to the end of file
    // because the loader cannot handle holes. Stripping can remove other
    // discardable ones than .reloc, which is first of them (created early).
    if (S->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
      return 2;
    // .rsrc should come at the end of the non-discardable sections because its
    // size may change by the Win32 UpdateResources() function, causing
    // subsequent sections to move (see https://crbug.com/827082).
    if (S == RsrcSec)
      return 1;
    return 0;
  };
  llvm::stable_sort(OutputSections,
                    [&](const OutputSection *S, const OutputSection *T) {
                      return SectionOrder(S) < SectionOrder(T);
                    });
}

void Writer::createMiscChunks() {
  for (MergeChunk *P : MergeChunk::Instances) {
    if (P) {
      P->finalizeContents();
      RdataSec->addChunk(P);
    }
  }

  // Create thunks for locally-dllimported symbols.
  if (!Symtab->LocalImportChunks.empty()) {
    for (Chunk *C : Symtab->LocalImportChunks)
      RdataSec->addChunk(C);
  }

  // Create Debug Information Chunks
  OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;
  if (Config->Debug || Config->Repro) {
    DebugDirectory = make<DebugDirectoryChunk>(DebugRecords, Config->Repro);
    DebugInfoSec->addChunk(DebugDirectory);
  }

  if (Config->Debug) {
    // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified.  We
    // output a PDB no matter what, and this chunk provides the only means of
    // allowing a debugger to match a PDB and an executable.  So we need it even
    // if we're ultimately not going to write CodeView data to the PDB.
    BuildId = make<CVDebugRecordChunk>();
    DebugRecords.push_back(BuildId);

    for (Chunk *C : DebugRecords)
      DebugInfoSec->addChunk(C);
  }

  // Create SEH table. x86-only.
  if (Config->Machine == I386)
    createSEHTable();

  // Create /guard:cf tables if requested.
  if (Config->GuardCF != GuardCFLevel::Off)
    createGuardCFTables();

  if (Config->MinGW) {
    createRuntimePseudoRelocs();

    insertCtorDtorSymbols();
  }
}

// Create .idata section for the DLL-imported symbol table.
// The format of this section is inherently Windows-specific.
// IdataContents class abstracted away the details for us,
// so we just let it create chunks and add them to the section.
void Writer::createImportTables() {
  // Initialize DLLOrder so that import entries are ordered in
  // the same order as in the command line. (That affects DLL
  // initialization order, and this ordering is MSVC-compatible.)
  for (ImportFile *File : ImportFile::Instances) {
    if (!File->Live)
      continue;

    std::string DLL = StringRef(File->DLLName).lower();
    if (Config->DLLOrder.count(DLL) == 0)
      Config->DLLOrder[DLL] = Config->DLLOrder.size();

    if (File->ImpSym && !isa<DefinedImportData>(File->ImpSym))
      fatal(toString(*File->ImpSym) + " was replaced");
    DefinedImportData *ImpSym = cast_or_null<DefinedImportData>(File->ImpSym);
    if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) {
      if (!File->ThunkSym)
        fatal("cannot delay-load " + toString(File) +
              " due to import of data: " + toString(*ImpSym));
      DelayIdata.add(ImpSym);
    } else {
      Idata.add(ImpSym);
    }
  }
}

void Writer::appendImportThunks() {
  if (ImportFile::Instances.empty())
    return;

  for (ImportFile *File : ImportFile::Instances) {
    if (!File->Live)
      continue;

    if (!File->ThunkSym)
      continue;

    if (!isa<DefinedImportThunk>(File->ThunkSym))
      fatal(toString(*File->ThunkSym) + " was replaced");
    DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym);
    if (File->ThunkLive)
      TextSec->addChunk(Thunk->getChunk());
  }

  if (!DelayIdata.empty()) {
    Defined *Helper = cast<Defined>(Config->DelayLoadHelper);
    DelayIdata.create(Helper);
    for (Chunk *C : DelayIdata.getChunks())
      DidatSec->addChunk(C);
    for (Chunk *C : DelayIdata.getDataChunks())
      DataSec->addChunk(C);
    for (Chunk *C : DelayIdata.getCodeChunks())
      TextSec->addChunk(C);
  }
}

void Writer::createExportTable() {
  if (Config->Exports.empty())
    return;
  for (Chunk *C : Edata.Chunks)
    EdataSec->addChunk(C);
}

void Writer::removeUnusedSections() {
  // Remove sections that we can be sure won't get content, to avoid
  // allocating space for their section headers.
  auto IsUnused = [this](OutputSection *S) {
    if (S == RelocSec)
      return false; // This section is populated later.
    // MergeChunks have zero size at this point, as their size is finalized
    // later. Only remove sections that have no Chunks at all.
    return S->Chunks.empty();
  };
  OutputSections.erase(
      std::remove_if(OutputSections.begin(), OutputSections.end(), IsUnused),
      OutputSections.end());
}

// The Windows loader doesn't seem to like empty sections,
// so we remove them if any.
void Writer::removeEmptySections() {
  auto IsEmpty = [](OutputSection *S) { return S->getVirtualSize() == 0; };
  OutputSections.erase(
      std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
      OutputSections.end());
}

void Writer::assignOutputSectionIndices() {
  // Assign final output section indices, and assign each chunk to its output
  // section.
  uint32_t Idx = 1;
  for (OutputSection *OS : OutputSections) {
    OS->SectionIndex = Idx;
    for (Chunk *C : OS->Chunks)
      C->setOutputSectionIdx(Idx);
    ++Idx;
  }

  // Merge chunks are containers of chunks, so assign those an output section
  // too.
  for (MergeChunk *MC : MergeChunk::Instances)
    if (MC)
      for (SectionChunk *SC : MC->Sections)
        if (SC && SC->Live)
          SC->setOutputSectionIdx(MC->getOutputSectionIdx());
}

size_t Writer::addEntryToStringTable(StringRef Str) {
  assert(Str.size() > COFF::NameSize);
  size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field
  Strtab.insert(Strtab.end(), Str.begin(), Str.end());
  Strtab.push_back('\0');
  return OffsetOfEntry;
}

Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
  coff_symbol16 Sym;
  switch (Def->kind()) {
  case Symbol::DefinedAbsoluteKind:
    Sym.Value = Def->getRVA();
    Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
    break;
  case Symbol::DefinedSyntheticKind:
    // Relative symbols are unrepresentable in a COFF symbol table.
    return None;
  default: {
    // Don't write symbols that won't be written to the output to the symbol
    // table.
    Chunk *C = Def->getChunk();
    if (!C)
      return None;
    OutputSection *OS = C->getOutputSection();
    if (!OS)
      return None;

    Sym.Value = Def->getRVA() - OS->getRVA();
    Sym.SectionNumber = OS->SectionIndex;
    break;
  }
  }

  StringRef Name = Def->getName();
  if (Name.size() > COFF::NameSize) {
    Sym.Name.Offset.Zeroes = 0;
    Sym.Name.Offset.Offset = addEntryToStringTable(Name);
  } else {
    memset(Sym.Name.ShortName, 0, COFF::NameSize);
    memcpy(Sym.Name.ShortName, Name.data(), Name.size());
  }

  if (auto *D = dyn_cast<DefinedCOFF>(Def)) {
    COFFSymbolRef Ref = D->getCOFFSymbol();
    Sym.Type = Ref.getType();
    Sym.StorageClass = Ref.getStorageClass();
  } else {
    Sym.Type = IMAGE_SYM_TYPE_NULL;
    Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
  }
  Sym.NumberOfAuxSymbols = 0;
  return Sym;
}

void Writer::createSymbolAndStringTable() {
  // PE/COFF images are limited to 8 byte section names. Longer names can be
  // supported by writing a non-standard string table, but this string table is
  // not mapped at runtime and the long names will therefore be inaccessible.
  // link.exe always truncates section names to 8 bytes, whereas binutils always
  // preserves long section names via the string table. LLD adopts a hybrid
  // solution where discardable sections have long names preserved and
  // non-discardable sections have their names truncated, to ensure that any
  // section which is mapped at runtime also has its name mapped at runtime.
  for (OutputSection *Sec : OutputSections) {
    if (Sec->Name.size() <= COFF::NameSize)
      continue;
    if ((Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)
      continue;
    Sec->setStringTableOff(addEntryToStringTable(Sec->Name));
  }

  if (Config->DebugDwarf || Config->DebugSymtab) {
    for (ObjFile *File : ObjFile::Instances) {
      for (Symbol *B : File->getSymbols()) {
        auto *D = dyn_cast_or_null<Defined>(B);
        if (!D || D->WrittenToSymtab)
          continue;
        D->WrittenToSymtab = true;

        if (Optional<coff_symbol16> Sym = createSymbol(D))
          OutputSymtab.push_back(*Sym);
      }
    }
  }

  if (OutputSymtab.empty() && Strtab.empty())
    return;

  // We position the symbol table to be adjacent to the end of the last section.
  uint64_t FileOff = FileSize;
  PointerToSymbolTable = FileOff;
  FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
  FileOff += 4 + Strtab.size();
  FileSize = alignTo(FileOff, Config->FileAlign);
}

void Writer::mergeSections() {
  if (!PdataSec->Chunks.empty()) {
    FirstPdata = PdataSec->Chunks.front();
    LastPdata = PdataSec->Chunks.back();
  }

  for (auto &P : Config->Merge) {
    StringRef ToName = P.second;
    if (P.first == ToName)
      continue;
    StringSet<> Names;
    while (1) {
      if (!Names.insert(ToName).second)
        fatal("/merge: cycle found for section '" + P.first + "'");
      auto I = Config->Merge.find(ToName);
      if (I == Config->Merge.end())
        break;
      ToName = I->second;
    }
    OutputSection *From = findSection(P.first);
    OutputSection *To = findSection(ToName);
    if (!From)
      continue;
    if (!To) {
      From->Name = ToName;
      continue;
    }
    To->merge(From);
  }
}

// Visits all sections to assign incremental, non-overlapping RVAs and
// file offsets.
void Writer::assignAddresses() {
  SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
                  sizeof(data_directory) * NumberOfDataDirectory +
                  sizeof(coff_section) * OutputSections.size();
  SizeOfHeaders +=
      Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
  SizeOfHeaders = alignTo(SizeOfHeaders, Config->FileAlign);
  uint64_t RVA = PageSize; // The first page is kept unmapped.
  FileSize = SizeOfHeaders;

  for (OutputSection *Sec : OutputSections) {
    if (Sec == RelocSec)
      addBaserels();
    uint64_t RawSize = 0, VirtualSize = 0;
    Sec->Header.VirtualAddress = RVA;

    // If /FUNCTIONPADMIN is used, functions are padded in order to create a
    // hotpatchable image.
    const bool IsCodeSection =
        (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE) &&
        (Sec->Header.Characteristics & IMAGE_SCN_MEM_READ) &&
        (Sec->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE);
    uint32_t Padding = IsCodeSection ? Config->FunctionPadMin : 0;

    for (Chunk *C : Sec->Chunks) {
      if (Padding && C->isHotPatchable())
        VirtualSize += Padding;
      VirtualSize = alignTo(VirtualSize, C->getAlignment());
      C->setRVA(RVA + VirtualSize);
      VirtualSize += C->getSize();
      if (C->hasData())
        RawSize = alignTo(VirtualSize, Config->FileAlign);
    }
    if (VirtualSize > UINT32_MAX)
      error("section larger than 4 GiB: " + Sec->Name);
    Sec->Header.VirtualSize = VirtualSize;
    Sec->Header.SizeOfRawData = RawSize;
    if (RawSize != 0)
      Sec->Header.PointerToRawData = FileSize;
    RVA += alignTo(VirtualSize, PageSize);
    FileSize += alignTo(RawSize, Config->FileAlign);
  }
  SizeOfImage = alignTo(RVA, PageSize);

  // Assign addresses to sections in MergeChunks.
  for (MergeChunk *MC : MergeChunk::Instances)
    if (MC)
      MC->assignSubsectionRVAs();
}

template <typename PEHeaderTy> void Writer::writeHeader() {
  // Write DOS header. For backwards compatibility, the first part of a PE/COFF
  // executable consists of an MS-DOS MZ executable. If the executable is run
  // under DOS, that program gets run (usually to just print an error message).
  // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
  // the PE header instead.
  uint8_t *Buf = Buffer->getBufferStart();
  auto *DOS = reinterpret_cast<dos_header *>(Buf);
  Buf += sizeof(dos_header);
  DOS->Magic[0] = 'M';
  DOS->Magic[1] = 'Z';
  DOS->UsedBytesInTheLastPage = DOSStubSize % 512;
  DOS->FileSizeInPages = divideCeil(DOSStubSize, 512);
  DOS->HeaderSizeInParagraphs = sizeof(dos_header) / 16;

  DOS->AddressOfRelocationTable = sizeof(dos_header);
  DOS->AddressOfNewExeHeader = DOSStubSize;

  // Write DOS program.
  memcpy(Buf, DOSProgram, sizeof(DOSProgram));
  Buf += sizeof(DOSProgram);

  // Write PE magic
  memcpy(Buf, PEMagic, sizeof(PEMagic));
  Buf += sizeof(PEMagic);

  // Write COFF header
  auto *COFF = reinterpret_cast<coff_file_header *>(Buf);
  Buf += sizeof(*COFF);
  COFF->Machine = Config->Machine;
  COFF->NumberOfSections = OutputSections.size();
  COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
  if (Config->LargeAddressAware)
    COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
  if (!Config->is64())
    COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
  if (Config->DLL)
    COFF->Characteristics |= IMAGE_FILE_DLL;
  if (!Config->Relocatable)
    COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
  if (Config->SwaprunCD)
    COFF->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
  if (Config->SwaprunNet)
    COFF->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP;
  COFF->SizeOfOptionalHeader =
      sizeof(PEHeaderTy) + sizeof(data_directory) * NumberOfDataDirectory;

  // Write PE header
  auto *PE = reinterpret_cast<PEHeaderTy *>(Buf);
  Buf += sizeof(*PE);
  PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;

  // If {Major,Minor}LinkerVersion is left at 0.0, then for some
  // reason signing the resulting PE file with Authenticode produces a
  // signature that fails to validate on Windows 7 (but is OK on 10).
  // Set it to 14.0, which is what VS2015 outputs, and which avoids
  // that problem.
  PE->MajorLinkerVersion = 14;
  PE->MinorLinkerVersion = 0;

  PE->ImageBase = Config->ImageBase;
  PE->SectionAlignment = PageSize;
  PE->FileAlignment = Config->FileAlign;
  PE->MajorImageVersion = Config->MajorImageVersion;
  PE->MinorImageVersion = Config->MinorImageVersion;
  PE->MajorOperatingSystemVersion = Config->MajorOSVersion;
  PE->MinorOperatingSystemVersion = Config->MinorOSVersion;
  PE->MajorSubsystemVersion = Config->MajorOSVersion;
  PE->MinorSubsystemVersion = Config->MinorOSVersion;
  PE->Subsystem = Config->Subsystem;
  PE->SizeOfImage = SizeOfImage;
  PE->SizeOfHeaders = SizeOfHeaders;
  if (!Config->NoEntry) {
    Defined *Entry = cast<Defined>(Config->Entry);
    PE->AddressOfEntryPoint = Entry->getRVA();
    // Pointer to thumb code must have the LSB set, so adjust it.
    if (Config->Machine == ARMNT)
      PE->AddressOfEntryPoint |= 1;
  }
  PE->SizeOfStackReserve = Config->StackReserve;
  PE->SizeOfStackCommit = Config->StackCommit;
  PE->SizeOfHeapReserve = Config->HeapReserve;
  PE->SizeOfHeapCommit = Config->HeapCommit;
  if (Config->AppContainer)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER;
  if (Config->DynamicBase)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
  if (Config->HighEntropyVA)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
  if (!Config->AllowBind)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
  if (Config->NxCompat)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
  if (!Config->AllowIsolation)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
  if (Config->GuardCF != GuardCFLevel::Off)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
  if (Config->IntegrityCheck)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
  if (SetNoSEHCharacteristic)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
  if (Config->TerminalServerAware)
    PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
  PE->NumberOfRvaAndSize = NumberOfDataDirectory;
  if (TextSec->getVirtualSize()) {
    PE->BaseOfCode = TextSec->getRVA();
    PE->SizeOfCode = TextSec->getRawSize();
  }
  PE->SizeOfInitializedData = getSizeOfInitializedData();

  // Write data directory
  auto *Dir = reinterpret_cast<data_directory *>(Buf);
  Buf += sizeof(*Dir) * NumberOfDataDirectory;
  if (!Config->Exports.empty()) {
    Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata.getRVA();
    Dir[EXPORT_TABLE].Size = Edata.getSize();
  }
  if (ImportTableStart) {
    Dir[IMPORT_TABLE].RelativeVirtualAddress = ImportTableStart->getRVA();
    Dir[IMPORT_TABLE].Size = ImportTableSize;
  }
  if (IATStart) {
    Dir[IAT].RelativeVirtualAddress = IATStart->getRVA();
    Dir[IAT].Size = IATSize;
  }
  if (RsrcSec->getVirtualSize()) {
    Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA();
    Dir[RESOURCE_TABLE].Size = RsrcSec->getVirtualSize();
  }
  if (FirstPdata) {
    Dir[EXCEPTION_TABLE].RelativeVirtualAddress = FirstPdata->getRVA();
    Dir[EXCEPTION_TABLE].Size =
        LastPdata->getRVA() + LastPdata->getSize() - FirstPdata->getRVA();
  }
  if (RelocSec->getVirtualSize()) {
    Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = RelocSec->getRVA();
    Dir[BASE_RELOCATION_TABLE].Size = RelocSec->getVirtualSize();
  }
  if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {
    if (Defined *B = dyn_cast<Defined>(Sym)) {
      Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
      Dir[TLS_TABLE].Size = Config->is64()
                                ? sizeof(object::coff_tls_directory64)
                                : sizeof(object::coff_tls_directory32);
    }
  }
  if (DebugDirectory) {
    Dir[DEBUG_DIRECTORY].RelativeVirtualAddress = DebugDirectory->getRVA();
    Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize();
  }
  if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {
    if (auto *B = dyn_cast<DefinedRegular>(Sym)) {
      SectionChunk *SC = B->getChunk();
      assert(B->getRVA() >= SC->getRVA());
      uint64_t OffsetInChunk = B->getRVA() - SC->getRVA();
      if (!SC->hasData() || OffsetInChunk + 4 > SC->getSize())
        fatal("_load_config_used is malformed");

      ArrayRef<uint8_t> SecContents = SC->getContents();
      uint32_t LoadConfigSize =
          *reinterpret_cast<const ulittle32_t *>(&SecContents[OffsetInChunk]);
      if (OffsetInChunk + LoadConfigSize > SC->getSize())
        fatal("_load_config_used is too large");
      Dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = B->getRVA();
      Dir[LOAD_CONFIG_TABLE].Size = LoadConfigSize;
    }
  }
  if (!DelayIdata.empty()) {
    Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
        DelayIdata.getDirRVA();
    Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize();
  }

  // Write section table
  for (OutputSection *Sec : OutputSections) {
    Sec->writeHeaderTo(Buf);
    Buf += sizeof(coff_section);
  }
  SectionTable = ArrayRef<uint8_t>(
      Buf - OutputSections.size() * sizeof(coff_section), Buf);

  if (OutputSymtab.empty() && Strtab.empty())
    return;

  COFF->PointerToSymbolTable = PointerToSymbolTable;
  uint32_t NumberOfSymbols = OutputSymtab.size();
  COFF->NumberOfSymbols = NumberOfSymbols;
  auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(
      Buffer->getBufferStart() + COFF->PointerToSymbolTable);
  for (size_t I = 0; I != NumberOfSymbols; ++I)
    SymbolTable[I] = OutputSymtab[I];
  // Create the string table, it follows immediately after the symbol table.
  // The first 4 bytes is length including itself.
  Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);
  write32le(Buf, Strtab.size() + 4);
  if (!Strtab.empty())
    memcpy(Buf + 4, Strtab.data(), Strtab.size());
}

void Writer::openFile(StringRef Path) {
  Buffer = CHECK(
      FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable),
      "failed to open " + Path);
}

void Writer::createSEHTable() {
  // Set the no SEH characteristic on x86 binaries unless we find exception
  // handlers.
  SetNoSEHCharacteristic = true;

  SymbolRVASet Handlers;
  for (ObjFile *File : ObjFile::Instances) {
    // FIXME: We should error here instead of earlier unless /safeseh:no was
    // passed.
    if (!File->hasSafeSEH())
      return;

    markSymbolsForRVATable(File, File->getSXDataChunks(), Handlers);
  }

  // Remove the "no SEH" characteristic if all object files were built with
  // safeseh, we found some exception handlers, and there is a load config in
  // the object.
  SetNoSEHCharacteristic =
      Handlers.empty() || !Symtab->findUnderscore("_load_config_used");

  maybeAddRVATable(std::move(Handlers), "__safe_se_handler_table",
                   "__safe_se_handler_count");
}

// Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set
// cannot contain duplicates. Therefore, the set is uniqued by Chunk and the
// symbol's offset into that Chunk.
static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) {
  Chunk *C = S->getChunk();
  if (auto *SC = dyn_cast<SectionChunk>(C))
    C = SC->Repl; // Look through ICF replacement.
  uint32_t Off = S->getRVA() - (C ? C->getRVA() : 0);
  RVASet.insert({C, Off});
}

// Given a symbol, add it to the GFIDs table if it is a live, defined, function
// symbol in an executable section.
static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms,
                                         Symbol *S) {
  if (!S)
    return;

  switch (S->kind()) {
  case Symbol::DefinedLocalImportKind:
  case Symbol::DefinedImportDataKind:
    // Defines an __imp_ pointer, so it is data, so it is ignored.
    break;
  case Symbol::DefinedCommonKind:
    // Common is always data, so it is ignored.
    break;
  case Symbol::DefinedAbsoluteKind:
  case Symbol::DefinedSyntheticKind:
    // Absolute is never code, synthetic generally isn't and usually isn't
    // determinable.
    break;
  case Symbol::LazyKind:
  case Symbol::UndefinedKind:
    // Undefined symbols resolve to zero, so they don't have an RVA. Lazy
    // symbols shouldn't have relocations.
    break;

  case Symbol::DefinedImportThunkKind:
    // Thunks are always code, include them.
    addSymbolToRVASet(AddressTakenSyms, cast<Defined>(S));
    break;

  case Symbol::DefinedRegularKind: {
    // This is a regular, defined, symbol from a COFF file. Mark the symbol as
    // address taken if the symbol type is function and it's in an executable
    // section.
    auto *D = cast<DefinedRegular>(S);
    if (D->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
      SectionChunk *SC = dyn_cast<SectionChunk>(D->getChunk());
      if (SC && SC->Live &&
          SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)
        addSymbolToRVASet(AddressTakenSyms, D);
    }
    break;
  }
  }
}

// Visit all relocations from all section contributions of this object file and
// mark the relocation target as address-taken.
static void markSymbolsWithRelocations(ObjFile *File,
                                       SymbolRVASet &UsedSymbols) {
  for (Chunk *C : File->getChunks()) {
    // We only care about live section chunks. Common chunks and other chunks
    // don't generally contain relocations.
    SectionChunk *SC = dyn_cast<SectionChunk>(C);
    if (!SC || !SC->Live)
      continue;

    for (const coff_relocation &Reloc : SC->getRelocs()) {
      if (Config->Machine == I386 && Reloc.Type == COFF::IMAGE_REL_I386_REL32)
        // Ignore relative relocations on x86. On x86_64 they can't be ignored
        // since they're also used to compute absolute addresses.
        continue;

      Symbol *Ref = SC->File->getSymbol(Reloc.SymbolTableIndex);
      maybeAddAddressTakenFunction(UsedSymbols, Ref);
    }
  }
}

// Create the guard function id table. This is a table of RVAs of all
// address-taken functions. It is sorted and uniqued, just like the safe SEH
// table.
void Writer::createGuardCFTables() {
  SymbolRVASet AddressTakenSyms;
  SymbolRVASet LongJmpTargets;
  for (ObjFile *File : ObjFile::Instances) {
    // If the object was compiled with /guard:cf, the address taken symbols
    // are in .gfids$y sections, and the longjmp targets are in .gljmp$y
    // sections. If the object was not compiled with /guard:cf, we assume there
    // were no setjmp targets, and that all code symbols with relocations are
    // possibly address-taken.
    if (File->hasGuardCF()) {
      markSymbolsForRVATable(File, File->getGuardFidChunks(), AddressTakenSyms);
      markSymbolsForRVATable(File, File->getGuardLJmpChunks(), LongJmpTargets);
    } else {
      markSymbolsWithRelocations(File, AddressTakenSyms);
    }
  }

  // Mark the image entry as address-taken.
  if (Config->Entry)
    maybeAddAddressTakenFunction(AddressTakenSyms, Config->Entry);

  // Mark exported symbols in executable sections as address-taken.
  for (Export &E : Config->Exports)
    maybeAddAddressTakenFunction(AddressTakenSyms, E.Sym);

  // Ensure sections referenced in the gfid table are 16-byte aligned.
  for (const ChunkAndOffset &C : AddressTakenSyms)
    if (C.InputChunk->getAlignment() < 16)
      C.InputChunk->setAlignment(16);

  maybeAddRVATable(std::move(AddressTakenSyms), "__guard_fids_table",
                   "__guard_fids_count");

  // Add the longjmp target table unless the user told us not to.
  if (Config->GuardCF == GuardCFLevel::Full)
    maybeAddRVATable(std::move(LongJmpTargets), "__guard_longjmp_table",
                     "__guard_longjmp_count");

  // Set __guard_flags, which will be used in the load config to indicate that
  // /guard:cf was enabled.
  uint32_t GuardFlags = uint32_t(coff_guard_flags::CFInstrumented) |
                        uint32_t(coff_guard_flags::HasFidTable);
  if (Config->GuardCF == GuardCFLevel::Full)
    GuardFlags |= uint32_t(coff_guard_flags::HasLongJmpTable);
  Symbol *FlagSym = Symtab->findUnderscore("__guard_flags");
  cast<DefinedAbsolute>(FlagSym)->setVA(GuardFlags);
}

// Take a list of input sections containing symbol table indices and add those
// symbols to an RVA table. The challenge is that symbol RVAs are not known and
// depend on the table size, so we can't directly build a set of integers.
void Writer::markSymbolsForRVATable(ObjFile *File,
                                    ArrayRef<SectionChunk *> SymIdxChunks,
                                    SymbolRVASet &TableSymbols) {
  for (SectionChunk *C : SymIdxChunks) {
    // Skip sections discarded by linker GC. This comes up when a .gfids section
    // is associated with something like a vtable and the vtable is discarded.
    // In this case, the associated gfids section is discarded, and we don't
    // mark the virtual member functions as address-taken by the vtable.
    if (!C->Live)
      continue;

    // Validate that the contents look like symbol table indices.
    ArrayRef<uint8_t> Data = C->getContents();
    if (Data.size() % 4 != 0) {
      warn("ignoring " + C->getSectionName() +
           " symbol table index section in object " + toString(File));
      continue;
    }

    // Read each symbol table index and check if that symbol was included in the
    // final link. If so, add it to the table symbol set.
    ArrayRef<ulittle32_t> SymIndices(
        reinterpret_cast<const ulittle32_t *>(Data.data()), Data.size() / 4);
    ArrayRef<Symbol *> ObjSymbols = File->getSymbols();
    for (uint32_t SymIndex : SymIndices) {
      if (SymIndex >= ObjSymbols.size()) {
        warn("ignoring invalid symbol table index in section " +
             C->getSectionName() + " in object " + toString(File));
        continue;
      }
      if (Symbol *S = ObjSymbols[SymIndex]) {
        if (S->isLive())
          addSymbolToRVASet(TableSymbols, cast<Defined>(S));
      }
    }
  }
}

// Replace the absolute table symbol with a synthetic symbol pointing to
// TableChunk so that we can emit base relocations for it and resolve section
// relative relocations.
void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,
                              StringRef CountSym) {
  if (TableSymbols.empty())
    return;

  RVATableChunk *TableChunk = make<RVATableChunk>(std::move(TableSymbols));
  RdataSec->addChunk(TableChunk);

  Symbol *T = Symtab->findUnderscore(TableSym);
  Symbol *C = Symtab->findUnderscore(CountSym);
  replaceSymbol<DefinedSynthetic>(T, T->getName(), TableChunk);
  cast<DefinedAbsolute>(C)->setVA(TableChunk->getSize() / 4);
}

// MinGW specific. Gather all relocations that are imported from a DLL even
// though the code didn't expect it to, produce the table that the runtime
// uses for fixing them up, and provide the synthetic symbols that the
// runtime uses for finding the table.
void Writer::createRuntimePseudoRelocs() {
  std::vector<RuntimePseudoReloc> Rels;

  for (Chunk *C : Symtab->getChunks()) {
    auto *SC = dyn_cast<SectionChunk>(C);
    if (!SC || !SC->Live)
      continue;
    SC->getRuntimePseudoRelocs(Rels);
  }

  if (!Rels.empty())
    log("Writing " + Twine(Rels.size()) + " runtime pseudo relocations");
  PseudoRelocTableChunk *Table = make<PseudoRelocTableChunk>(Rels);
  RdataSec->addChunk(Table);
  EmptyChunk *EndOfList = make<EmptyChunk>();
  RdataSec->addChunk(EndOfList);

  Symbol *HeadSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__");
  Symbol *EndSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__");
  replaceSymbol<DefinedSynthetic>(HeadSym, HeadSym->getName(), Table);
  replaceSymbol<DefinedSynthetic>(EndSym, EndSym->getName(), EndOfList);
}

// MinGW specific.
// The MinGW .ctors and .dtors lists have sentinels at each end;
// a (uintptr_t)-1 at the start and a (uintptr_t)0 at the end.
// There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__
// and __DTOR_LIST__ respectively.
void Writer::insertCtorDtorSymbols() {
  AbsolutePointerChunk *CtorListHead = make<AbsolutePointerChunk>(-1);
  AbsolutePointerChunk *CtorListEnd = make<AbsolutePointerChunk>(0);
  AbsolutePointerChunk *DtorListHead = make<AbsolutePointerChunk>(-1);
  AbsolutePointerChunk *DtorListEnd = make<AbsolutePointerChunk>(0);
  CtorsSec->insertChunkAtStart(CtorListHead);
  CtorsSec->addChunk(CtorListEnd);
  DtorsSec->insertChunkAtStart(DtorListHead);
  DtorsSec->addChunk(DtorListEnd);

  Symbol *CtorListSym = Symtab->findUnderscore("__CTOR_LIST__");
  Symbol *DtorListSym = Symtab->findUnderscore("__DTOR_LIST__");
  replaceSymbol<DefinedSynthetic>(CtorListSym, CtorListSym->getName(),
                                  CtorListHead);
  replaceSymbol<DefinedSynthetic>(DtorListSym, DtorListSym->getName(),
                                  DtorListHead);
}

// Handles /section options to allow users to overwrite
// section attributes.
void Writer::setSectionPermissions() {
  for (auto &P : Config->Section) {
    StringRef Name = P.first;
    uint32_t Perm = P.second;
    for (OutputSection *Sec : OutputSections)
      if (Sec->Name == Name)
        Sec->setPermissions(Perm);
  }
}

// Write section contents to a mmap'ed file.
void Writer::writeSections() {
  // Record the number of sections to apply section index relocations
  // against absolute symbols. See applySecIdx in Chunks.cpp..
  DefinedAbsolute::NumOutputSections = OutputSections.size();

  uint8_t *Buf = Buffer->getBufferStart();
  for (OutputSection *Sec : OutputSections) {
    uint8_t *SecBuf = Buf + Sec->getFileOff();
    // Fill gaps between functions in .text with INT3 instructions
    // instead of leaving as NUL bytes (which can be interpreted as
    // ADD instructions).
    if (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE)
      memset(SecBuf, 0xCC, Sec->getRawSize());
    parallelForEach(Sec->Chunks, [&](Chunk *C) {
      C->writeTo(SecBuf + C->getRVA() - Sec->getRVA());
    });
  }
}

void Writer::writeBuildId() {
  // There are two important parts to the build ID.
  // 1) If building with debug info, the COFF debug directory contains a
  //    timestamp as well as a Guid and Age of the PDB.
  // 2) In all cases, the PE COFF file header also contains a timestamp.
  // For reproducibility, instead of a timestamp we want to use a hash of the
  // PE contents.
  if (Config->Debug) {
    assert(BuildId && "BuildId is not set!");
    // BuildId->BuildId was filled in when the PDB was written.
  }

  // At this point the only fields in the COFF file which remain unset are the
  // "timestamp" in the COFF file header, and the ones in the coff debug
  // directory.  Now we can hash the file and write that hash to the various
  // timestamp fields in the file.
  StringRef OutputFileData(
      reinterpret_cast<const char *>(Buffer->getBufferStart()),
      Buffer->getBufferSize());

  uint32_t Timestamp = Config->Timestamp;
  uint64_t Hash = 0;
  bool GenerateSyntheticBuildId =
      Config->MinGW && Config->Debug && Config->PDBPath.empty();

  if (Config->Repro || GenerateSyntheticBuildId)
    Hash = xxHash64(OutputFileData);

  if (Config->Repro)
    Timestamp = static_cast<uint32_t>(Hash);

  if (GenerateSyntheticBuildId) {
    // For MinGW builds without a PDB file, we still generate a build id
    // to allow associating a crash dump to the executable.
    BuildId->BuildId->PDB70.CVSignature = OMF::Signature::PDB70;
    BuildId->BuildId->PDB70.Age = 1;
    memcpy(BuildId->BuildId->PDB70.Signature, &Hash, 8);
    // xxhash only gives us 8 bytes, so put some fixed data in the other half.
    memcpy(&BuildId->BuildId->PDB70.Signature[8], "LLD PDB.", 8);
  }

  if (DebugDirectory)
    DebugDirectory->setTimeDateStamp(Timestamp);

  uint8_t *Buf = Buffer->getBufferStart();
  Buf += DOSStubSize + sizeof(PEMagic);
  object::coff_file_header *CoffHeader =
      reinterpret_cast<coff_file_header *>(Buf);
  CoffHeader->TimeDateStamp = Timestamp;
}

// Sort .pdata section contents according to PE/COFF spec 5.5.
void Writer::sortExceptionTable() {
  if (!FirstPdata)
    return;
  // We assume .pdata contains function table entries only.
  auto BufAddr = [&](Chunk *C) {
    OutputSection *OS = C->getOutputSection();
    return Buffer->getBufferStart() + OS->getFileOff() + C->getRVA() -
           OS->getRVA();
  };
  uint8_t *Begin = BufAddr(FirstPdata);
  uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize();
  if (Config->Machine == AMD64) {
    struct Entry { ulittle32_t Begin, End, Unwind; };
    parallelSort(
        MutableArrayRef<Entry>((Entry *)Begin, (Entry *)End),
        [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
    return;
  }
  if (Config->Machine == ARMNT || Config->Machine == ARM64) {
    struct Entry { ulittle32_t Begin, Unwind; };
    parallelSort(
        MutableArrayRef<Entry>((Entry *)Begin, (Entry *)End),
        [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
    return;
  }
  errs() << "warning: don't know how to handle .pdata.\n";
}

// The CRT section contains, among other things, the array of function
// pointers that initialize every global variable that is not trivially
// constructed. The CRT calls them one after the other prior to invoking
// main().
//
// As per C++ spec, 3.6.2/2.3,
// "Variables with ordered initialization defined within a single
// translation unit shall be initialized in the order of their definitions
// in the translation unit"
//
// It is therefore critical to sort the chunks containing the function
// pointers in the order that they are listed in the object file (top to
// bottom), otherwise global objects might not be initialized in the
// correct order.
void Writer::sortCRTSectionChunks(std::vector<Chunk *> &Chunks) {
  auto SectionChunkOrder = [](const Chunk *A, const Chunk *B) {
    auto SA = dyn_cast<SectionChunk>(A);
    auto SB = dyn_cast<SectionChunk>(B);
    assert(SA && SB && "Non-section chunks in CRT section!");

    StringRef SAObj = SA->File->MB.getBufferIdentifier();
    StringRef SBObj = SB->File->MB.getBufferIdentifier();

    return SAObj == SBObj && SA->getSectionNumber() < SB->getSectionNumber();
  };
  llvm::stable_sort(Chunks, SectionChunkOrder);

  if (Config->Verbose) {
    for (auto &C : Chunks) {
      auto SC = dyn_cast<SectionChunk>(C);
      log("  " + SC->File->MB.getBufferIdentifier().str() +
          ", SectionID: " + Twine(SC->getSectionNumber()));
    }
  }
}

OutputSection *Writer::findSection(StringRef Name) {
  for (OutputSection *Sec : OutputSections)
    if (Sec->Name == Name)
      return Sec;
  return nullptr;
}

uint32_t Writer::getSizeOfInitializedData() {
  uint32_t Res = 0;
  for (OutputSection *S : OutputSections)
    if (S->Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
      Res += S->getRawSize();
  return Res;
}

// Add base relocations to .reloc section.
void Writer::addBaserels() {
  if (!Config->Relocatable)
    return;
  RelocSec->Chunks.clear();
  std::vector<Baserel> V;
  for (OutputSection *Sec : OutputSections) {
    if (Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
      continue;
    // Collect all locations for base relocations.
    for (Chunk *C : Sec->Chunks)
      C->getBaserels(&V);
    // Add the addresses to .reloc section.
    if (!V.empty())
      addBaserelBlocks(V);
    V.clear();
  }
}

// Add addresses to .reloc section. Note that addresses are grouped by page.
void Writer::addBaserelBlocks(std::vector<Baserel> &V) {
  const uint32_t Mask = ~uint32_t(PageSize - 1);
  uint32_t Page = V[0].RVA & Mask;
  size_t I = 0, J = 1;
  for (size_t E = V.size(); J < E; ++J) {
    uint32_t P = V[J].RVA & Mask;
    if (P == Page)
      continue;
    RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
    I = J;
    Page = P;
  }
  if (I == J)
    return;
  RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));
}

PartialSection *Writer::createPartialSection(StringRef Name,
                                             uint32_t OutChars) {
  PartialSection *&PSec = PartialSections[{Name, OutChars}];
  if (PSec)
    return PSec;
  PSec = make<PartialSection>(Name, OutChars);
  return PSec;
}

PartialSection *Writer::findPartialSection(StringRef Name, uint32_t OutChars) {
  auto It = PartialSections.find({Name, OutChars});
  if (It != PartialSections.end())
    return It->second;
  return nullptr;
}
