Move OutputSectionBase and derived classes out of Writer.cpp.

The file was getting a bit too big and OutputSection is a central enough
concept in ELF linking to justify its own file.

llvm-svn: 248214
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 00d9989..5253bac 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -8,17 +8,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "Writer.h"
-#include "Chunks.h"
 #include "Config.h"
-#include "Error.h"
-#include "Symbols.h"
+#include "OutputSections.h"
 #include "SymbolTable.h"
 
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/MC/StringTableBuilder.h"
 #include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 using namespace llvm::ELF;
@@ -39,525 +33,6 @@
 static const int VAStart = 0x10000;
 
 namespace {
-// OutputSection represents a section in an output file. It's a
-// container of chunks. OutputSection and Chunk are 1:N relationship.
-// Chunks cannot belong to more than one OutputSections. The writer
-// creates multiple OutputSections and assign them unique,
-// non-overlapping file offsets and VAs.
-template <bool Is64Bits> class OutputSectionBase {
-public:
-  typedef
-      typename std::conditional<Is64Bits, Elf64_Dyn, Elf32_Dyn>::type Elf_Dyn;
-  typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
-  typedef
-      typename std::conditional<Is64Bits, Elf64_Shdr, Elf32_Shdr>::type HeaderT;
-
-  OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_flags)
-      : Name(Name) {
-    memset(&Header, 0, sizeof(HeaderT));
-    Header.sh_type = sh_type;
-    Header.sh_flags = sh_flags;
-  }
-  void setVA(uintX_t VA) { Header.sh_addr = VA; }
-  uintX_t getVA() const { return Header.sh_addr; }
-  void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
-  template <endianness E>
-  void writeHeaderTo(typename ELFFile<ELFType<E, Is64Bits>>::Elf_Shdr *SHdr);
-  StringRef getName() { return Name; }
-  void setNameOffset(uintX_t Offset) { Header.sh_name = Offset; }
-
-  unsigned getSectionIndex() const { return SectionIndex; }
-  void setSectionIndex(unsigned I) { SectionIndex = I; }
-
-  // Returns the size of the section in the output file.
-  uintX_t getSize() { return Header.sh_size; }
-  void setSize(uintX_t Val) { Header.sh_size = Val; }
-  uintX_t getFlags() { return Header.sh_flags; }
-  uintX_t getFileOff() { return Header.sh_offset; }
-  uintX_t getAlign() {
-    // The ELF spec states that a value of 0 means the section has no alignment
-    // constraits.
-    return std::max<uintX_t>(Header.sh_addralign, 1);
-  }
-  uint32_t getType() { return Header.sh_type; }
-
-  static unsigned getAddrSize() { return Is64Bits ? 8 : 4; }
-
-  virtual void finalize() {}
-  virtual void writeTo(uint8_t *Buf) = 0;
-
-protected:
-  StringRef Name;
-  HeaderT Header;
-  unsigned SectionIndex;
-  ~OutputSectionBase() = default;
-};
-template <class ELFT> class SymbolTableSection;
-
-template <class ELFT> struct DynamicReloc {
-  typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
-  const InputSection<ELFT> &C;
-  const Elf_Rel &RI;
-};
-
-static bool relocNeedsPLT(uint32_t Type) {
-  switch (Type) {
-  default:
-    return false;
-  case R_X86_64_PLT32:
-    return true;
-  }
-}
-
-static bool relocNeedsGOT(uint32_t Type) {
-  if (relocNeedsPLT(Type))
-    return true;
-  switch (Type) {
-  default:
-    return false;
-  case R_X86_64_GOTPCREL:
-    return true;
-  }
-}
-
-template <class ELFT>
-class GotSection final : public OutputSectionBase<ELFT::Is64Bits> {
-  typedef OutputSectionBase<ELFT::Is64Bits> Base;
-  typedef typename Base::uintX_t uintX_t;
-
-public:
-  GotSection()
-      : OutputSectionBase<ELFT::Is64Bits>(".got", SHT_PROGBITS,
-                                          SHF_ALLOC | SHF_WRITE) {
-    this->Header.sh_addralign = this->getAddrSize();
-  }
-  void finalize() override {
-    this->Header.sh_size = Entries.size() * this->getAddrSize();
-  }
-  void writeTo(uint8_t *Buf) override {}
-  void addEntry(SymbolBody *Sym) {
-    Sym->setGotIndex(Entries.size());
-    Entries.push_back(Sym);
-  }
-  bool empty() const { return Entries.empty(); }
-  uintX_t getEntryAddr(const SymbolBody &B) const {
-    return this->getVA() + B.getGotIndex() * this->getAddrSize();
-  }
-
-private:
-  std::vector<const SymbolBody *> Entries;
-};
-
-template <class ELFT>
-class PltSection final : public OutputSectionBase<ELFT::Is64Bits> {
-  typedef OutputSectionBase<ELFT::Is64Bits> Base;
-  typedef typename Base::uintX_t uintX_t;
-
-public:
-  PltSection(const GotSection<ELFT> &GotSec)
-      : OutputSectionBase<ELFT::Is64Bits>(".plt", SHT_PROGBITS,
-                                          SHF_ALLOC | SHF_EXECINSTR),
-        GotSec(GotSec) {
-    this->Header.sh_addralign = 16;
-  }
-  void finalize() override {
-    this->Header.sh_size = Entries.size() * EntrySize;
-  }
-  void writeTo(uint8_t *Buf) override {
-    uintptr_t Start = reinterpret_cast<uintptr_t>(Buf);
-    ArrayRef<uint8_t> Jmp = {0xff, 0x25}; // jmpq *val(%rip)
-    for (const SymbolBody *E : Entries) {
-      uintptr_t InstPos = reinterpret_cast<uintptr_t>(Buf);
-
-      memcpy(Buf, Jmp.data(), Jmp.size());
-      Buf += Jmp.size();
-
-      uintptr_t OffsetInPLT = (InstPos + 6) - Start;
-      uintptr_t Delta = GotSec.getEntryAddr(*E) - (this->getVA() + OffsetInPLT);
-      assert(isInt<32>(Delta));
-      support::endian::write32le(Buf, Delta);
-      Buf += 4;
-
-      *Buf = 0x90; // nop
-      ++Buf;
-      *Buf = 0x90; // nop
-      ++Buf;
-    }
-  }
-  void addEntry(SymbolBody *Sym) {
-    Sym->setPltIndex(Entries.size());
-    Entries.push_back(Sym);
-  }
-  bool empty() const { return Entries.empty(); }
-  uintX_t getEntryAddr(const SymbolBody &B) const {
-    return this->getVA() + B.getPltIndex() * EntrySize;
-  }
-
-  static const unsigned EntrySize = 8;
-
-private:
-  std::vector<const SymbolBody *> Entries;
-  const GotSection<ELFT> &GotSec;
-};
-
-template <class ELFT>
-class RelocationSection final : public OutputSectionBase<ELFT::Is64Bits> {
-  typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
-  typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
-
-public:
-  RelocationSection(SymbolTableSection<ELFT> &DynSymSec,
-                    const GotSection<ELFT> &GotSec, bool IsRela)
-      : OutputSectionBase<ELFT::Is64Bits>(IsRela ? ".rela.dyn" : ".rel.dyn",
-                                          IsRela ? SHT_RELA : SHT_REL,
-                                          SHF_ALLOC),
-        DynSymSec(DynSymSec), GotSec(GotSec), IsRela(IsRela) {
-    this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
-    this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
-  }
-
-  void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(Reloc); }
-  void finalize() override {
-    this->Header.sh_link = DynSymSec.getSectionIndex();
-    this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
-  }
-  void writeTo(uint8_t *Buf) override {
-    auto *P = reinterpret_cast<Elf_Rela *>(Buf);
-    bool IsMips64EL = Relocs[0].C.getFile()->getObj()->isMips64EL();
-    for (const DynamicReloc<ELFT> &Rel : Relocs) {
-      const InputSection<ELFT> &C = Rel.C;
-      const Elf_Rel &RI = Rel.RI;
-      OutputSection<ELFT> *Out = C.getOutputSection();
-      uint32_t SymIndex = RI.getSymbol(IsMips64EL);
-      const SymbolBody *Body = C.getFile()->getSymbolBody(SymIndex);
-      uint32_t Type = RI.getType(IsMips64EL);
-      if (relocNeedsGOT(Type)) {
-        P->r_offset = GotSec.getEntryAddr(*Body);
-        P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
-                            R_X86_64_GLOB_DAT, IsMips64EL);
-      } else {
-        P->r_offset = RI.r_offset + C.getOutputSectionOff() + Out->getVA();
-        P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type,
-                            IsMips64EL);
-        if (IsRela)
-          P->r_addend = static_cast<const Elf_Rela &>(RI).r_addend;
-      }
-
-      ++P;
-    }
-  }
-  bool hasRelocs() const { return !Relocs.empty(); }
-  bool isRela() const { return IsRela; }
-
-private:
-  std::vector<DynamicReloc<ELFT>> Relocs;
-  SymbolTableSection<ELFT> &DynSymSec;
-  const GotSection<ELFT> &GotSec;
-  const bool IsRela;
-};
-}
-
-template <class ELFT>
-class lld::elf2::OutputSection final
-    : public OutputSectionBase<ELFT::Is64Bits> {
-public:
-  typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
-  typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
-  typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
-  typedef typename ELFFile<ELFT>::Elf_Rel Elf_Rel;
-  typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
-  OutputSection(const PltSection<ELFT> &PltSec, const GotSection<ELFT> &GotSec,
-                StringRef Name, uint32_t sh_type, uintX_t sh_flags)
-      : OutputSectionBase<ELFT::Is64Bits>(Name, sh_type, sh_flags),
-        PltSec(PltSec), GotSec(GotSec) {}
-
-  void addChunk(InputSection<ELFT> *C);
-  void writeTo(uint8_t *Buf) override;
-
-  template <bool isRela>
-  void relocate(uint8_t *Buf,
-                iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,
-                const ObjectFile<ELFT> &File, uintX_t BaseAddr);
-
-  void relocateOne(uint8_t *Buf, const Elf_Rela &Rel, uint32_t Type,
-                   uintX_t BaseAddr, uintX_t SymVA);
-  void relocateOne(uint8_t *Buf, const Elf_Rel &Rel, uint32_t Type,
-                   uintX_t BaseAddr, uintX_t SymVA);
-
-private:
-  std::vector<InputSection<ELFT> *> Chunks;
-  const PltSection<ELFT> &PltSec;
-  const GotSection<ELFT> &GotSec;
-};
-
-namespace {
-template <bool Is64Bits>
-class InterpSection final : public OutputSectionBase<Is64Bits> {
-public:
-  InterpSection()
-      : OutputSectionBase<Is64Bits>(".interp", SHT_PROGBITS, SHF_ALLOC) {
-    this->Header.sh_size = Config->DynamicLinker.size() + 1;
-    this->Header.sh_addralign = 1;
-  }
-
-  void writeTo(uint8_t *Buf) override {
-    memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
-  }
-};
-
-template <bool Is64Bits>
-class StringTableSection final : public OutputSectionBase<Is64Bits> {
-public:
-  typedef typename OutputSectionBase<Is64Bits>::uintX_t uintX_t;
-  StringTableSection(bool Dynamic)
-      : OutputSectionBase<Is64Bits>(Dynamic ? ".dynstr" : ".strtab", SHT_STRTAB,
-                                    Dynamic ? (uintX_t)SHF_ALLOC : 0),
-        Dynamic(Dynamic) {
-    this->Header.sh_addralign = 1;
-  }
-
-  void add(StringRef S) { StrTabBuilder.add(S); }
-  size_t getFileOff(StringRef S) const { return StrTabBuilder.getOffset(S); }
-  StringRef data() const { return StrTabBuilder.data(); }
-  void writeTo(uint8_t *Buf) override;
-
-  void finalize() override {
-    StrTabBuilder.finalize(StringTableBuilder::ELF);
-    this->Header.sh_size = StrTabBuilder.data().size();
-  }
-
-  bool isDynamic() const { return Dynamic; }
-
-private:
-  const bool Dynamic;
-  llvm::StringTableBuilder StrTabBuilder;
-};
-
-template <class ELFT> class Writer;
-
-template <class ELFT>
-class SymbolTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
-public:
-  typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
-  typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym;
-  typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
-  typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
-  SymbolTableSection(Writer<ELFT> &W, SymbolTable &Table,
-                     StringTableSection<ELFT::Is64Bits> &StrTabSec)
-      : OutputSectionBase<ELFT::Is64Bits>(
-            StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
-            StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
-            StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0),
-        Table(Table), StrTabSec(StrTabSec), W(W) {
-    typedef OutputSectionBase<ELFT::Is64Bits> Base;
-    typename Base::HeaderT &Header = this->Header;
-
-    Header.sh_entsize = sizeof(Elf_Sym);
-    Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
-  }
-
-  void finalize() override {
-    this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
-    this->Header.sh_link = StrTabSec.getSectionIndex();
-    this->Header.sh_info = NumLocals + 1;
-  }
-
-  void writeTo(uint8_t *Buf) override;
-
-  const SymbolTable &getSymTable() const { return Table; }
-
-  void addSymbol(StringRef Name, bool isLocal = false) {
-    StrTabSec.add(Name);
-    ++NumVisible;
-    if (isLocal)
-      ++NumLocals;
-  }
-
-  StringTableSection<ELFT::Is64Bits> &getStrTabSec() { return StrTabSec; }
-  unsigned getNumSymbols() const { return NumVisible + 1; }
-
-private:
-  SymbolTable &Table;
-  StringTableSection<ELFT::Is64Bits> &StrTabSec;
-  unsigned NumVisible = 0;
-  unsigned NumLocals = 0;
-  const Writer<ELFT> &W;
-};
-
-template <class ELFT>
-class HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
-  typedef typename ELFFile<ELFT>::Elf_Word Elf_Word;
-
-public:
-  HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
-      : OutputSectionBase<ELFT::Is64Bits>(".hash", SHT_HASH, SHF_ALLOC),
-        DynSymSec(DynSymSec) {
-    this->Header.sh_entsize = sizeof(Elf_Word);
-    this->Header.sh_addralign = sizeof(Elf_Word);
-  }
-
-  void addSymbol(SymbolBody *S) {
-    StringRef Name = S->getName();
-    DynSymSec.addSymbol(Name);
-    Hashes.push_back(hash(Name));
-    S->setDynamicSymbolTableIndex(Hashes.size());
-  }
-
-  void finalize() override {
-    this->Header.sh_link = DynSymSec.getSectionIndex();
-
-    assert(DynSymSec.getNumSymbols() == Hashes.size() + 1);
-    unsigned NumEntries = 2;                 // nbucket and nchain.
-    NumEntries += DynSymSec.getNumSymbols(); // The chain entries.
-
-    // Create as many buckets as there are symbols.
-    // FIXME: This is simplistic. We can try to optimize it, but implementing
-    // support for SHT_GNU_HASH is probably even more profitable.
-    NumEntries += DynSymSec.getNumSymbols();
-    this->Header.sh_size = NumEntries * sizeof(Elf_Word);
-  }
-
-  void writeTo(uint8_t *Buf) override {
-    unsigned NumSymbols = DynSymSec.getNumSymbols();
-    auto *P = reinterpret_cast<Elf_Word *>(Buf);
-    *P++ = NumSymbols; // nbucket
-    *P++ = NumSymbols; // nchain
-
-    Elf_Word *Buckets = P;
-    Elf_Word *Chains = P + NumSymbols;
-
-    for (unsigned I = 1; I < NumSymbols; ++I) {
-      uint32_t Hash = Hashes[I - 1] % NumSymbols;
-      Chains[I] = Buckets[Hash];
-      Buckets[Hash] = I;
-    }
-  }
-
-  SymbolTableSection<ELFT> &getDynSymSec() { return DynSymSec; }
-
-private:
-  uint32_t hash(StringRef Name) {
-    uint32_t H = 0;
-    for (char C : Name) {
-      H = (H << 4) + C;
-      uint32_t G = H & 0xf0000000;
-      if (G)
-        H ^= G >> 24;
-      H &= ~G;
-    }
-    return H;
-  }
-  SymbolTableSection<ELFT> &DynSymSec;
-  std::vector<uint32_t> Hashes;
-};
-
-template <class ELFT>
-class DynamicSection final : public OutputSectionBase<ELFT::Is64Bits> {
-  typedef OutputSectionBase<ELFT::Is64Bits> Base;
-  typedef typename Base::HeaderT HeaderT;
-  typedef typename Base::Elf_Dyn Elf_Dyn;
-
-public:
-  DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
-                 RelocationSection<ELFT> &RelaDynSec)
-      : OutputSectionBase<ELFT::Is64Bits>(".dynamic", SHT_DYNAMIC,
-                                          SHF_ALLOC | SHF_WRITE),
-        HashSec(HashSec), DynSymSec(HashSec.getDynSymSec()),
-        DynStrSec(DynSymSec.getStrTabSec()), RelaDynSec(RelaDynSec),
-        SymTab(SymTab) {
-    typename Base::HeaderT &Header = this->Header;
-    Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
-    Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
-  }
-
-  void finalize() override {
-    typename Base::HeaderT &Header = this->Header;
-    Header.sh_link = DynStrSec.getSectionIndex();
-
-    unsigned NumEntries = 0;
-    if (RelaDynSec.hasRelocs()) {
-      ++NumEntries; // DT_RELA / DT_REL
-      ++NumEntries; // DT_RELASZ / DTRELSZ
-    }
-    ++NumEntries; // DT_SYMTAB
-    ++NumEntries; // DT_STRTAB
-    ++NumEntries; // DT_STRSZ
-    ++NumEntries; // DT_HASH
-
-    StringRef RPath = Config->RPath;
-    if (!RPath.empty()) {
-      ++NumEntries; // DT_RUNPATH
-      DynStrSec.add(RPath);
-    }
-
-    const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
-        SymTab.getSharedFiles();
-    for (const std::unique_ptr<SharedFileBase> &File : SharedFiles)
-      DynStrSec.add(File->getName());
-    NumEntries += SharedFiles.size();
-
-    ++NumEntries; // DT_NULL
-
-    Header.sh_size = NumEntries * Header.sh_entsize;
-  }
-
-  void writeTo(uint8_t *Buf) override {
-    auto *P = reinterpret_cast<Elf_Dyn *>(Buf);
-
-    if (RelaDynSec.hasRelocs()) {
-      bool IsRela = RelaDynSec.isRela();
-      P->d_tag = IsRela ? DT_RELA : DT_REL;
-      P->d_un.d_ptr = RelaDynSec.getVA();
-      ++P;
-
-      P->d_tag = IsRela ? DT_RELASZ : DT_RELSZ;
-      P->d_un.d_val = RelaDynSec.getSize();
-      ++P;
-    }
-
-    P->d_tag = DT_SYMTAB;
-    P->d_un.d_ptr = DynSymSec.getVA();
-    ++P;
-
-    P->d_tag = DT_STRTAB;
-    P->d_un.d_ptr = DynStrSec.getVA();
-    ++P;
-
-    P->d_tag = DT_STRSZ;
-    P->d_un.d_val = DynStrSec.data().size();
-    ++P;
-
-    P->d_tag = DT_HASH;
-    P->d_un.d_ptr = HashSec.getVA();
-    ++P;
-
-    StringRef RPath = Config->RPath;
-    if (!RPath.empty()) {
-      P->d_tag = DT_RUNPATH;
-      P->d_un.d_val = DynStrSec.getFileOff(RPath);
-      ++P;
-    }
-
-    const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles =
-        SymTab.getSharedFiles();
-    for (const std::unique_ptr<SharedFileBase> &File : SharedFiles) {
-      P->d_tag = DT_NEEDED;
-      P->d_un.d_val = DynStrSec.getFileOff(File->getName());
-      ++P;
-    }
-
-    P->d_tag = DT_NULL;
-    P->d_un.d_val = 0;
-    ++P;
-  }
-
-private:
-  HashTableSection<ELFT> &HashSec;
-  SymbolTableSection<ELFT> &DynSymSec;
-  StringTableSection<ELFT::Is64Bits> &DynStrSec;
-  RelocationSection<ELFT> &RelaDynSec;
-  SymbolTable &SymTab;
-};
 
 static uint32_t convertSectionFlagsToPHDRFlags(uint64_t Flags) {
   uint32_t Ret = PF_R;
@@ -621,16 +96,11 @@
   typedef typename ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
   typedef typename ELFFile<ELFT>::Elf_Rela Elf_Rela;
   Writer(SymbolTable *T)
-      : SymTabSec(*this, *T, StrTabSec), DynSymSec(*this, *T, DynStrSec),
+      : SymTabSec(*T, StrTabSec), DynSymSec(*T, DynStrSec),
         RelaDynSec(DynSymSec, GotSec, T->shouldUseRela()), PltSec(GotSec),
         HashSec(DynSymSec), DynamicSec(*T, HashSec, RelaDynSec) {}
   void run();
 
-  const OutputSection<ELFT> &getBSS() const {
-    assert(BSSSec);
-    return *BSSSec;
-  }
-
 private:
   void createSections();
   template <bool isRela>
@@ -669,8 +139,8 @@
   StringTableSection<ELFT::Is64Bits> StrTabSec = { /*dynamic=*/false };
   StringTableSection<ELFT::Is64Bits> DynStrSec = { /*dynamic=*/true };
 
-  SymbolTableSection<ELFT> SymTabSec;
-  SymbolTableSection<ELFT> DynSymSec;
+  lld::elf2::SymbolTableSection<ELFT> SymTabSec;
+  lld::elf2::SymbolTableSection<ELFT> DynSymSec;
 
   RelocationSection<ELFT> RelaDynSec;
 
@@ -712,174 +182,6 @@
 }
 
 template <class ELFT>
