[lld] r248214 - Move OutputSectionBase and derived classes out of Writer.cpp.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 21 14:38:09 PDT 2015


Author: rafael
Date: Mon Sep 21 16:38:08 2015
New Revision: 248214

URL: http://llvm.org/viewvc/llvm-project?rev=248214&view=rev
Log:
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.

Added:
    lld/trunk/ELF/OutputSections.cpp
    lld/trunk/ELF/OutputSections.h
Modified:
    lld/trunk/ELF/CMakeLists.txt
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=248214&r1=248213&r2=248214&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Mon Sep 21 16:38:08 2015
@@ -8,6 +8,7 @@ add_llvm_library(lldELF2
   DriverUtils.cpp
   Error.cpp
   InputFiles.cpp
+  OutputSections.cpp
   SymbolTable.cpp
   Symbols.cpp
   Writer.cpp

Added: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=248214&view=auto
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (added)
+++ lld/trunk/ELF/OutputSections.cpp Mon Sep 21 16:38:08 2015
@@ -0,0 +1,586 @@
+//===- OutputSections.cpp -------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OutputSections.h"
+#include "Config.h"
+#include "InputFiles.h"
+#include "Symbols.h"
+#include "SymbolTable.h"
+
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf2;
+
+template <bool Is64Bits>
+OutputSectionBase<Is64Bits>::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;
+}
+
+template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) {
+  Sym->setGotIndex(Entries.size());
+  Entries.push_back(Sym);
+}
+
+template <class ELFT>
+typename GotSection<ELFT>::uintX_t
+GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
+  return this->getVA() + B.getGotIndex() * this->getAddrSize();
+}
+
+template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
+  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;
+  }
+}
+
+template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody *Sym) {
+  Sym->setPltIndex(Entries.size());
+  Entries.push_back(Sym);
+}
+
+template <class ELFT>
+typename PltSection<ELFT>::uintX_t
+PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
+  return this->getVA() + B.getPltIndex() * EntrySize;
+}
+
+bool lld::elf2::relocNeedsPLT(uint32_t Type) {
+  switch (Type) {
+  default:
+    return false;
+  case R_X86_64_PLT32:
+    return true;
+  }
+}
+
+bool lld::elf2::relocNeedsGOT(uint32_t Type) {
+  if (relocNeedsPLT(Type))
+    return true;
+  switch (Type) {
+  default:
+    return false;
+  case R_X86_64_GOTPCREL:
+    return true;
+  }
+}
+
+template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
+  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;
+  }
+}
+
+template <class ELFT> void RelocationSection<ELFT>::finalize() {
+  this->Header.sh_link = DynSymSec.getSectionIndex();
+  this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
+}
+
+template <bool Is64Bits>
+InterpSection<Is64Bits>::InterpSection()
+    : OutputSectionBase<Is64Bits>(".interp", llvm::ELF::SHT_PROGBITS,
+                                  llvm::ELF::SHF_ALLOC) {
+  this->Header.sh_size = Config->DynamicLinker.size() + 1;
+  this->Header.sh_addralign = 1;
+}
+
+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;
+}
+
+template <bool Is64Bits> void InterpSection<Is64Bits>::writeTo(uint8_t *Buf) {
+  memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
+}
+
+template <class ELFT> void HashTableSection<ELFT>::addSymbol(SymbolBody *S) {
+  StringRef Name = S->getName();
+  DynSymSec.addSymbol(Name);
+  Hashes.push_back(hash(Name));
+  S->setDynamicSymbolTableIndex(Hashes.size());
+}
+
+template <class ELFT> void DynamicSection<ELFT>::finalize() {
+  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;
+}
+
+template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {
+  typedef typename std::conditional<ELFT::Is64Bits, Elf64_Dyn, Elf32_Dyn>::type
+      Elf_Dyn;
+  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;
+}
+
+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>
+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>
+typename ELFFile<ELFT>::uintX_t
+lld::elf2::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>
+typename ELFFile<ELFT>::uintX_t
+lld::elf2::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>
+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());
+}
+
+bool lld::elf2::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 = BssSec;
+      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);
+  }
+}
+
+namespace lld {
+namespace elf2 {
+template class OutputSectionBase<false>;
+template class OutputSectionBase<true>;
+
+template void OutputSectionBase<false>::writeHeaderTo<support::little>(
+    typename ELFFile<ELFType<support::little, false>>::Elf_Shdr *SHdr);
+template void OutputSectionBase<true>::writeHeaderTo<support::little>(
+    typename ELFFile<ELFType<support::little, true>>::Elf_Shdr *SHdr);
+template void OutputSectionBase<false>::writeHeaderTo<support::big>(
+    typename ELFFile<ELFType<support::big, false>>::Elf_Shdr *SHdr);
+template void OutputSectionBase<true>::writeHeaderTo<support::big>(
+    typename ELFFile<ELFType<support::big, true>>::Elf_Shdr *SHdr);
+
+template class GotSection<ELF32LE>;
+template class GotSection<ELF32BE>;
+template class GotSection<ELF64LE>;
+template class GotSection<ELF64BE>;
+
+template class PltSection<ELF32LE>;
+template class PltSection<ELF32BE>;
+template class PltSection<ELF64LE>;
+template class PltSection<ELF64BE>;
+
+template class RelocationSection<ELF32LE>;
+template class RelocationSection<ELF32BE>;
+template class RelocationSection<ELF64LE>;
+template class RelocationSection<ELF64BE>;
+
+template class InterpSection<false>;
+template class InterpSection<true>;
+
+template class HashTableSection<ELF32LE>;
+template class HashTableSection<ELF32BE>;
+template class HashTableSection<ELF64LE>;
+template class HashTableSection<ELF64BE>;
+
+template class DynamicSection<ELF32LE>;
+template class DynamicSection<ELF32BE>;
+template class DynamicSection<ELF64LE>;
+template class DynamicSection<ELF64BE>;
+
+template class OutputSection<ELF32LE>;
+template class OutputSection<ELF32BE>;
+template class OutputSection<ELF64LE>;
+template class OutputSection<ELF64BE>;
+
+template class StringTableSection<false>;
+template class StringTableSection<true>;
+
+template class SymbolTableSection<ELF32LE>;
+template class SymbolTableSection<ELF32BE>;
+template class SymbolTableSection<ELF64LE>;
+template class SymbolTableSection<ELF64BE>;
+
+template typename ELFFile<ELF32LE>::uintX_t
+getSymVA(const DefinedRegular<ELF32LE> *DR);
+
+template typename ELFFile<ELF32BE>::uintX_t
+getSymVA(const DefinedRegular<ELF32BE> *DR);
+
+template typename ELFFile<ELF64LE>::uintX_t
+getSymVA(const DefinedRegular<ELF64LE> *DR);
+
+template typename ELFFile<ELF64BE>::uintX_t
+getSymVA(const DefinedRegular<ELF64BE> *DR);
+}
+}

Added: lld/trunk/ELF/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=248214&view=auto
==============================================================================
--- lld/trunk/ELF/OutputSections.h (added)
+++ lld/trunk/ELF/OutputSections.h Mon Sep 21 16:38:08 2015
@@ -0,0 +1,396 @@
+//===- OutputSections.h -----------------------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_OUTPUT_SECTIONS_H
+#define LLD_ELF_OUTPUT_SECTIONS_H
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Object/ELF.h"
+
+#include <type_traits>
+
+namespace lld {
+namespace elf2 {
+
+class SymbolBody;
+class SymbolTable;
+template <class ELFT> class SymbolTableSection;
+template <bool Is64Bits> class StringTableSection;
+template <class ELFT> class InputSection;
+template <class ELFT> class OutputSection;
+template <class ELFT> class ObjectFile;
+template <class ELFT> class DefinedRegular;
+
+bool relocNeedsPLT(uint32_t Type);
+bool relocNeedsGOT(uint32_t Type);
+
+template <class ELFT>
+typename llvm::object::ELFFile<ELFT>::uintX_t
+getSymVA(const DefinedRegular<ELFT> *DR);
+
+template <class ELFT>
+typename llvm::object::ELFFile<ELFT>::uintX_t
+getLocalSymVA(const typename llvm::object::ELFFile<ELFT>::Elf_Sym *Sym,
+              const ObjectFile<ELFT> &File);
+
+bool includeInSymtab(const SymbolBody &B);
+
+// 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, uint64_t, uint32_t>::type uintX_t;
+  typedef typename std::conditional<Is64Bits, llvm::ELF::Elf64_Shdr,
+                                    llvm::ELF::Elf32_Shdr>::type HeaderT;
+
+  OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t 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 <llvm::object::endianness E>
+  void writeHeaderTo(typename llvm::object::ELFFile<
+                     llvm::object::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 GotSection final : public OutputSectionBase<ELFT::Is64Bits> {
+  typedef OutputSectionBase<ELFT::Is64Bits> Base;
+  typedef typename Base::uintX_t uintX_t;
+
+public:
+  GotSection()
+      : OutputSectionBase<ELFT::Is64Bits>(".got", llvm::ELF::SHT_PROGBITS,
+                                          llvm::ELF::SHF_ALLOC |
+                                              llvm::ELF::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);
+  bool empty() const { return Entries.empty(); }
+  uintX_t getEntryAddr(const SymbolBody &B) const;
+
+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", llvm::ELF::SHT_PROGBITS,
+                                          llvm::ELF::SHF_ALLOC |
+                                              llvm::ELF::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;
+  void addEntry(SymbolBody *Sym);
+  bool empty() const { return Entries.empty(); }
+  uintX_t getEntryAddr(const SymbolBody &B) const;
+  static const unsigned EntrySize = 8;
+
+private:
+  std::vector<const SymbolBody *> Entries;
+  const GotSection<ELFT> &GotSec;
+};
+
+template <class ELFT> struct DynamicReloc {
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
+  const InputSection<ELFT> &C;
+  const Elf_Rel &RI;
+};
+
+template <class ELFT>
+class SymbolTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
+public:
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+  typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
+  SymbolTableSection(SymbolTable &Table,
+                     StringTableSection<ELFT::Is64Bits> &StrTabSec)
+      : OutputSectionBase<ELFT::Is64Bits>(
+            StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
+            StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM
+                                  : llvm::ELF::SHT_SYMTAB,
+            StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
+        Table(Table), StrTabSec(StrTabSec) {
+    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; }
+  void setBssSec(const OutputSection<ELFT> *V) { BssSec = V; }
+
+private:
+  SymbolTable &Table;
+  StringTableSection<ELFT::Is64Bits> &StrTabSec;
+  unsigned NumVisible = 0;
+  unsigned NumLocals = 0;
+  const OutputSection<ELFT> *BssSec = nullptr;
+};
+
+template <class ELFT>
+class RelocationSection final : public OutputSectionBase<ELFT::Is64Bits> {
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
+  typedef typename llvm::object::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 ? llvm::ELF::SHT_RELA
+                                                 : llvm::ELF::SHT_REL,
+                                          llvm::ELF::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;
+  void writeTo(uint8_t *Buf) override;
+  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 OutputSection final : public OutputSectionBase<ELFT::Is64Bits> {
+public:
+  typedef typename OutputSectionBase<ELFT::Is64Bits>::uintX_t uintX_t;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
+  typedef typename llvm::object::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,
+                llvm::iterator_range<
+                    const llvm::object::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;
+};
+
+template <bool Is64Bits>
+class InterpSection final : public OutputSectionBase<Is64Bits> {
+public:
+  InterpSection();
+
+  void writeTo(uint8_t *Buf);
+};
+
+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", llvm::ELF::SHT_STRTAB,
+            Dynamic ? (uintX_t)llvm::ELF::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(llvm::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 HashTableSection final : public OutputSectionBase<ELFT::Is64Bits> {
+  typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
+
+public:
+  HashTableSection(SymbolTableSection<ELFT> &DynSymSec)
+      : OutputSectionBase<ELFT::Is64Bits>(".hash", llvm::ELF::SHT_HASH,
+                                          llvm::ELF::SHF_ALLOC),
+        DynSymSec(DynSymSec) {
+    this->Header.sh_entsize = sizeof(Elf_Word);
+    this->Header.sh_addralign = sizeof(Elf_Word);
+  }
+
+  void addSymbol(SymbolBody *S);
+
+  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;
+
+public:
+  DynamicSection(SymbolTable &SymTab, HashTableSection<ELFT> &HashSec,
+                 RelocationSection<ELFT> &RelaDynSec)
+      : OutputSectionBase<ELFT::Is64Bits>(".dynamic", llvm::ELF::SHT_DYNAMIC,
+                                          llvm::ELF::SHF_ALLOC |
+                                              llvm::ELF::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;
+  void writeTo(uint8_t *Buf) override;
+
+private:
+  HashTableSection<ELFT> &HashSec;
+  SymbolTableSection<ELFT> &DynSymSec;
+  StringTableSection<ELFT::Is64Bits> &DynStrSec;
+  RelocationSection<ELFT> &RelaDynSec;
+  SymbolTable &SymTab;
+};
+}
+}
+#endif

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=248214&r1=248213&r2=248214&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Mon Sep 21 16:38:08 2015
@@ -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 PageSize = 4096;
 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 @@ public:
   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 @@ private:
   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 Writer<ELFT>:
 }
 
 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 @@ static int compareSym(const typename ELF
   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 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   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();




More information about the llvm-commits mailing list