-void OutputSection<ELFT>::addChunk(InputSection<ELFT> *C) {
-  Chunks.push_back(C);
-  C->setOutputSection(this);
-  uint32_t Align = C->getAlign();
-  if (Align > this->Header.sh_addralign)
-    this->Header.sh_addralign = Align;
-
-  uintX_t Off = this->Header.sh_size;
-  Off = RoundUpToAlignment(Off, Align);
-  C->setOutputSectionOff(Off);
-  Off += C->getSize();
-  this->Header.sh_size = Off;
-}
-
-template <class ELFT>
-static typename ELFFile<ELFT>::uintX_t
-getSymVA(const DefinedRegular<ELFT> *DR) {
-  const InputSection<ELFT> *SC = &DR->Section;
-  OutputSection<ELFT> *OS = SC->getOutputSection();
-  return OS->getVA() + SC->getOutputSectionOff() + DR->Sym.st_value;
-}
-
-template <class ELFT>
-static typename ELFFile<ELFT>::uintX_t
-getLocalSymVA(const typename ELFFile<ELFT>::Elf_Sym *Sym,
-              const ObjectFile<ELFT> &File) {
-  uint32_t SecIndex = Sym->st_shndx;
-
-  if (SecIndex == SHN_XINDEX)
-    SecIndex = File.getObj()->getExtendedSymbolTableIndex(
-        Sym, File.getSymbolTable(), File.getSymbolTableShndx());
-  ArrayRef<InputSection<ELFT> *> Chunks = File.getChunks();
-  InputSection<ELFT> *Section = Chunks[SecIndex];
-  OutputSection<ELFT> *Out = Section->getOutputSection();
-  return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;
-}
-
-template <class ELFT>
-void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rel &Rel,
-                                      uint32_t Type, uintX_t BaseAddr,
-                                      uintX_t SymVA) {
-  uintX_t Offset = Rel.r_offset;
-  uint8_t *Location = Buf + Offset;
-  switch (Type) {
-  case R_386_32:
-    support::endian::write32le(Location, SymVA);
-    break;
-  default:
-    llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
-    break;
-  }
-}
-
-template <class ELFT>
-void OutputSection<ELFT>::relocateOne(uint8_t *Buf, const Elf_Rela &Rel,
-                                      uint32_t Type, uintX_t BaseAddr,
-                                      uintX_t SymVA) {
-  uintX_t Offset = Rel.r_offset;
-  uint8_t *Location = Buf + Offset;
-  switch (Type) {
-  case R_X86_64_PC32:
-    support::endian::write32le(Location,
-                               SymVA + (Rel.r_addend - (BaseAddr + Offset)));
-    break;
-  case R_X86_64_64:
-    support::endian::write64le(Location, SymVA + Rel.r_addend);
-    break;
-  case R_X86_64_32: {
-  case R_X86_64_32S:
-    uint64_t VA = SymVA + Rel.r_addend;
-    if (Type == R_X86_64_32 && !isUInt<32>(VA))
-      error("R_X86_64_32 out of range");
-    else if (!isInt<32>(VA))
-      error("R_X86_64_32S out of range");
-
-    support::endian::write32le(Location, VA);
-    break;
-  }
-  default:
-    llvm::errs() << Twine("unrecognized reloc ") + Twine(Type) << '\n';
-    break;
-  }
-}
-
-template <class ELFT>
-template <bool isRela>
-void OutputSection<ELFT>::relocate(
-    uint8_t *Buf, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels,
-    const ObjectFile<ELFT> &File, uintX_t BaseAddr) {
-  typedef Elf_Rel_Impl<ELFT, isRela> RelType;
-  bool IsMips64EL = File.getObj()->isMips64EL();
-  for (const RelType &RI : Rels) {
-    uint32_t SymIndex = RI.getSymbol(IsMips64EL);
-    uint32_t Type = RI.getType(IsMips64EL);
-    uintX_t SymVA;
-
-    // Handle relocations for local symbols -- they never get
-    // resolved so we don't allocate a SymbolBody.
-    const Elf_Shdr *SymTab = File.getSymbolTable();
-    if (SymIndex < SymTab->sh_info) {
-      const Elf_Sym *Sym = File.getObj()->getRelocationSymbol(&RI, SymTab);
-      if (!Sym)
-        continue;
-      SymVA = getLocalSymVA(Sym, File);
-    } else {
-      const SymbolBody *Body = File.getSymbolBody(SymIndex);
-      if (!Body)
-        continue;
-      switch (Body->kind()) {
-      case SymbolBody::DefinedRegularKind:
-        SymVA = getSymVA<ELFT>(cast<DefinedRegular<ELFT>>(Body));
-        break;
-      case SymbolBody::DefinedAbsoluteKind:
-        SymVA = cast<DefinedAbsolute<ELFT>>(Body)->Sym.st_value;
-        break;
-      case SymbolBody::DefinedCommonKind: {
-        auto *DC = cast<DefinedCommon<ELFT>>(Body);
-        SymVA = DC->OutputSec->getVA() + DC->OffsetInBSS;
-        break;
-      }
-      case SymbolBody::SharedKind:
-        if (relocNeedsPLT(Type)) {
-          SymVA = PltSec.getEntryAddr(*Body);
-          Type = R_X86_64_PC32;
-        } else if (relocNeedsGOT(Type)) {
-          SymVA = GotSec.getEntryAddr(*Body);
-          Type = R_X86_64_PC32;
-        } else {
-          continue;
-        }
-        break;
-      case SymbolBody::UndefinedKind:
-        assert(Body->isWeak() && "Undefined symbol reached writer");
-        SymVA = 0;
-        break;
-      case SymbolBody::LazyKind:
-        llvm_unreachable("Lazy symbol reached writer");
-      }
-    }
-
-    relocateOne(Buf, RI, Type, BaseAddr, SymVA);
-  }
-}
-
-template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
-  for (InputSection<ELFT> *C : Chunks) {
-    C->writeTo(Buf);
-    const ObjectFile<ELFT> *File = C->getFile();
-    ELFFile<ELFT> *EObj = File->getObj();
-    uint8_t *Base = Buf + C->getOutputSectionOff();
-    uintX_t BaseAddr = this->getVA() + C->getOutputSectionOff();
-    // Iterate over all relocation sections that apply to this section.
-    for (const Elf_Shdr *RelSec : C->RelocSections) {
-      if (RelSec->sh_type == SHT_RELA)
-        relocate(Base, EObj->relas(RelSec), *File, BaseAddr);
-      else
-        relocate(Base, EObj->rels(RelSec), *File, BaseAddr);
-    }
-  }
-}
-
-template <bool Is64Bits>
-void StringTableSection<Is64Bits>::writeTo(uint8_t *Buf) {
-  StringRef Data = StrTabBuilder.data();
-  memcpy(Buf, Data.data(), Data.size());
-}
-
-template <class ELFT>
 static int compareSym(const typename ELFFile<ELFT>::Elf_Sym *A,
                       const typename ELFFile<ELFT>::Elf_Sym *B) {
   uint32_t AN = A->st_name;
@@ -888,126 +190,6 @@
   return AN - BN;
 }
 
-static bool includeInSymtab(const SymbolBody &B) {
-  if (B.isLazy())
-    return false;
-  if (!B.isUsedInRegularObj())
-    return false;
-  uint8_t V = B.getMostConstrainingVisibility();
-  if (V != STV_DEFAULT && V != STV_PROTECTED)
-    return false;
-  return true;
-}
-
-template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
-  const OutputSection<ELFT> *Out = nullptr;
-  const InputSection<ELFT> *Section = nullptr;
-  Buf += sizeof(Elf_Sym);
-
-  // All symbols with STB_LOCAL binding precede the weak and global symbols.
-  // .dynsym only contains global symbols.
-  if (!Config->DiscardAll && !StrTabSec.isDynamic()) {
-    for (const std::unique_ptr<ObjectFileBase> &FileB :
-         Table.getObjectFiles()) {
-      auto &File = cast<ObjectFile<ELFT>>(*FileB);
-      Elf_Sym_Range Syms = File.getLocalSymbols();
-      for (const Elf_Sym &Sym : Syms) {
-        auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
-        uint32_t SecIndex = Sym.st_shndx;
-        ErrorOr<StringRef> SymName = Sym.getName(File.getStringTable());
-        if (Config->DiscardLocals && SymName->startswith(".L"))
-          continue;
-        ESym->st_name = (SymName) ? StrTabSec.getFileOff(*SymName) : 0;
-        ESym->st_size = Sym.st_size;
-        ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
-        if (SecIndex == SHN_XINDEX)
-          SecIndex = File.getObj()->getExtendedSymbolTableIndex(
-              &Sym, File.getSymbolTable(), File.getSymbolTableShndx());
-        ArrayRef<InputSection<ELFT> *> Chunks = File.getChunks();
-        Section = Chunks[SecIndex];
-        assert(Section != nullptr);
-        Out = Section->getOutputSection();
-        assert(Out != nullptr);
-        ESym->st_shndx = Out->getSectionIndex();
-        ESym->st_value =
-            Out->getVA() + Section->getOutputSectionOff() + Sym.st_value;
-        Buf += sizeof(Elf_Sym);
-      }
-    }
-  }
-
-  for (auto &P : Table.getSymbols()) {
-    StringRef Name = P.first;
-    Symbol *Sym = P.second;
-    SymbolBody *Body = Sym->Body;
-    if (!includeInSymtab(*Body))
-      continue;
-    const Elf_Sym &InputSym = cast<ELFSymbolBody<ELFT>>(Body)->Sym;
-
-    auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
-    ESym->st_name = StrTabSec.getFileOff(Name);
-
-    Out = nullptr;
-    Section = nullptr;
-
-    switch (Body->kind()) {
-    case SymbolBody::DefinedRegularKind:
-      Section = &cast<DefinedRegular<ELFT>>(Body)->Section;
-      break;
-    case SymbolBody::DefinedCommonKind:
-      Out = &W.getBSS();
-      break;
-    case SymbolBody::UndefinedKind:
-    case SymbolBody::DefinedAbsoluteKind:
-    case SymbolBody::SharedKind:
-      break;
-    case SymbolBody::LazyKind:
-      llvm_unreachable("Lazy symbol got to output symbol table!");
-    }
-
-    ESym->setBindingAndType(InputSym.getBinding(), InputSym.getType());
-    ESym->st_size = InputSym.st_size;
-    ESym->setVisibility(Body->getMostConstrainingVisibility());
-    if (InputSym.isAbsolute()) {
-      ESym->st_shndx = SHN_ABS;
-      ESym->st_value = InputSym.st_value;
-    }
-
-    if (Section)
-      Out = Section->getOutputSection();
-
-    if (Out) {
-      ESym->st_shndx = Out->getSectionIndex();
-      uintX_t VA = Out->getVA();
-      if (Section)
-        VA += Section->getOutputSectionOff();
-      if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
-        VA += C->OffsetInBSS;
-      else
-        VA += InputSym.st_value;
-      ESym->st_value = VA;
-    }
-
-    Buf += sizeof(Elf_Sym);
-  }
-}
-
-template <bool Is64Bits>
-template <endianness E>
-void OutputSectionBase<Is64Bits>::writeHeaderTo(
-    typename ELFFile<ELFType<E, Is64Bits>>::Elf_Shdr *SHdr) {
-  SHdr->sh_name = Header.sh_name;
-  SHdr->sh_type = Header.sh_type;
-  SHdr->sh_flags = Header.sh_flags;
-  SHdr->sh_addr = Header.sh_addr;
-  SHdr->sh_offset = Header.sh_offset;
-  SHdr->sh_size = Header.sh_size;
-  SHdr->sh_link = Header.sh_link;
-  SHdr->sh_info = Header.sh_info;
-  SHdr->sh_addralign = Header.sh_addralign;
-  SHdr->sh_entsize = Header.sh_entsize;
-}
-
 namespace {
 template <bool Is64Bits> struct SectionKey {
   typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
@@ -1163,6 +345,9 @@
   }
 
   BSSSec = getSection(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
+  SymTabSec.setBssSec(BSSSec);
+  DynSymSec.setBssSec(BSSSec);
+
   // Sort the common symbols by alignment as an heuristic to pack them better.
   std::stable_sort(CommonSymbols.begin(), CommonSymbols.end(), cmpAlign<ELFT>);
   uintX_t Off = BSSSec->getSize();